Build 0.5.0
This commit is contained in:
parent
618c5fd3c5
commit
4663599ffe
|
@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.5.0 / 5.45.0] - 2020-12-01
|
||||
## [0.5.0 / 5.45.0] - 2020-12-06
|
||||
|
||||
### Added
|
||||
- added new notification window
|
||||
|
@ -27,6 +27,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- added icons to box option tabs
|
||||
- added box grouping
|
||||
- added new debug option "DebugTrace=y" to log debug output to the trace log
|
||||
- added check for updates to the new SandMan UI
|
||||
- added check for updates to the legacy SbieCtrl UI
|
||||
|
||||
### Changed
|
||||
- File migration limit can now be disabled by specifying "CopyLimitKb=-1"
|
||||
|
@ -35,6 +37,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- reworked sandbox dletion mechaism ofthe new UI
|
||||
- restructured sandbox options window
|
||||
- SbieDLL.dll can now be compiled with an up to date nitll.lib
|
||||
- improved automated driver self repair
|
||||
|
||||
### Fixed
|
||||
- fixed issues migrating files > 4GB
|
||||
|
@ -47,6 +50,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- fixed issues when a snapshot operation failed
|
||||
- fixed some special cases of IpcPath and WinClass in the new UI
|
||||
- fixed driver issues with WHQL passing compatybility testing
|
||||
- fixed issues with classical installer
|
||||
|
||||
|
||||
|
||||
|
@ -118,7 +122,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- fixed issue deleting sandbox when located on a drive directly
|
||||
|
||||
|
||||
|
||||
## [0.4.2 / 5.43.6] - 2020-10-10
|
||||
|
||||
### Added
|
||||
|
@ -130,7 +133,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
- fixed chrome 86+ compatybility bug with chroms own sandbox
|
||||
|
||||
|
||||
|
||||
## [0.4.1 / 5.43.5] - 2020-09-12
|
||||
|
||||
### Added
|
||||
|
|
|
@ -108,7 +108,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib;winhttp.lib</AdditionalDependencies>
|
||||
<EntryPointSymbol>
|
||||
</EntryPointSymbol>
|
||||
<IgnoreSpecificDefaultLibraries>uafxcw.lib</IgnoreSpecificDefaultLibraries>
|
||||
|
@ -126,7 +126,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib;winhttp.lib</AdditionalDependencies>
|
||||
<EntryPointSymbol>
|
||||
</EntryPointSymbol>
|
||||
<IgnoreSpecificDefaultLibraries>uafxcw.lib</IgnoreSpecificDefaultLibraries>
|
||||
|
@ -143,7 +143,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib;winhttp.lib</AdditionalDependencies>
|
||||
<EntryPointSymbol>
|
||||
</EntryPointSymbol>
|
||||
<IgnoreSpecificDefaultLibraries>uafxcw.lib</IgnoreSpecificDefaultLibraries>
|
||||
|
@ -158,7 +158,7 @@
|
|||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>uafxcw.lib;common.lib;SbieDll.lib;ntdll.lib;psapi.lib;wininet.lib;winhttp.lib</AdditionalDependencies>
|
||||
<EntryPointSymbol>
|
||||
</EntryPointSymbol>
|
||||
<IgnoreSpecificDefaultLibraries>uafxcw.lib</IgnoreSpecificDefaultLibraries>
|
||||
|
@ -167,6 +167,18 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\common\json\JSON.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\common\json\JSONValue.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\BoxOrder.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">NotUsing</PrecompiledHeader>
|
||||
|
@ -271,11 +283,16 @@
|
|||
<ClCompile Include="ThirdPartyDialog.cpp" />
|
||||
<ClCompile Include="ToolTipButton.cpp" />
|
||||
<ClCompile Include="TreePropSheet.cpp" />
|
||||
<ClCompile Include="UpdateDialog.cpp" />
|
||||
<ClCompile Include="Updater.cpp" />
|
||||
<ClCompile Include="UserSettings.cpp" />
|
||||
<ClCompile Include="ViewTemplateDialog.cpp" />
|
||||
<ClCompile Include="WindowTitleMap.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\common\json\JSON.h" />
|
||||
<ClInclude Include="..\..\common\json\JSONValue.h" />
|
||||
<ClInclude Include="..\..\common\my_version.h" />
|
||||
<ClInclude Include="..\common\BoxOrder.h" />
|
||||
<ClInclude Include="..\common\FontStore.h" />
|
||||
<ClInclude Include="..\common\Layout.h" />
|
||||
|
@ -331,6 +348,8 @@
|
|||
<ClInclude Include="ThirdPartyDialog.h" />
|
||||
<ClInclude Include="ToolTipButton.h" />
|
||||
<ClInclude Include="TreePropSheet.h" />
|
||||
<ClInclude Include="UpdateDialog.h" />
|
||||
<ClInclude Include="Updater.h" />
|
||||
<ClInclude Include="UserSettings.h" />
|
||||
<ClInclude Include="ViewTemplateDialog.h" />
|
||||
<ClInclude Include="WindowTitleMap.h" />
|
||||
|
@ -339,7 +358,6 @@
|
|||
<ResourceCompile Include="SbieControl.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\sbieweb\web\img\FrontPage\FrontPageAnimation.gif" />
|
||||
<None Include="..\res\background.png" />
|
||||
<None Include="..\res\bigex.ico" />
|
||||
<None Include="..\res\checkmark.png" />
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\res\xptheme.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AboutDialog.cpp" />
|
||||
<ClCompile Include="AlertDialog.cpp" />
|
||||
<ClCompile Include="AnimatedBitmap.cpp" />
|
||||
<ClCompile Include="AppPage.cpp" />
|
||||
<ClCompile Include="AutoPlay.cpp" />
|
||||
<ClCompile Include="BaseDialog.cpp" />
|
||||
<ClCompile Include="BorderGuard.cpp" />
|
||||
<ClCompile Include="Box.cpp" />
|
||||
<ClCompile Include="Boxes.cpp" />
|
||||
<ClCompile Include="BoxFile.cpp" />
|
||||
<ClCompile Include="BoxPage.cpp" />
|
||||
<ClCompile Include="BoxProc.cpp" />
|
||||
<ClCompile Include="CreateDialog.cpp" />
|
||||
<ClCompile Include="DeleteDialog.cpp" />
|
||||
<ClCompile Include="DisableForceDialog.cpp" />
|
||||
<ClCompile Include="FileListCtrl.cpp" />
|
||||
<ClCompile Include="FinderDialog.cpp" />
|
||||
<ClCompile Include="FindTool.c" />
|
||||
<ClCompile Include="FlashingButton.cpp" />
|
||||
<ClCompile Include="GettingStartedWizard.cpp" />
|
||||
<ClCompile Include="InitWait.cpp" />
|
||||
<ClCompile Include="LockConfigDialog.cpp" />
|
||||
<ClCompile Include="MenuXP.cpp" />
|
||||
<ClCompile Include="MenuXP_Draw.cpp" />
|
||||
<ClCompile Include="MessageDialog.cpp" />
|
||||
<ClCompile Include="MonitorDialog.cpp" />
|
||||
<ClCompile Include="MyApp.cpp" />
|
||||
<ClCompile Include="MyFrame.cpp" />
|
||||
<ClCompile Include="MyListCtrl.cpp" />
|
||||
<ClCompile Include="MyWizard.cpp" />
|
||||
<ClCompile Include="ProcListCtrl.cpp" />
|
||||
<ClCompile Include="ProcSettingsDialog.cpp" />
|
||||
<ClCompile Include="ProgramSelector.cpp" />
|
||||
<ClCompile Include="PropPageFrame.cpp" />
|
||||
<ClCompile Include="PropPageFrameDefault.cpp" />
|
||||
<ClCompile Include="QuickRecover.cpp" />
|
||||
<ClCompile Include="RevealDialog.cpp" />
|
||||
<ClCompile Include="SbieIni.cpp" />
|
||||
<ClCompile Include="SetFolderDialog.cpp" />
|
||||
<ClCompile Include="SetLayoutDialog.cpp" />
|
||||
<ClCompile Include="ShellDialog.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
<ClCompile Include="TabbingComboBox.cpp" />
|
||||
<ClCompile Include="TemplateListBox.cpp" />
|
||||
<ClCompile Include="ThirdPartyDialog.cpp" />
|
||||
<ClCompile Include="ToolTipButton.cpp" />
|
||||
<ClCompile Include="TreePropSheet.cpp" />
|
||||
<ClCompile Include="UserSettings.cpp" />
|
||||
<ClCompile Include="ViewTemplateDialog.cpp" />
|
||||
<ClCompile Include="WindowTitleMap.cpp" />
|
||||
<ClCompile Include="..\common\BoxOrder.c">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\FontStore.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\Layout.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\MyGdi.c">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\MyMsg.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\RunBrowser.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\common\RunStartExe.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\common\json\JSON.cpp">
|
||||
<Filter>common\json</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\common\json\JSONValue.cpp">
|
||||
<Filter>common\json</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UpdateDialog.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AboutDialog.h" />
|
||||
<ClInclude Include="AlertDialog.h" />
|
||||
<ClInclude Include="AnimatedBitmap.h" />
|
||||
<ClInclude Include="AppPage.h" />
|
||||
<ClInclude Include="AutoPlay.h" />
|
||||
<ClInclude Include="BaseDialog.h" />
|
||||
<ClInclude Include="BorderGuard.h" />
|
||||
<ClInclude Include="Box.h" />
|
||||
<ClInclude Include="Boxes.h" />
|
||||
<ClInclude Include="BoxFile.h" />
|
||||
<ClInclude Include="BoxPage.h" />
|
||||
<ClInclude Include="BoxProc.h" />
|
||||
<ClInclude Include="CreateDialog.h" />
|
||||
<ClInclude Include="DeleteDialog.h" />
|
||||
<ClInclude Include="DisableForceDialog.h" />
|
||||
<ClInclude Include="FileListCtrl.h" />
|
||||
<ClInclude Include="FinderDialog.h" />
|
||||
<ClInclude Include="FindTool.h" />
|
||||
<ClInclude Include="FlashingButton.h" />
|
||||
<ClInclude Include="GettingStartedWizard.h" />
|
||||
<ClInclude Include="InitWait.h" />
|
||||
<ClInclude Include="LockConfigDialog.h" />
|
||||
<ClInclude Include="MenuXP.h" />
|
||||
<ClInclude Include="MenuXP_Draw.h" />
|
||||
<ClInclude Include="MenuXP_Tools.h" />
|
||||
<ClInclude Include="MessageDialog.h" />
|
||||
<ClInclude Include="MonitorDialog.h" />
|
||||
<ClInclude Include="MyApp.h" />
|
||||
<ClInclude Include="MyFrame.h" />
|
||||
<ClInclude Include="MyListCtrl.h" />
|
||||
<ClInclude Include="MyWizard.h" />
|
||||
<ClInclude Include="ProcListCtrl.h" />
|
||||
<ClInclude Include="ProcSettingsDialog.h" />
|
||||
<ClInclude Include="ProgramSelector.h" />
|
||||
<ClInclude Include="PropPageFrame.h" />
|
||||
<ClInclude Include="PropPageFrameDefault.h" />
|
||||
<ClInclude Include="QuickRecover.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="RevealDialog.h" />
|
||||
<ClInclude Include="SbieIni.h" />
|
||||
<ClInclude Include="SetFolderDialog.h" />
|
||||
<ClInclude Include="SetLayoutDialog.h" />
|
||||
<ClInclude Include="ShellDialog.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="TabbingComboBox.h" />
|
||||
<ClInclude Include="TemplateListBox.h" />
|
||||
<ClInclude Include="ThirdPartyDialog.h" />
|
||||
<ClInclude Include="ToolTipButton.h" />
|
||||
<ClInclude Include="TreePropSheet.h" />
|
||||
<ClInclude Include="UserSettings.h" />
|
||||
<ClInclude Include="ViewTemplateDialog.h" />
|
||||
<ClInclude Include="WindowTitleMap.h" />
|
||||
<ClInclude Include="..\common\BoxOrder.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\FontStore.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\Layout.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\MyGdi.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\MyMsg.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\RunBrowser.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\common\my_version.h">
|
||||
<Filter>common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\common\json\JSON.h">
|
||||
<Filter>common\json</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\common\json\JSONValue.h">
|
||||
<Filter>common\json</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UpdateDialog.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="SbieControl.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\res\FrontPageAnimation.gif" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\res\background.png" />
|
||||
<None Include="..\res\bigex.ico" />
|
||||
<None Include="..\res\checkmark.png" />
|
||||
<None Include="..\res\controlwin.ico" />
|
||||
<None Include="..\res\cycle.png" />
|
||||
<None Include="..\res\exclamation.png" />
|
||||
<None Include="..\res\finder-empty.bmp" />
|
||||
<None Include="..\res\finder-full.bmp" />
|
||||
<None Include="..\res\finder.cur" />
|
||||
<None Include="..\res\folder-minus.ico" />
|
||||
<None Include="..\res\folder-plus.ico" />
|
||||
<None Include="..\res\GettingStartedLegend.png" />
|
||||
<None Include="..\res\initwait1.ico" />
|
||||
<None Include="..\res\initwait2.ico" />
|
||||
<None Include="..\res\MastheadLogo.jpg" />
|
||||
<None Include="..\res\none.ico" />
|
||||
<None Include="..\res\proc-empty.ico" />
|
||||
<None Include="..\res\proc-full-minus.ico" />
|
||||
<None Include="..\res\proc-full-plus.ico" />
|
||||
<None Include="..\res\questionmark.png" />
|
||||
<None Include="..\res\sandbox-delete.ico" />
|
||||
<None Include="..\res\sandbox-empty-dfp.ico" />
|
||||
<None Include="..\res\sandbox-empty.ico" />
|
||||
<None Include="..\res\sandbox-full-dfp.ico" />
|
||||
<None Include="..\res\sandbox-full.ico" />
|
||||
<None Include="SbieControl.rc2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="common">
|
||||
<UniqueIdentifier>{be66dba5-2f3c-4325-abc0-4283750262a2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="common\json">
|
||||
<UniqueIdentifier>{1eb5d258-3c21-4ed6-9384-57dd80c51c36}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -45,7 +45,8 @@
|
|||
#include "apps/common/RunBrowser.h"
|
||||
#include "apps/common/BoxOrder.h"
|
||||
#include "common/my_version.h"
|
||||
|
||||
#include "Updater.h"
|
||||
#include "UpdateDialog.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
@ -87,6 +88,8 @@ static const WCHAR *_HideWindowNotify = L"HideWindowNotify";
|
|||
const WCHAR *_UpdateCheckNotify = L"UpdateCheckNotify";
|
||||
static const WCHAR *_ShouldDeleteNotify = L"ShouldDeleteNotify";
|
||||
|
||||
const WCHAR *_NextUpdateCheck = L"NextUpdateCheck";
|
||||
|
||||
BOOL CMyFrame::m_inTimer = FALSE;
|
||||
BOOL CMyFrame::m_destroyed = FALSE;
|
||||
|
||||
|
@ -135,11 +138,15 @@ BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
|
|||
ON_COMMAND(ID_CONF_EDIT, OnCmdConfEdit)
|
||||
ON_COMMAND(ID_CONF_RELOAD, OnCmdConfReload)
|
||||
|
||||
ON_COMMAND(ID_HELP_SUPPORT, OnCmdHelpSupport)
|
||||
ON_COMMAND(ID_HELP_TOPICS, OnCmdHelpTopics)
|
||||
ON_COMMAND(ID_HELP_TUTORIAL, OnCmdHelpTutorial)
|
||||
ON_COMMAND(ID_HELP_FORUM, OnCmdHelpForum)
|
||||
ON_COMMAND(ID_HELP_UPDATE, OnCmdHelpUpdate)
|
||||
ON_COMMAND(ID_HELP_ABOUT, OnCmdHelpAbout)
|
||||
|
||||
//ON_MESSAGE(WM_UPDATERESULT, OnUpdateResult)
|
||||
|
||||
ON_COMMAND(ID_PROCESS_TERMINATE, OnCmdTerminateProcess)
|
||||
|
||||
ON_UPDATE_COMMAND_UI(ID_DISABLE_FORCE, OnUpdDisableForce)
|
||||
|
@ -962,6 +969,17 @@ void CMyFrame::OnCmdConfReload()
|
|||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnCmdHelpSupport
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CMyFrame::OnCmdHelpSupport()
|
||||
{
|
||||
CRunBrowser x(this, L"https://xanasoft.com/go.php?to=donate");
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnCmdHelpTopics
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -997,8 +1015,17 @@ void CMyFrame::OnCmdHelpForum()
|
|||
CRunBrowser::OpenForum(this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnCmdHelpUpdate
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CMyFrame::OnCmdHelpUpdate()
|
||||
{
|
||||
CUpdateDialog dlg(this);
|
||||
dlg.DoModal();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnCmdHelpAbout
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -2007,6 +2034,39 @@ void CMyFrame::OnTimer(UINT_PTR nIDEvent)
|
|||
if ((_counter % 600) == 0)
|
||||
SaveSettings();
|
||||
|
||||
//
|
||||
// update check
|
||||
//
|
||||
|
||||
if (! m_hidden)
|
||||
{
|
||||
__int64 NextUpdateCheck;
|
||||
CUserSettings::GetInstance().GetNum64(_NextUpdateCheck, NextUpdateCheck, 0);
|
||||
if(NextUpdateCheck == 0)
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, time(NULL) + 7 * 24 * 60 * 60);
|
||||
else if(NextUpdateCheck != -1 && time(NULL) >= NextUpdateCheck)
|
||||
{
|
||||
BOOL UpdateCheckNotify;
|
||||
CUserSettings::GetInstance().GetBool(_UpdateCheckNotify, UpdateCheckNotify, TRUE);
|
||||
if (UpdateCheckNotify)
|
||||
{
|
||||
static BOOLEAN update_dlg_open = FALSE;
|
||||
if (!update_dlg_open) {
|
||||
update_dlg_open = TRUE;
|
||||
CUpdateDialog dlg(this);
|
||||
if(dlg.DoModal() == 0)
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, time(NULL) + 1 * 24 * 60 * 60);
|
||||
update_dlg_open = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, time(NULL) + 1 * 24 * 60 * 60);
|
||||
CUpdater::GetInstance().CheckUpdates(this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// refresh processes
|
||||
//
|
||||
|
@ -2331,3 +2391,9 @@ void CMyFrame::CheckShouldDelete(CBox &box)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*LRESULT CMyFrame::OnUpdateResult(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}*/
|
|
@ -119,10 +119,13 @@ class CMyFrame : public CFrameWnd
|
|||
afx_msg void OnCmdConfLock();
|
||||
afx_msg void OnCmdConfEdit();
|
||||
afx_msg void OnCmdConfReload();
|
||||
afx_msg void OnCmdHelpSupport();
|
||||
afx_msg void OnCmdHelpTopics();
|
||||
afx_msg void OnCmdHelpTutorial();
|
||||
afx_msg void OnCmdHelpForum();
|
||||
afx_msg void OnCmdHelpUpdate();
|
||||
afx_msg void OnCmdHelpAbout();
|
||||
//afx_msg LRESULT OnUpdateResult(WPARAM wParam, LPARAM lParam);
|
||||
afx_msg void OnCmdTerminateProcess();
|
||||
|
||||
afx_msg void OnUpdViewMenu(CCmdUI *pCmdUI);
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright 2020 David Xanatos, xanasoft.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Browser Dialog
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "UpdateDialog.h"
|
||||
#include "Updater.h"
|
||||
#include "common/CommonUtils.h"
|
||||
#include "common/MyMsg.h"
|
||||
#include "core/dll/sbiedll.h"
|
||||
#include "UserSettings.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Message Map
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(CUpdateDialog, CDialog)
|
||||
|
||||
ON_COMMAND(IDOK, OnNow)
|
||||
ON_COMMAND(ID_UPDATE_LATER, OnLater)
|
||||
ON_COMMAND(ID_UPDATE_NEVER, OnNever)
|
||||
ON_COMMAND(IDCANCEL, OnCancel)
|
||||
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdateDialog::CUpdateDialog(CWnd *pParentWnd)
|
||||
: CDialog((UINT)0, pParentWnd)
|
||||
{
|
||||
m_lpszTemplateName = L"UPDATE_DIALOG";
|
||||
|
||||
BOOLEAN LayoutRTL;
|
||||
SbieDll_GetLanguage(&LayoutRTL);
|
||||
if (LayoutRTL) {
|
||||
|
||||
m_DlgTmplCopy =
|
||||
Common_DlgTmplRtl(AfxGetInstanceHandle(), m_lpszTemplateName);
|
||||
if (m_DlgTmplCopy) {
|
||||
m_lpszTemplateName = NULL;
|
||||
InitModalIndirect((LPCDLGTEMPLATE)m_DlgTmplCopy, m_pParentWnd);
|
||||
}
|
||||
|
||||
} else
|
||||
m_DlgTmplCopy = NULL;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdateDialog::~CUpdateDialog()
|
||||
{
|
||||
if (m_DlgTmplCopy) {
|
||||
HeapFree(GetProcessHeap(), 0, m_DlgTmplCopy);
|
||||
m_DlgTmplCopy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnInitDialog
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
BOOL CUpdateDialog::OnInitDialog()
|
||||
{
|
||||
SetWindowText(CMyMsg(MSG_3621));
|
||||
|
||||
GetDlgItem(ID_UPDATE_EXPLAIN_1)->SetWindowText(CMyMsg(MSG_3622));
|
||||
GetDlgItem(IDOK)->SetWindowText(CMyMsg(MSG_3623));
|
||||
GetDlgItem(ID_UPDATE_LATER)->SetWindowText(CMyMsg(MSG_3624));
|
||||
GetDlgItem(ID_UPDATE_NEVER)->SetWindowText(CMyMsg(MSG_3625));
|
||||
GetDlgItem(IDCANCEL)->SetWindowText(CMyMsg(MSG_3002));
|
||||
GetDlgItem(ID_UPDATE_SILENT)->SetWindowText(CMyMsg(MSG_3626));
|
||||
GetDlgItem(ID_UPDATE_EXPLAIN_2)->SetWindowText(CMyMsg(MSG_3627));
|
||||
|
||||
BOOL UpdateCheckNotify;
|
||||
CUserSettings::GetInstance().GetBool(_UpdateCheckNotify, UpdateCheckNotify, FALSE);
|
||||
CButton *pCheckBox1 = (CButton *)GetDlgItem(ID_UPDATE_SILENT);
|
||||
pCheckBox1->SetCheck(!UpdateCheckNotify ? BST_CHECKED : BST_UNCHECKED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnNow
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CUpdateDialog::OnNow()
|
||||
{
|
||||
if(!CUpdater::GetInstance().CheckUpdates(GetParent()))
|
||||
CMyApp::MsgBox(NULL, MSG_3628, MB_OK);
|
||||
CloseDialog();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnLater
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CUpdateDialog::OnLater()
|
||||
{
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, time(NULL) + 7 * 24 * 60 * 60);
|
||||
CloseDialog();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnNever
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CUpdateDialog::OnNever()
|
||||
{
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, -1);
|
||||
CloseDialog();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// OnCancel
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CUpdateDialog::OnCancel()
|
||||
{
|
||||
EndDialog(0);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// EndDialog
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CUpdateDialog::CloseDialog()
|
||||
{
|
||||
CButton *pCheckBox1 = (CButton *)GetDlgItem(ID_UPDATE_SILENT);
|
||||
CUserSettings::GetInstance().SetBool(_UpdateCheckNotify, !pCheckBox1->GetCheck() == BST_CHECKED);
|
||||
|
||||
EndDialog(1);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2020 David Xanatos, xanasoft.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Browser Dialog Box
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef _MY_UPDATEDIALOG_H
|
||||
#define _MY_UPDATEDIALOG_H
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Defines
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#define ID_RUN_BROWSER_EXPLAIN 10111
|
||||
#define ID_RUN_BROWSER_URL 10222
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// CUpdateDialog Class
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
||||
#include <afxcmn.h>
|
||||
|
||||
|
||||
class CUpdateDialog : public CDialog
|
||||
{
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
void *m_DlgTmplCopy;
|
||||
|
||||
virtual BOOL OnInitDialog();
|
||||
|
||||
afx_msg void OnNow();
|
||||
afx_msg void OnLater();
|
||||
afx_msg void OnNever();
|
||||
afx_msg void OnCancel();
|
||||
|
||||
void CloseDialog();
|
||||
|
||||
public:
|
||||
|
||||
CUpdateDialog(CWnd *pParentWnd);
|
||||
~CUpdateDialog();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // ! RC_INVOKED
|
||||
#endif // _MY_UPDATEDIALOG_H
|
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* Copyright 2020 David Xanatos, xanasoft.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Updater
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <winhttp.h>
|
||||
#include "Updater.h"
|
||||
#include "UpdateDialog.h"
|
||||
#include "common/RunBrowser.h"
|
||||
#include "SbieIni.h"
|
||||
#include "UserSettings.h"
|
||||
#define CRC_WITH_ADLER32
|
||||
#include "common/crc.c"
|
||||
#include "common/my_version.h"
|
||||
#include "common/json/JSON.h"
|
||||
#include "common/win32_ntddk.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Variables
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdater *CUpdater::m_instance = NULL;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdater::CUpdater()
|
||||
{
|
||||
m_update_pending = false;
|
||||
|
||||
//OSVERSIONINFOW m_osvi = { 0 };
|
||||
m_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOW);
|
||||
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
|
||||
if (RtlGetVersion == NULL || !NT_SUCCESS(RtlGetVersion(&m_osvi)))
|
||||
GetVersionExW(&m_osvi);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdater::~CUpdater()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// GetInstance
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CUpdater &CUpdater::GetInstance()
|
||||
{
|
||||
if (!m_instance)
|
||||
m_instance = new CUpdater();
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// CheckUpdates
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool CUpdater::CheckUpdates(CWnd *pParentWnd, bool bManual)
|
||||
{
|
||||
if (m_update_pending)
|
||||
return false;
|
||||
|
||||
ULONG ThreadId;
|
||||
ULONG_PTR *ThreadArgs = new ULONG_PTR[2];
|
||||
ThreadArgs[0] = (ULONG_PTR)pParentWnd->m_hWnd;
|
||||
ThreadArgs[1] = bManual ? 1 : 0;
|
||||
CreateThread(NULL, 0, UpdaterServiceThread, ThreadArgs, 0, &ThreadId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DownloadUpdateData
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
BOOLEAN CUpdater::DownloadUpdateData(const WCHAR* Host, const WCHAR* Path, PSTR* pData, ULONG* pDataLength)
|
||||
{
|
||||
BOOLEAN success = FALSE;
|
||||
|
||||
PVOID SessionHandle = NULL;
|
||||
PVOID ConnectionHandle = NULL;
|
||||
PVOID RequestHandle = NULL;
|
||||
|
||||
{
|
||||
SessionHandle = WinHttpOpen(NULL,
|
||||
m_osvi.dwMajorVersion >= 8 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||
if (!SessionHandle)
|
||||
goto CleanupExit;
|
||||
|
||||
if (m_osvi.dwMajorVersion >= 8) {
|
||||
ULONG Options = WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
|
||||
WinHttpSetOption(SessionHandle, WINHTTP_OPTION_DECOMPRESSION, &Options, sizeof(Options));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ConnectionHandle = WinHttpConnect(SessionHandle, Host, 443, 0); // ssl port
|
||||
if (!ConnectionHandle)
|
||||
goto CleanupExit;
|
||||
}
|
||||
|
||||
{
|
||||
ULONG httpFlags = WINHTTP_FLAG_SECURE | WINHTTP_FLAG_REFRESH;
|
||||
RequestHandle = WinHttpOpenRequest(ConnectionHandle,
|
||||
NULL, Path, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, httpFlags);
|
||||
|
||||
if (!RequestHandle)
|
||||
goto CleanupExit;
|
||||
|
||||
ULONG Options = WINHTTP_DISABLE_KEEP_ALIVE;
|
||||
WinHttpSetOption(RequestHandle, WINHTTP_OPTION_DISABLE_FEATURE, &Options, sizeof(Options));
|
||||
}
|
||||
|
||||
if (!WinHttpSendRequest(RequestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0))
|
||||
goto CleanupExit;
|
||||
|
||||
if (!WinHttpReceiveResponse(RequestHandle, NULL))
|
||||
goto CleanupExit;
|
||||
|
||||
{
|
||||
PVOID result = NULL;
|
||||
ULONG allocatedLength;
|
||||
ULONG dataLength;
|
||||
ULONG returnLength;
|
||||
BYTE buffer[PAGE_SIZE];
|
||||
|
||||
if (pData == NULL)
|
||||
goto CleanupExit;
|
||||
|
||||
allocatedLength = sizeof(buffer);
|
||||
*pData = (PSTR)malloc(allocatedLength);
|
||||
dataLength = 0;
|
||||
|
||||
while (WinHttpReadData(RequestHandle, buffer, PAGE_SIZE, &returnLength))
|
||||
{
|
||||
if (returnLength == 0)
|
||||
break;
|
||||
|
||||
if (allocatedLength < dataLength + returnLength)
|
||||
{
|
||||
allocatedLength *= 2;
|
||||
*pData = (PSTR)realloc(*pData, allocatedLength);
|
||||
}
|
||||
|
||||
memcpy(*pData + dataLength, buffer, returnLength);
|
||||
|
||||
dataLength += returnLength;
|
||||
}
|
||||
|
||||
if (allocatedLength < dataLength + 1)
|
||||
{
|
||||
allocatedLength++;
|
||||
*pData = (PSTR)realloc(*pData, allocatedLength);
|
||||
}
|
||||
|
||||
// Ensure that the buffer is null-terminated.
|
||||
(*pData)[dataLength] = 0;
|
||||
|
||||
if (pDataLength != NULL)
|
||||
*pDataLength = dataLength;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
CleanupExit:
|
||||
if (RequestHandle)
|
||||
WinHttpCloseHandle(RequestHandle);
|
||||
if (ConnectionHandle)
|
||||
WinHttpCloseHandle(ConnectionHandle);
|
||||
if (SessionHandle)
|
||||
WinHttpCloseHandle(SessionHandle);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// GetJSONStringSafe
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
std::wstring GetJSONStringSafe(const JSONObject& root, const std::wstring& key, const std::wstring& default = L"")
|
||||
{
|
||||
auto I = root.find(key);
|
||||
if (I == root.end() || !I->second->IsString())
|
||||
return default;
|
||||
return I->second->AsString();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// QueryUpdateData
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
BOOLEAN CUpdater::QueryUpdateData(UPDATER_DATA* Context)
|
||||
{
|
||||
BOOLEAN success = FALSE;
|
||||
|
||||
CString Path;
|
||||
|
||||
char* jsonString = NULL;
|
||||
JSONValue* jsonObject = NULL;
|
||||
JSONObject jsonRoot;
|
||||
|
||||
Path.Format(L"/update.php?software=sandboxie&version=%S&system=windows-%d.%d.%d-%s&language=%d&auto=%s", MY_VERSION_STRING,
|
||||
#ifdef _WIN64
|
||||
m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber, L"x86_64",
|
||||
#else
|
||||
m_osvi.dwMajorVersion, m_osvi.dwMinorVersion, m_osvi.dwBuildNumber, L"i386",
|
||||
#endif
|
||||
SbieDll_GetLanguage(NULL), Context->Manual ? L"0" : L"1");
|
||||
|
||||
CString update_key;
|
||||
CSbieIni::GetInstance().GetText(_GlobalSettings, L"UpdateKey", update_key);
|
||||
if (!update_key.IsEmpty())
|
||||
Path += L"&update_key=" + update_key;
|
||||
|
||||
if (!DownloadUpdateData(L"xanasoft.com", Path, &jsonString, NULL)) {
|
||||
Context->ErrorCode = GetLastError();
|
||||
goto CleanupExit;
|
||||
}
|
||||
|
||||
jsonObject = JSON::Parse((const char*)jsonString);
|
||||
if (jsonObject == NULL || !jsonObject->IsObject()) {
|
||||
Context->ErrorCode = WEB_E_INVALID_JSON_STRING;
|
||||
goto CleanupExit;
|
||||
}
|
||||
|
||||
jsonRoot = jsonObject->AsObject();
|
||||
|
||||
Context->userMsg = GetJSONStringSafe(jsonRoot, L"userMsg").c_str();
|
||||
Context->infoUrl = GetJSONStringSafe(jsonRoot, L"infoUrl").c_str();
|
||||
|
||||
Context->version = GetJSONStringSafe(jsonRoot, L"version").c_str();
|
||||
//Context->updated = (uint64_t)jsonRoot[L"updated"]->AsNumber();
|
||||
Context->updateMsg = GetJSONStringSafe(jsonRoot, L"updateMsg").c_str();
|
||||
Context->updateUrl = GetJSONStringSafe(jsonRoot, L"updateUrl").c_str();
|
||||
Context->downloadUrl = GetJSONStringSafe(jsonRoot, L"downloadUrl").c_str();
|
||||
|
||||
success = TRUE;
|
||||
|
||||
CleanupExit:
|
||||
|
||||
if (jsonString)
|
||||
free(jsonString);
|
||||
|
||||
if (jsonObject)
|
||||
delete jsonObject;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DownloadUpdate
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
CString CUpdater::DownloadUpdate(const CString& downloadUrl)
|
||||
{
|
||||
WCHAR TempDir[MAX_PATH + 1];
|
||||
if (GetTempPath(MAX_PATH, (LPWSTR)&TempDir) == 0)
|
||||
return L"";
|
||||
|
||||
int hostPos = downloadUrl.Find(L"://") + 3;
|
||||
if(hostPos < 3)
|
||||
return L"";
|
||||
|
||||
int pathPos = downloadUrl.Find(L"/", hostPos);
|
||||
if (pathPos < 0)
|
||||
return L"";
|
||||
|
||||
CString Host = downloadUrl.Mid(hostPos, pathPos - hostPos);
|
||||
CString Path = downloadUrl.Mid(pathPos);
|
||||
|
||||
int queryPos = downloadUrl.Find(L"?", pathPos);
|
||||
if (queryPos < 0)
|
||||
queryPos = downloadUrl.GetLength();
|
||||
|
||||
CString Name = downloadUrl.Left(queryPos);
|
||||
Name = Name.Mid(Name.ReverseFind(L'/') + 1);
|
||||
if (Name.IsEmpty() || Name.Right(4).CompareNoCase(L".exe") != 0)
|
||||
Name = L"SandboxieInstall.exe";
|
||||
|
||||
char* data = NULL;
|
||||
ULONG size = 0;
|
||||
|
||||
if (!DownloadUpdateData(Host, Path, &data, &size))
|
||||
return L"";
|
||||
|
||||
CString FilePath = TempDir + Name;
|
||||
|
||||
ULONG bytesWriten = 0;
|
||||
HANDLE hFile = CreateFile(FilePath, FILE_GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
//SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
WriteFile(hFile, data, size, &bytesWriten, NULL);
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
free(data);
|
||||
|
||||
if(bytesWriten != size)
|
||||
return L"";
|
||||
|
||||
return FilePath;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// UpdaterServiceThread
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
ULONG CUpdater::UpdaterServiceThread(void *lpParameter)
|
||||
{
|
||||
m_instance->m_update_pending = true;
|
||||
|
||||
ULONG_PTR *ThreadArgs = (ULONG_PTR *)lpParameter;
|
||||
HWND parent = (HWND)ThreadArgs[0];
|
||||
|
||||
PUPDATER_DATA pContext = new UPDATER_DATA;
|
||||
pContext->Manual = ThreadArgs[1] ? TRUE : FALSE;
|
||||
pContext->ErrorCode = 0;
|
||||
BOOLEAN Ret = m_instance->QueryUpdateData(pContext);
|
||||
if (Ret)
|
||||
{
|
||||
bool bNothing = true;
|
||||
|
||||
CStringList IgnoredUpdates;
|
||||
CUserSettings::GetInstance().GetTextList(L"_IgnoreUpdate", IgnoredUpdates);
|
||||
|
||||
if (!pContext->userMsg.IsEmpty())
|
||||
{
|
||||
WCHAR MsgHash[9];
|
||||
ULONG crc = CRC_Adler32((UCHAR *)(const WCHAR*)pContext->userMsg, pContext->userMsg.GetLength() * sizeof(WCHAR));
|
||||
wsprintf(MsgHash, L"%08X", crc);
|
||||
|
||||
if (IgnoredUpdates.Find(MsgHash) == NULL)
|
||||
{
|
||||
bNothing = false;
|
||||
|
||||
CString Msg = pContext->userMsg;
|
||||
|
||||
int rv;
|
||||
if (pContext->infoUrl.IsEmpty())
|
||||
rv = CMyApp::MsgCheckBox(NULL, Msg, 0, MB_OK);
|
||||
else
|
||||
{
|
||||
Msg += "\n \n";
|
||||
Msg += CMyMsg(MSG_3641) + L"?";
|
||||
|
||||
rv = CMyApp::MsgCheckBox(NULL, Msg, 0, MB_YESNO);
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
rv = -rv;
|
||||
CUserSettings::GetInstance().AppendText(L"_IgnoreUpdate", MsgHash);
|
||||
}
|
||||
|
||||
if (rv == IDYES)
|
||||
CRunBrowser dlg(NULL, pContext->infoUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!pContext->version.IsEmpty() && pContext->version.Compare(_T(MY_VERSION_STRING)) != 0)
|
||||
{
|
||||
if (pContext->Manual || IgnoredUpdates.Find(pContext->version) == NULL)
|
||||
{
|
||||
bNothing = false;
|
||||
|
||||
CString Msg = pContext->updateMsg;
|
||||
if (Msg.IsEmpty())
|
||||
Msg = CMyMsg(MSG_3630, pContext->version);
|
||||
|
||||
int rv;
|
||||
if (pContext->updateUrl.IsEmpty() && pContext->downloadUrl.IsEmpty())
|
||||
rv = CMyApp::MsgCheckBox(NULL, Msg, 0, MB_OK);
|
||||
else
|
||||
{
|
||||
Msg += "\n \n";
|
||||
if (!pContext->downloadUrl.IsEmpty())
|
||||
Msg += CMyMsg(MSG_3631);
|
||||
else
|
||||
Msg += CMyMsg(MSG_3641) + L"?"; // MSG_3631
|
||||
|
||||
rv = CMyApp::MsgCheckBox(NULL, Msg, 0, MB_YESNO);
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
rv = -rv;
|
||||
CUserSettings::GetInstance().AppendText(L"_IgnoreUpdate", pContext->version);
|
||||
}
|
||||
|
||||
if (rv == IDYES)
|
||||
{
|
||||
if (!pContext->downloadUrl.IsEmpty())
|
||||
{
|
||||
CString downloadPath = m_instance->DownloadUpdate(pContext->downloadUrl);
|
||||
if (downloadPath.IsEmpty())
|
||||
CMyApp::MsgBox(NULL, MSG_3634, MB_OK);
|
||||
else
|
||||
{
|
||||
rv = CMyApp::MsgBox(NULL, CMyMsg(MSG_3633, pContext->version, downloadPath), MB_YESNO);
|
||||
if (rv == IDYES)
|
||||
{
|
||||
SHELLEXECUTEINFO shex;
|
||||
memzero(&shex, sizeof(SHELLEXECUTEINFO));
|
||||
shex.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||
shex.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
|
||||
shex.hwnd = parent;
|
||||
shex.lpFile = downloadPath;
|
||||
shex.lpParameters = NULL;
|
||||
shex.nShow = SW_SHOWNORMAL;
|
||||
shex.lpVerb = L"runas";
|
||||
if (ShellExecuteEx(&shex))
|
||||
CloseHandle(shex.hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CRunBrowser dlg(NULL, pContext->updateUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bNothing)
|
||||
{
|
||||
// schedule next theck for in a week, except when the user choose never
|
||||
__int64 NextUpdateCheck;
|
||||
CUserSettings::GetInstance().GetNum64(_NextUpdateCheck, NextUpdateCheck, 0);
|
||||
if (NextUpdateCheck != -1)
|
||||
CUserSettings::GetInstance().SetNum64(_NextUpdateCheck, time(NULL) + 7 * 24 * 60 * 60);
|
||||
|
||||
if (pContext->Manual)
|
||||
CMyApp::MsgBox(NULL, MSG_3629, MB_OK);
|
||||
}
|
||||
}
|
||||
else if (pContext->Manual)
|
||||
CMyApp::MsgBox(NULL, MSG_3634, MB_OK);
|
||||
|
||||
//::PostMessage(parent, WM_UPDATERESULT, Ret, (LPARAM)pContext);
|
||||
delete pContext;
|
||||
|
||||
m_instance->m_update_pending = false;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2020 David Xanatos, xanasoft.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Updater
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef _MY_UPDATER_H
|
||||
#define _MY_UPDATER_H
|
||||
|
||||
//#define WM_UPDATERESULT (WM_APP + 10)
|
||||
|
||||
typedef struct _UPDATER_DATA
|
||||
{
|
||||
CString userMsg;
|
||||
CString infoUrl;
|
||||
|
||||
CString version;
|
||||
//unsigned __int64 updated;
|
||||
CString updateMsg;
|
||||
CString updateUrl;
|
||||
CString downloadUrl;
|
||||
|
||||
BOOLEAN Manual;
|
||||
ULONG ErrorCode;
|
||||
|
||||
} UPDATER_DATA, *PUPDATER_DATA;
|
||||
|
||||
extern const WCHAR *_UpdateCheckNotify;
|
||||
extern const WCHAR *_NextUpdateCheck;
|
||||
|
||||
class CUpdater
|
||||
{
|
||||
static CUpdater *m_instance;
|
||||
|
||||
bool m_update_pending;
|
||||
|
||||
OSVERSIONINFOW m_osvi;
|
||||
|
||||
CUpdater();
|
||||
|
||||
BOOLEAN DownloadUpdateData(const WCHAR* Host, const WCHAR* Path, PSTR* pData, ULONG* dataLength);
|
||||
BOOLEAN QueryUpdateData(UPDATER_DATA* Context);
|
||||
CString DownloadUpdate(const CString& downloadUrl);
|
||||
|
||||
static ULONG UpdaterServiceThread(void *lpParameter);
|
||||
|
||||
public:
|
||||
|
||||
~CUpdater();
|
||||
|
||||
static CUpdater &GetInstance();
|
||||
|
||||
bool CheckUpdates(CWnd *pParentWnd, bool bManual = true);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // _MY_UPDATER_H
|
|
@ -46,9 +46,11 @@
|
|||
#define ID_CONF_RELOAD 40037
|
||||
#define ID_CONF_THIRD_PARTY 40038
|
||||
#define ID_CONF_LOCK 40039
|
||||
#define ID_HELP_SUPPORT 40040
|
||||
#define ID_HELP_TOPICS 40041
|
||||
#define ID_HELP_TUTORIAL 40042
|
||||
#define ID_HELP_FORUM 40043
|
||||
#define ID_HELP_UPDATE 40044
|
||||
#define ID_HELP_ABOUT 40045
|
||||
#define ID_PROCESS_TERMINATE 40051
|
||||
#define ID_PROCESS_SETTINGS 40052
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* File JSON.cpp part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "JSON.h"
|
||||
|
||||
/**
|
||||
* Blocks off the public constructor
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
*/
|
||||
JSON::JSON()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a complete JSON encoded string
|
||||
* This is just a wrapper around the UNICODE Parse().
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param char* data The JSON text
|
||||
*
|
||||
* @return JSONValue* Returns a JSON Value representing the root, or NULL on error
|
||||
*/
|
||||
JSONValue *JSON::Parse(const char *data)
|
||||
{
|
||||
size_t length = strlen(data) + 1;
|
||||
wchar_t *w_data = (wchar_t*)malloc(length * sizeof(wchar_t));
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__)
|
||||
size_t ret_value = 0;
|
||||
if (mbstowcs_s(&ret_value, w_data, length, data, length) != 0)
|
||||
{
|
||||
free(w_data);
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(ANDROID)
|
||||
// mbstowcs seems to misbehave on android
|
||||
for(size_t i = 0; i<length; i++)
|
||||
w_data[i] = (wchar_t)data[i];
|
||||
#else
|
||||
if (mbstowcs(w_data, data, length) == (size_t)-1)
|
||||
{
|
||||
free(w_data);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSONValue *value = JSON::Parse(w_data);
|
||||
free(w_data);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a complete JSON encoded string (UNICODE input version)
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param wchar_t* data The JSON text
|
||||
*
|
||||
* @return JSONValue* Returns a JSON Value representing the root, or NULL on error
|
||||
*/
|
||||
JSONValue *JSON::Parse(const wchar_t *data)
|
||||
{
|
||||
// Skip any preceding whitespace, end of data = no JSON = fail
|
||||
if (!SkipWhitespace(&data))
|
||||
return NULL;
|
||||
|
||||
// We need the start of a value here now...
|
||||
JSONValue *value = JSONValue::Parse(&data);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
// Can be white space now and should be at the end of the string then...
|
||||
if (SkipWhitespace(&data))
|
||||
{
|
||||
delete value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// We're now at the end of the string
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the passed in JSONValue into a JSON encode string
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONValue* value The root value
|
||||
*
|
||||
* @return std::wstring Returns a JSON encoded string representation of the given value
|
||||
*/
|
||||
std::wstring JSON::Stringify(const JSONValue *value)
|
||||
{
|
||||
if (value != NULL)
|
||||
return value->Stringify();
|
||||
else
|
||||
return L"";
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over any whitespace characters (space, tab, \r or \n) defined by the JSON spec
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return bool Returns true if there is more data, or false if the end of the text was reached
|
||||
*/
|
||||
bool JSON::SkipWhitespace(const wchar_t **data)
|
||||
{
|
||||
while (**data != 0 && (**data == L' ' || **data == L'\t' || **data == L'\r' || **data == L'\n'))
|
||||
(*data)++;
|
||||
|
||||
return **data != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a JSON String as defined by the spec - "<some chars>"
|
||||
* Any escaped characters are swapped out for their unescaped values
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
* @param std::wstring& str Reference to a std::wstring to receive the extracted string
|
||||
*
|
||||
* @return bool Returns true on success, false on failure
|
||||
*/
|
||||
bool JSON::ExtractString(const wchar_t **data, std::wstring &str)
|
||||
{
|
||||
str = L"";
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Save the char so we can change it if need be
|
||||
wchar_t next_char = **data;
|
||||
|
||||
// Escaping something?
|
||||
if (next_char == L'\\')
|
||||
{
|
||||
// Move over the escape char
|
||||
(*data)++;
|
||||
|
||||
// Deal with the escaped char
|
||||
switch (**data)
|
||||
{
|
||||
case L'"': next_char = L'"'; break;
|
||||
case L'\\': next_char = L'\\'; break;
|
||||
case L'/': next_char = L'/'; break;
|
||||
case L'b': next_char = L'\b'; break;
|
||||
case L'f': next_char = L'\f'; break;
|
||||
case L'n': next_char = L'\n'; break;
|
||||
case L'r': next_char = L'\r'; break;
|
||||
case L't': next_char = L'\t'; break;
|
||||
case L'u':
|
||||
{
|
||||
// We need 5 chars (4 hex + the 'u') or its not valid
|
||||
if (!simplejson_wcsnlen(*data, 5))
|
||||
return false;
|
||||
|
||||
// Deal with the chars
|
||||
next_char = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Do it first to move off the 'u' and leave us on the
|
||||
// final hex digit as we move on by one later on
|
||||
(*data)++;
|
||||
|
||||
next_char <<= 4;
|
||||
|
||||
// Parse the hex digit
|
||||
if (**data >= '0' && **data <= '9')
|
||||
next_char |= (**data - '0');
|
||||
else if (**data >= 'A' && **data <= 'F')
|
||||
next_char |= (10 + (**data - 'A'));
|
||||
else if (**data >= 'a' && **data <= 'f')
|
||||
next_char |= (10 + (**data - 'a'));
|
||||
else
|
||||
{
|
||||
// Invalid hex digit = invalid JSON
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// By the spec, only the above cases are allowed
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// End of the string?
|
||||
else if (next_char == L'"')
|
||||
{
|
||||
(*data)++;
|
||||
str.reserve(); // Remove unused capacity
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disallowed char?
|
||||
else if (next_char < L' ' && next_char != L'\t')
|
||||
{
|
||||
// SPEC Violation: Allow tabs due to real world cases
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the next char
|
||||
str += next_char;
|
||||
|
||||
// Move on
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// If we're here, the string ended incorrectly
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses some text as though it is an integer
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return double Returns the double value of the number found
|
||||
*/
|
||||
double JSON::ParseInt(const wchar_t **data)
|
||||
{
|
||||
double integer = 0;
|
||||
while (**data != 0 && **data >= '0' && **data <= '9')
|
||||
integer = integer * 10 + (*(*data)++ - '0');
|
||||
|
||||
return integer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses some text as though it is a decimal
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return double Returns the double value of the decimal found
|
||||
*/
|
||||
double JSON::ParseDecimal(const wchar_t **data)
|
||||
{
|
||||
double decimal = 0.0;
|
||||
double factor = 0.1;
|
||||
while (**data != 0 && **data >= '0' && **data <= '9')
|
||||
{
|
||||
int digit = (*(*data)++ - '0');
|
||||
decimal = decimal + digit * factor;
|
||||
factor *= 0.1;
|
||||
}
|
||||
return decimal;
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* File JSON.h part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H_
|
||||
#define _JSON_H_
|
||||
|
||||
// Win32 incompatibilities
|
||||
#if defined(WIN32) && !defined(__GNUC__)
|
||||
#define wcsncasecmp _wcsnicmp
|
||||
static inline bool isnan(double x) { return x != x; }
|
||||
static inline bool isinf(double x) { return !isnan(x) && isnan(x - x); }
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// Linux compile fix - from quaker66
|
||||
#ifdef __GNUC__
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
// Mac compile fixes - from quaker66, Lion fix by dabrahams
|
||||
#if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L || (defined(WIN32) && defined(__GNUC__)) || defined(ANDROID)
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
|
||||
static inline int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
|
||||
{
|
||||
int lc1 = 0;
|
||||
int lc2 = 0;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
lc1 = towlower (*s1);
|
||||
lc2 = towlower (*s2);
|
||||
|
||||
if (lc1 != lc2)
|
||||
return (lc1 - lc2);
|
||||
|
||||
if (!lc1)
|
||||
return 0;
|
||||
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simple function to check a string 's' has at least 'n' characters
|
||||
static inline bool simplejson_wcsnlen(const wchar_t *s, size_t n) {
|
||||
if (s == 0)
|
||||
return false;
|
||||
|
||||
const wchar_t *save = s;
|
||||
while (n-- > 0)
|
||||
{
|
||||
if (*(save++) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Custom types
|
||||
class JSONValue;
|
||||
typedef std::vector<JSONValue*> JSONArray;
|
||||
typedef std::map<std::wstring, JSONValue*> JSONObject;
|
||||
|
||||
#include "JSONValue.h"
|
||||
|
||||
class JSON
|
||||
{
|
||||
friend class JSONValue;
|
||||
|
||||
public:
|
||||
static JSONValue* Parse(const char *data);
|
||||
static JSONValue* Parse(const wchar_t *data);
|
||||
static std::wstring Stringify(const JSONValue *value);
|
||||
protected:
|
||||
static bool SkipWhitespace(const wchar_t **data);
|
||||
static bool ExtractString(const wchar_t **data, std::wstring &str);
|
||||
static double ParseInt(const wchar_t **data);
|
||||
static double ParseDecimal(const wchar_t **data);
|
||||
private:
|
||||
JSON();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,944 @@
|
|||
/*
|
||||
* File JSONValue.cpp part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#include "JSONValue.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define wcsncasecmp wcsnicmp
|
||||
#endif
|
||||
|
||||
// Macros to free an array/object
|
||||
#define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }
|
||||
#define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter).second; } }
|
||||
|
||||
/**
|
||||
* Parses a JSON encoded value to a JSONValue object
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the data
|
||||
*
|
||||
* @return JSONValue* Returns a pointer to a JSONValue object on success, NULL on error
|
||||
*/
|
||||
JSONValue *JSONValue::Parse(const wchar_t **data)
|
||||
{
|
||||
// Is it a string?
|
||||
if (**data == '"')
|
||||
{
|
||||
std::wstring str;
|
||||
if (!JSON::ExtractString(&(++(*data)), str))
|
||||
return NULL;
|
||||
else
|
||||
return new JSONValue(str);
|
||||
}
|
||||
|
||||
// Is it a boolean?
|
||||
else if ((simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"true", 4) == 0) || (simplejson_wcsnlen(*data, 5) && wcsncasecmp(*data, L"false", 5) == 0))
|
||||
{
|
||||
bool value = wcsncasecmp(*data, L"true", 4) == 0;
|
||||
(*data) += value ? 4 : 5;
|
||||
return new JSONValue(value);
|
||||
}
|
||||
|
||||
// Is it a null?
|
||||
else if (simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"null", 4) == 0)
|
||||
{
|
||||
(*data) += 4;
|
||||
return new JSONValue();
|
||||
}
|
||||
|
||||
// Is it a number?
|
||||
else if (**data == L'-' || (**data >= L'0' && **data <= L'9'))
|
||||
{
|
||||
// Negative?
|
||||
bool neg = **data == L'-';
|
||||
if (neg) (*data)++;
|
||||
|
||||
double number = 0.0;
|
||||
|
||||
// Parse the whole part of the number - only if it wasn't 0
|
||||
if (**data == L'0')
|
||||
(*data)++;
|
||||
else if (**data >= L'1' && **data <= L'9')
|
||||
number = JSON::ParseInt(data);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
// Could be a decimal now...
|
||||
if (**data == '.')
|
||||
{
|
||||
(*data)++;
|
||||
|
||||
// Not get any digits?
|
||||
if (!(**data >= L'0' && **data <= L'9'))
|
||||
return NULL;
|
||||
|
||||
// Find the decimal and sort the decimal place out
|
||||
// Use ParseDecimal as ParseInt won't work with decimals less than 0.1
|
||||
// thanks to Javier Abadia for the report & fix
|
||||
double decimal = JSON::ParseDecimal(data);
|
||||
|
||||
// Save the number
|
||||
number += decimal;
|
||||
}
|
||||
|
||||
// Could be an exponent now...
|
||||
if (**data == L'E' || **data == L'e')
|
||||
{
|
||||
(*data)++;
|
||||
|
||||
// Check signage of expo
|
||||
bool neg_expo = false;
|
||||
if (**data == L'-' || **data == L'+')
|
||||
{
|
||||
neg_expo = **data == L'-';
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Not get any digits?
|
||||
if (!(**data >= L'0' && **data <= L'9'))
|
||||
return NULL;
|
||||
|
||||
// Sort the expo out
|
||||
double expo = JSON::ParseInt(data);
|
||||
for (double i = 0.0; i < expo; i++)
|
||||
number = neg_expo ? (number / 10.0) : (number * 10.0);
|
||||
}
|
||||
|
||||
// Was it neg?
|
||||
if (neg) number *= -1;
|
||||
|
||||
return new JSONValue(number);
|
||||
}
|
||||
|
||||
// An object?
|
||||
else if (**data == L'{')
|
||||
{
|
||||
JSONObject object;
|
||||
|
||||
(*data)++;
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Whitespace at the start?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Special case - empty object
|
||||
if (object.size() == 0 && **data == L'}')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(object);
|
||||
}
|
||||
|
||||
// We want a string now...
|
||||
std::wstring name;
|
||||
if (!JSON::ExtractString(&(++(*data)), name))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Need a : now
|
||||
if (*((*data)++) != L':')
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The value is here
|
||||
JSONValue *value = Parse(data);
|
||||
if (value == NULL)
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add the name:value
|
||||
if (object.find(name) != object.end())
|
||||
delete object[name];
|
||||
object[name] = value;
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// End of object?
|
||||
if (**data == L'}')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(object);
|
||||
}
|
||||
|
||||
// Want a , now
|
||||
if (**data != L',')
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Only here if we ran out of data
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// An array?
|
||||
else if (**data == L'[')
|
||||
{
|
||||
JSONArray array;
|
||||
|
||||
(*data)++;
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Whitespace at the start?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Special case - empty array
|
||||
if (array.size() == 0 && **data == L']')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(array);
|
||||
}
|
||||
|
||||
// Get the value
|
||||
JSONValue *value = Parse(data);
|
||||
if (value == NULL)
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add the value
|
||||
array.push_back(value);
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// End of array?
|
||||
if (**data == L']')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(array);
|
||||
}
|
||||
|
||||
// Want a , now
|
||||
if (**data != L',')
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Only here if we ran out of data
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Ran out of possibilites, it's bad!
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type NULL
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
JSONValue::JSONValue(/*NULL*/)
|
||||
{
|
||||
type = JSONType_Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param wchar_t* m_char_value The string to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const wchar_t *m_char_value)
|
||||
{
|
||||
type = JSONType_String;
|
||||
string_value = new std::wstring(std::wstring(m_char_value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param std::wstring m_string_value The string to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const std::wstring &m_string_value)
|
||||
{
|
||||
type = JSONType_String;
|
||||
string_value = new std::wstring(m_string_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Bool
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param bool m_bool_value The bool to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(bool m_bool_value)
|
||||
{
|
||||
type = JSONType_Bool;
|
||||
bool_value = m_bool_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Number
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param double m_number_value The number to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(double m_number_value)
|
||||
{
|
||||
type = JSONType_Number;
|
||||
number_value = m_number_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Number
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param int m_integer_value The number to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(int m_integer_value)
|
||||
{
|
||||
type = JSONType_Number;
|
||||
number_value = (double) m_integer_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Array
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONArray m_array_value The JSONArray to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const JSONArray &m_array_value)
|
||||
{
|
||||
type = JSONType_Array;
|
||||
array_value = new JSONArray(m_array_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Object
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONObject m_object_value The JSONObject to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const JSONObject &m_object_value)
|
||||
{
|
||||
type = JSONType_Object;
|
||||
object_value = new JSONObject(m_object_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor to perform a deep copy of array / object values
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONValue m_source The source JSONValue that is being copied
|
||||
*/
|
||||
JSONValue::JSONValue(const JSONValue &m_source)
|
||||
{
|
||||
type = m_source.type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case JSONType_String:
|
||||
string_value = new std::wstring(*m_source.string_value);
|
||||
break;
|
||||
|
||||
case JSONType_Bool:
|
||||
bool_value = m_source.bool_value;
|
||||
break;
|
||||
|
||||
case JSONType_Number:
|
||||
number_value = m_source.number_value;
|
||||
break;
|
||||
|
||||
case JSONType_Array:
|
||||
{
|
||||
JSONArray source_array = *m_source.array_value;
|
||||
JSONArray::iterator iter;
|
||||
array_value = new JSONArray();
|
||||
for (iter = source_array.begin(); iter != source_array.end(); iter++)
|
||||
array_value->push_back(new JSONValue(**iter));
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Object:
|
||||
{
|
||||
JSONObject source_object = *m_source.object_value;
|
||||
object_value = new JSONObject();
|
||||
JSONObject::iterator iter;
|
||||
for (iter = source_object.begin(); iter != source_object.end(); iter++)
|
||||
{
|
||||
std::wstring name = (*iter).first;
|
||||
(*object_value)[name] = new JSONValue(*((*iter).second));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Null:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The destructor for the JSON Value object
|
||||
* Handles deleting the objects in the array or the object value
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
JSONValue::~JSONValue()
|
||||
{
|
||||
if (type == JSONType_Array)
|
||||
{
|
||||
JSONArray::iterator iter;
|
||||
for (iter = array_value->begin(); iter != array_value->end(); iter++)
|
||||
delete *iter;
|
||||
delete array_value;
|
||||
}
|
||||
else if (type == JSONType_Object)
|
||||
{
|
||||
JSONObject::iterator iter;
|
||||
for (iter = object_value->begin(); iter != object_value->end(); iter++)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
delete object_value;
|
||||
}
|
||||
else if (type == JSONType_String)
|
||||
{
|
||||
delete string_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a NULL
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a NULL value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsNull() const
|
||||
{
|
||||
return type == JSONType_Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a String value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsString() const
|
||||
{
|
||||
return type == JSONType_String;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a Bool
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a Bool value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsBool() const
|
||||
{
|
||||
return type == JSONType_Bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a Number
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a Number value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsNumber() const
|
||||
{
|
||||
return type == JSONType_Number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is an Array
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is an Array value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsArray() const
|
||||
{
|
||||
return type == JSONType_Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is an Object
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is an Object value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsObject() const
|
||||
{
|
||||
return type == JSONType_Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the String value of this JSONValue
|
||||
* Use IsString() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return std::wstring Returns the string value
|
||||
*/
|
||||
const std::wstring &JSONValue::AsString() const
|
||||
{
|
||||
return (*string_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Bool value of this JSONValue
|
||||
* Use IsBool() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns the bool value
|
||||
*/
|
||||
bool JSONValue::AsBool() const
|
||||
{
|
||||
return bool_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Number value of this JSONValue
|
||||
* Use IsNumber() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return double Returns the number value
|
||||
*/
|
||||
double JSONValue::AsNumber() const
|
||||
{
|
||||
return number_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Array value of this JSONValue
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONArray Returns the array value
|
||||
*/
|
||||
const JSONArray &JSONValue::AsArray() const
|
||||
{
|
||||
return (*array_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Object value of this JSONValue
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONObject Returns the object value
|
||||
*/
|
||||
const JSONObject &JSONValue::AsObject() const
|
||||
{
|
||||
return (*object_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of children of this JSONValue.
|
||||
* This number will be 0 or the actual number of children
|
||||
* if IsArray() or IsObject().
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return The number of children.
|
||||
*/
|
||||
std::size_t JSONValue::CountChildren() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case JSONType_Array:
|
||||
return array_value->size();
|
||||
case JSONType_Object:
|
||||
return object_value->size();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this JSONValue has a child at the given index.
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if the array has a value at the given index.
|
||||
*/
|
||||
bool JSONValue::HasChild(std::size_t index) const
|
||||
{
|
||||
if (type == JSONType_Array)
|
||||
{
|
||||
return index < array_value->size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the child of this JSONValue at the given index.
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONValue* Returns JSONValue at the given index or NULL
|
||||
* if it doesn't exist.
|
||||
*/
|
||||
JSONValue *JSONValue::Child(std::size_t index)
|
||||
{
|
||||
if (index < array_value->size())
|
||||
{
|
||||
return (*array_value)[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this JSONValue has a child at the given key.
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if the object has a value at the given key.
|
||||
*/
|
||||
bool JSONValue::HasChild(const wchar_t* name) const
|
||||
{
|
||||
if (type == JSONType_Object)
|
||||
{
|
||||
return object_value->find(name) != object_value->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the child of this JSONValue at the given key.
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONValue* Returns JSONValue for the given key in the object
|
||||
* or NULL if it doesn't exist.
|
||||
*/
|
||||
JSONValue* JSONValue::Child(const wchar_t* name)
|
||||
{
|
||||
JSONObject::const_iterator it = object_value->find(name);
|
||||
if (it != object_value->end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the keys of the JSON Object or an empty vector
|
||||
* if this value is not an object.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return std::vector<std::wstring> A vector containing the keys.
|
||||
*/
|
||||
std::vector<std::wstring> JSONValue::ObjectKeys() const
|
||||
{
|
||||
std::vector<std::wstring> keys;
|
||||
|
||||
if (type == JSONType_Object)
|
||||
{
|
||||
JSONObject::const_iterator iter = object_value->begin();
|
||||
while (iter != object_value->end())
|
||||
{
|
||||
keys.push_back(iter->first);
|
||||
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded string for the value with all necessary characters escaped
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param bool prettyprint Enable prettyprint
|
||||
*
|
||||
* @return std::wstring Returns the JSON string
|
||||
*/
|
||||
std::wstring JSONValue::Stringify(bool const prettyprint) const
|
||||
{
|
||||
size_t const indentDepth = prettyprint ? 1 : 0;
|
||||
return StringifyImpl(indentDepth);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded string for the value with all necessary characters escaped
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param size_t indentDepth The prettyprint indentation depth (0 : no prettyprint)
|
||||
*
|
||||
* @return std::wstring Returns the JSON string
|
||||
*/
|
||||
std::wstring JSONValue::StringifyImpl(size_t const indentDepth) const
|
||||
{
|
||||
std::wstring ret_string;
|
||||
size_t const indentDepth1 = indentDepth ? indentDepth + 1 : 0;
|
||||
std::wstring const indentStr = Indent(indentDepth);
|
||||
std::wstring const indentStr1 = Indent(indentDepth1);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case JSONType_Null:
|
||||
ret_string = L"null";
|
||||
break;
|
||||
|
||||
case JSONType_String:
|
||||
ret_string = StringifyString(*string_value);
|
||||
break;
|
||||
|
||||
case JSONType_Bool:
|
||||
ret_string = bool_value ? L"true" : L"false";
|
||||
break;
|
||||
|
||||
case JSONType_Number:
|
||||
{
|
||||
if (isinf(number_value) || isnan(number_value))
|
||||
ret_string = L"null";
|
||||
else
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss.precision(15);
|
||||
ss << number_value;
|
||||
ret_string = ss.str();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Array:
|
||||
{
|
||||
ret_string = indentDepth ? L"[\n" + indentStr1 : L"[";
|
||||
JSONArray::const_iterator iter = array_value->begin();
|
||||
while (iter != array_value->end())
|
||||
{
|
||||
ret_string += (*iter)->StringifyImpl(indentDepth1);
|
||||
|
||||
// Not at the end - add a separator
|
||||
if (++iter != array_value->end())
|
||||
ret_string += L",";
|
||||
}
|
||||
ret_string += indentDepth ? L"\n" + indentStr + L"]" : L"]";
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Object:
|
||||
{
|
||||
ret_string = indentDepth ? L"{\n" + indentStr1 : L"{";
|
||||
JSONObject::const_iterator iter = object_value->begin();
|
||||
while (iter != object_value->end())
|
||||
{
|
||||
ret_string += StringifyString((*iter).first);
|
||||
ret_string += L":";
|
||||
ret_string += (*iter).second->StringifyImpl(indentDepth1);
|
||||
|
||||
// Not at the end - add a separator
|
||||
if (++iter != object_value->end())
|
||||
ret_string += L",";
|
||||
}
|
||||
ret_string += indentDepth ? L"\n" + indentStr + L"}" : L"}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded string with all required fields escaped
|
||||
* Works from http://www.ecma-internationl.org/publications/files/ECMA-ST/ECMA-262.pdf
|
||||
* Section 15.12.3.
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param std::wstring str The string that needs to have the characters escaped
|
||||
*
|
||||
* @return std::wstring Returns the JSON string
|
||||
*/
|
||||
std::wstring JSONValue::StringifyString(const std::wstring &str)
|
||||
{
|
||||
std::wstring str_out = L"\"";
|
||||
|
||||
std::wstring::const_iterator iter = str.begin();
|
||||
while (iter != str.end())
|
||||
{
|
||||
wchar_t chr = *iter;
|
||||
|
||||
if (chr == L'"' || chr == L'\\' || chr == L'/')
|
||||
{
|
||||
str_out += L'\\';
|
||||
str_out += chr;
|
||||
}
|
||||
else if (chr == L'\b')
|
||||
{
|
||||
str_out += L"\\b";
|
||||
}
|
||||
else if (chr == L'\f')
|
||||
{
|
||||
str_out += L"\\f";
|
||||
}
|
||||
else if (chr == L'\n')
|
||||
{
|
||||
str_out += L"\\n";
|
||||
}
|
||||
else if (chr == L'\r')
|
||||
{
|
||||
str_out += L"\\r";
|
||||
}
|
||||
else if (chr == L'\t')
|
||||
{
|
||||
str_out += L"\\t";
|
||||
}
|
||||
else if (chr < L' ' || chr > 126)
|
||||
{
|
||||
str_out += L"\\u";
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int value = (chr >> 12) & 0xf;
|
||||
if (value >= 0 && value <= 9)
|
||||
str_out += (wchar_t)('0' + value);
|
||||
else if (value >= 10 && value <= 15)
|
||||
str_out += (wchar_t)('A' + (value - 10));
|
||||
chr <<= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
str_out += chr;
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
str_out += L"\"";
|
||||
return str_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the indentation string for the depth given
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param size_t indent The prettyprint indentation depth (0 : no indentation)
|
||||
*
|
||||
* @return std::wstring Returns the string
|
||||
*/
|
||||
std::wstring JSONValue::Indent(size_t depth)
|
||||
{
|
||||
const size_t indent_step = 2;
|
||||
depth ? --depth : 0;
|
||||
std::wstring indentStr(depth * indent_step, ' ');
|
||||
return indentStr;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* File JSONValue.h part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _JSONVALUE_H_
|
||||
#define _JSONVALUE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "JSON.h"
|
||||
|
||||
class JSON;
|
||||
|
||||
enum JSONType { JSONType_Null, JSONType_String, JSONType_Bool, JSONType_Number, JSONType_Array, JSONType_Object };
|
||||
|
||||
class JSONValue
|
||||
{
|
||||
friend class JSON;
|
||||
|
||||
public:
|
||||
JSONValue(/*NULL*/);
|
||||
JSONValue(const wchar_t *m_char_value);
|
||||
JSONValue(const std::wstring &m_string_value);
|
||||
JSONValue(bool m_bool_value);
|
||||
JSONValue(double m_number_value);
|
||||
JSONValue(int m_integer_value);
|
||||
JSONValue(const JSONArray &m_array_value);
|
||||
JSONValue(const JSONObject &m_object_value);
|
||||
JSONValue(const JSONValue &m_source);
|
||||
~JSONValue();
|
||||
|
||||
bool IsNull() const;
|
||||
bool IsString() const;
|
||||
bool IsBool() const;
|
||||
bool IsNumber() const;
|
||||
bool IsArray() const;
|
||||
bool IsObject() const;
|
||||
|
||||
const std::wstring &AsString() const;
|
||||
bool AsBool() const;
|
||||
double AsNumber() const;
|
||||
const JSONArray &AsArray() const;
|
||||
const JSONObject &AsObject() const;
|
||||
|
||||
std::size_t CountChildren() const;
|
||||
bool HasChild(std::size_t index) const;
|
||||
JSONValue *Child(std::size_t index);
|
||||
bool HasChild(const wchar_t* name) const;
|
||||
JSONValue *Child(const wchar_t* name);
|
||||
std::vector<std::wstring> ObjectKeys() const;
|
||||
|
||||
std::wstring Stringify(bool const prettyprint = false) const;
|
||||
protected:
|
||||
static JSONValue *Parse(const wchar_t **data);
|
||||
|
||||
private:
|
||||
static std::wstring StringifyString(const std::wstring &str);
|
||||
std::wstring StringifyImpl(size_t const indentDepth) const;
|
||||
static std::wstring Indent(size_t depth);
|
||||
|
||||
JSONType type;
|
||||
|
||||
union
|
||||
{
|
||||
bool bool_value;
|
||||
double number_value;
|
||||
std::wstring *string_value;
|
||||
JSONArray *array_value;
|
||||
JSONObject *object_value;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -49,10 +49,23 @@ ULONG DriverAssist::StartDriverAsync(void *arg)
|
|||
// get windows version
|
||||
//
|
||||
|
||||
OSVERSIONINFO osvi;
|
||||
OSVERSIONINFOW osvi;
|
||||
memzero(&osvi, sizeof(osvi));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osvi);
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOW);
|
||||
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetVersion");
|
||||
if (RtlGetVersion == NULL || !NT_SUCCESS(RtlGetVersion(&osvi)))
|
||||
GetVersionExW(&osvi);
|
||||
|
||||
//
|
||||
// get own path
|
||||
//
|
||||
|
||||
WCHAR svcPath[MAX_PATH] = { 0 };
|
||||
GetModuleFileName(NULL, svcPath, MAX_PATH);
|
||||
WCHAR* pathPtr = wcsrchr(svcPath, L'\\');
|
||||
if (pathPtr++)
|
||||
*pathPtr = L'\0';
|
||||
|
||||
//
|
||||
// start the driver, but only if it isn't already active
|
||||
|
@ -76,46 +89,132 @@ ULONG DriverAssist::StartDriverAsync(void *arg)
|
|||
L"\\Registry\\Machine\\System\\CurrentControlSet"
|
||||
L"\\Services\\" SBIEDRV);
|
||||
|
||||
rc = NtLoadDriver(&uni);
|
||||
if (rc == 0 || rc == STATUS_IMAGE_ALREADY_LOADED) {
|
||||
ok = true;
|
||||
goto driver_started;
|
||||
}
|
||||
//while (!IsDebuggerPresent())
|
||||
// Sleep(100);
|
||||
|
||||
if (rc != STATUS_PRIVILEGE_NOT_HELD || rc == STATUS_ACCESS_DENIED) {
|
||||
LogEvent(MSG_9234, 0x9153, rc);
|
||||
goto driver_started;
|
||||
}
|
||||
m_instance->LogMessage_Single(MSG_2201, L"Starting Driver...");
|
||||
|
||||
//
|
||||
// we have to enable a privilege to load the driver
|
||||
//
|
||||
bool PrivilegeSet = false;
|
||||
bool CopyDriver = false;
|
||||
bool DriverUnPacked = false;
|
||||
for (; ; ) //for (int i = 0; i < 10; i++)
|
||||
{
|
||||
m_instance->LogMessage_Single(MSG_2201, L"Attempting to Load Driver...");
|
||||
|
||||
WCHAR priv_space[64];
|
||||
TOKEN_PRIVILEGES *privs = (TOKEN_PRIVILEGES *)priv_space;
|
||||
HANDLE hToken;
|
||||
rc = NtLoadDriver(&uni);
|
||||
if (rc == 0 || rc == STATUS_IMAGE_ALREADY_LOADED) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
BOOL b = LookupPrivilegeValue(
|
||||
L"", SE_LOAD_DRIVER_NAME, &privs->Privileges[0].Luid);
|
||||
if (b) {
|
||||
if (rc == STATUS_PRIVILEGE_NOT_HELD && !PrivilegeSet)
|
||||
{
|
||||
m_instance->LogMessage_Single(MSG_2201, L"Acquiring necessary privileges...");
|
||||
|
||||
privs->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
privs->PrivilegeCount = 1;
|
||||
//
|
||||
// we have to enable a privilege to load the driver
|
||||
//
|
||||
|
||||
b = OpenProcessToken(
|
||||
GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
|
||||
if (b) {
|
||||
WCHAR priv_space[64];
|
||||
TOKEN_PRIVILEGES *privs = (TOKEN_PRIVILEGES *)priv_space;
|
||||
HANDLE hToken;
|
||||
|
||||
b = AdjustTokenPrivileges(hToken, FALSE, privs, 0, NULL, NULL);
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
}
|
||||
BOOL b = LookupPrivilegeValue(
|
||||
L"", SE_LOAD_DRIVER_NAME, &privs->Privileges[0].Luid);
|
||||
if (b) {
|
||||
|
||||
rc = NtLoadDriver(&uni);
|
||||
if (rc == 0 || rc == STATUS_IMAGE_ALREADY_LOADED)
|
||||
ok = true;
|
||||
else
|
||||
LogEvent(MSG_9234, 0x9153, rc);
|
||||
privs->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
privs->PrivilegeCount = 1;
|
||||
|
||||
b = OpenProcessToken(
|
||||
GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
|
||||
if (b) {
|
||||
|
||||
b = AdjustTokenPrivileges(hToken, FALSE, privs, 0, NULL, NULL);
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
}
|
||||
|
||||
PrivilegeSet = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (rc == STATUS_OBJECT_NAME_NOT_FOUND && DriverUnPacked)
|
||||
{
|
||||
m_instance->LogMessage_Single(MSG_2201, L"The provisionally driver got deleted...");
|
||||
|
||||
//
|
||||
// The provisionally signed driver got deleted, try to restore it
|
||||
//
|
||||
|
||||
DriverUnPacked = false;
|
||||
rc == STATUS_INVALID_IMAGE_HASH;
|
||||
}*/
|
||||
|
||||
if (rc == STATUS_OBJECT_NAME_NOT_FOUND && !CopyDriver)
|
||||
{
|
||||
m_instance->LogMessage_Single(MSG_2201, L"Preparing the windows 10 signed driver...");
|
||||
|
||||
//
|
||||
// there is no driver file we have to prepare one
|
||||
//
|
||||
|
||||
WCHAR srcPath[MAX_PATH];
|
||||
wcscpy(srcPath, svcPath);
|
||||
wcscat(srcPath, SBIEDRV_SYS L".w10");
|
||||
|
||||
WCHAR destPath[MAX_PATH];
|
||||
wcscpy(destPath, svcPath);
|
||||
wcscat(destPath, SBIEDRV_SYS);
|
||||
|
||||
CopyFile(srcPath, destPath, FALSE);
|
||||
|
||||
CopyDriver = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rc == STATUS_INVALID_IMAGE_HASH && !DriverUnPacked)
|
||||
{
|
||||
m_instance->LogMessage_Single(MSG_2201, L"Preparing the provisionally signed driver...");
|
||||
|
||||
//
|
||||
// the driver signature was not accepted, try the provisionally signed driver
|
||||
//
|
||||
|
||||
WCHAR cmd[512];
|
||||
wcscpy(cmd, L"\"");
|
||||
wcscat(cmd, svcPath);
|
||||
wcscat(cmd, L"KmdUtil.exe");
|
||||
wcscat(cmd, L"\" rc4 \"");
|
||||
wcscat(cmd, svcPath);
|
||||
wcscat(cmd, SBIEDRV_SYS L".rc4");
|
||||
wcscat(cmd, L"\"");
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_FORCEOFFFEEDBACK;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
|
||||
WaitForSingleObject(pi.hProcess, 10 * 1000);
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
|
||||
DriverUnPacked = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// we tryed all we could, log an error and break
|
||||
//
|
||||
|
||||
LogEvent(MSG_9234, 0x9153, rc);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// the driver has been started (or was started already), check
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 2004-2020 Sandboxie Holdings, LLC
|
||||
* Copyright 2020 David Xanatos, xanasoft.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include <sddl.h>
|
||||
#include <aclapi.h>
|
||||
#include <dde.h>
|
||||
#include "misc.h"
|
||||
|
||||
#define PATTERN XPATTERN
|
||||
extern "C" {
|
||||
|
@ -87,9 +89,14 @@ GuiServer::GuiServer()
|
|||
m_ParentPid = 0;
|
||||
m_SessionId = 0;
|
||||
|
||||
OSVERSIONINFO osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&osvi);
|
||||
OSVERSIONINFOW osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
|
||||
/*NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOW);
|
||||
*(FARPROC*)&RtlGetVersion = GetProcAddress(_Ntdll, "RtlGetVersion");
|
||||
if (RtlGetVersion != NULL)
|
||||
RtlGetVersion(&osvi);
|
||||
else*/
|
||||
GetVersionExW(&osvi); // since windows 10 this one is lying
|
||||
m_nOSVersion = osvi.dwMajorVersion * 10 + osvi.dwMinorVersion;
|
||||
}
|
||||
|
||||
|
@ -999,6 +1006,16 @@ HANDLE GuiServer::GetJobObjectForAssign(const WCHAR *boxname)
|
|||
| JOB_OBJECT_UILIMIT_READCLIPBOARD;
|
||||
|
||||
BOOL ok = FALSE; // set TRUE to skip UIRestrictions
|
||||
|
||||
// OpenToken BEGIN
|
||||
if ((SbieApi_QueryConfBool(boxname, L"OpenToken", FALSE) || SbieApi_QueryConfBool(boxname, L"UnrestrictedToken", FALSE)))
|
||||
ok = TRUE;
|
||||
// OpenToken END
|
||||
// OriginalToken BEGIN
|
||||
if (SbieApi_QueryConfBool(boxname, L"OriginalToken", FALSE))
|
||||
ok = TRUE;
|
||||
// OriginalToken END
|
||||
|
||||
if (! ok) {
|
||||
ok = SetInformationJobObject(
|
||||
hJobObject, JobObjectBasicUIRestrictions,
|
||||
|
|
|
@ -38,6 +38,7 @@ SetCompressor /SOLID /FINAL lzma
|
|||
!define BIN_ROOT_BASE "${SBIE_INSTALLER_PATH}"
|
||||
|
||||
!define SBIEDRV_SYS4 "${SBIEDRV_SYS}.rc4"
|
||||
!define SBIEDRV_SYSX "${SBIEDRV_SYS}.w10"
|
||||
|
||||
!define OUTFILE_BOTH "${PRODUCT_NAME}Install.exe"
|
||||
!define NAME_Win32 "${PRODUCT_FULL_NAME} ${VERSION} (32-bit)"
|
||||
|
@ -431,7 +432,7 @@ InstDir_Check_Suffix:
|
|||
Push -12
|
||||
Pop $2
|
||||
StrCpy $1 $0 "" $2
|
||||
StrCmp $1 "\${SBIEDRV_SYS4}" InstDir_Suffix_Good
|
||||
StrCmp $1 "\${SBIEDRV_SYS}" InstDir_Suffix_Good
|
||||
|
||||
Goto InstDir_ProgramFiles
|
||||
|
||||
|
@ -466,7 +467,7 @@ InstDir_Done:
|
|||
StrCmp "$EXEDIR" "$WINDIR\Installer\" InstType_Remove
|
||||
StrCmp "$EXEDIR\" "$WINDIR\Installer" InstType_Remove
|
||||
|
||||
IfFileExists $INSTDIR\${SBIEDRV_SYS4} InstType_Upgrade
|
||||
IfFileExists $INSTDIR\${SBIEDRV_SYS} InstType_Upgrade
|
||||
IfFileExists $INSTDIR\${SBIESVC_EXE} InstType_Upgrade
|
||||
IfFileExists $INSTDIR\${SBIEDLL_DLL} InstType_Upgrade
|
||||
|
||||
|
@ -971,6 +972,9 @@ WriteLoop:
|
|||
File /oname=${SBIEMSG_DLL} "${BIN_ROOT}\SbieMsg.dll"
|
||||
|
||||
File /oname=${SBIEDRV_SYS4} "${BIN_ROOT}\SbieDrv.sys.rc4"
|
||||
File /oname=${SBIEDRV_SYSX} "${BIN_ROOT}\SbieDrv.sys.w10"
|
||||
|
||||
File /oname=KmdUtil.exe "${BIN_ROOT}\KmdUtil.Exe"
|
||||
|
||||
File /oname=SboxHostDll.dll "${BIN_ROOT}\SboxHostDll.dll"
|
||||
|
||||
|
@ -1075,7 +1079,13 @@ Function DeleteProgramFiles
|
|||
|
||||
Delete "$INSTDIR\${SBIEMSG_DLL}"
|
||||
|
||||
Delete "$INSTDIR\${SBIEDRV_SYS}"
|
||||
Delete "$INSTDIR\${SBIEDRV_SYS4}"
|
||||
Delete "$INSTDIR\${SBIEDRV_SYSX}"
|
||||
|
||||
Delete "$INSTDIR\KmdUtil.exe"
|
||||
|
||||
Delete "$INSTDIR\boxHostDll.dll"
|
||||
|
||||
Delete "$INSTDIR\${SANDBOXIE}WUAU.exe"
|
||||
Delete "$INSTDIR\${SANDBOXIE}EventSys.exe"
|
||||
|
@ -1425,7 +1435,7 @@ Driver_Silent:
|
|||
; For Install and Upgrade, install the driver
|
||||
;
|
||||
|
||||
StrCpy $0 'install ${SBIEDRV} "$INSTDIR\${SBIEDRV_SYS4}" type=kernel start=demand "msgfile=$INSTDIR\${SBIEMSG_DLL}" altitude=${FILTER_ALTITUDE}'
|
||||
StrCpy $0 'install ${SBIEDRV} "$INSTDIR\${SBIEDRV_SYS}" type=kernel start=demand "msgfile=$INSTDIR\${SBIEMSG_DLL}" altitude=${FILTER_ALTITUDE}'
|
||||
Push $0
|
||||
Call KmdUtil
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ typedef enum _COMMAND {
|
|||
CMD_START,
|
||||
CMD_STOP,
|
||||
CMD_SCANDLL,
|
||||
CMD_SCANDLL_SILENT
|
||||
CMD_SCANDLL_SILENT,
|
||||
CMD_RC4
|
||||
} COMMAND;
|
||||
|
||||
typedef enum _OPTIONS {
|
||||
|
@ -219,7 +220,11 @@ BOOL Parse_Command_Line(
|
|||
*Command = CMD_STOP;
|
||||
num_args_needed = 1;
|
||||
|
||||
} else {
|
||||
} else if (_wcsicmp(args[1], L"rc4") == 0) {
|
||||
*Command = CMD_RC4;
|
||||
num_args_needed = 1;
|
||||
|
||||
} else {
|
||||
*Command = CMD_ERROR;
|
||||
MessageBox(NULL, L"Invalid command", L"KmdUtil",
|
||||
MB_ICONEXCLAMATION | MB_OK);
|
||||
|
@ -238,6 +243,11 @@ BOOL Parse_Command_Line(
|
|||
if (num_args_needed >= 2)
|
||||
*Driver_Path = args[3];
|
||||
|
||||
if (*Command == CMD_RC4) {
|
||||
*Driver_Path = *Driver_Name;
|
||||
*Driver_Name = NULL;
|
||||
}
|
||||
|
||||
*Options = OPT_NONE;
|
||||
next_arg = num_args_needed + 2;
|
||||
while (next_arg < num_args_given) {
|
||||
|
@ -716,41 +726,46 @@ int __stdcall WinMain(
|
|||
&Options))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (Driver_Path)
|
||||
if (Command == CMD_RC4)
|
||||
{
|
||||
int path_len = wcslen(Driver_Path);
|
||||
if (path_len > 8 && wcscmp(Driver_Path + path_len - 8, L".sys.rc4") == 0)
|
||||
BOOLEAN has_rc4 = path_len > 8 && wcscmp(Driver_Path + path_len - 8, L".sys.rc4") == 0;
|
||||
|
||||
PWSTR Driver_Path_tmp = Driver_Path; // strip \??\ if present
|
||||
if (Driver_Path_tmp[0] == L'\\' && Driver_Path_tmp[1] == L'?' && Driver_Path_tmp[2] == L'?' && Driver_Path_tmp[3] == L'\\')
|
||||
Driver_Path_tmp += 4;
|
||||
|
||||
FILE* inFile = _wfopen(Driver_Path_tmp, L"rb");
|
||||
if (inFile)
|
||||
{
|
||||
PWSTR Driver_Path_tmp = Driver_Path; // strip \??\ if present
|
||||
if (Driver_Path_tmp[0] == L'\\' && Driver_Path_tmp[1] == L'?' && Driver_Path_tmp[2] == L'?' && Driver_Path_tmp[3] == L'\\')
|
||||
Driver_Path_tmp += 4;
|
||||
|
||||
FILE* inFile = _wfopen(Driver_Path_tmp, L"rb");
|
||||
if (inFile)
|
||||
{
|
||||
if (has_rc4)
|
||||
Driver_Path_tmp[path_len - 4] = L'\0'; // strip .rc4
|
||||
FILE* outFile = _wfopen(Driver_Path_tmp, L"wb");
|
||||
if (outFile)
|
||||
{
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
DWORD fileSize = ftell(inFile);
|
||||
fseek(inFile, 0, SEEK_SET);
|
||||
else
|
||||
wcscat(Driver_Path_tmp, L".rc4"); // add .rc4
|
||||
FILE* outFile = _wfopen(Driver_Path_tmp, L"wb");
|
||||
if (outFile)
|
||||
{
|
||||
fseek(inFile, 0, SEEK_END);
|
||||
DWORD fileSize = ftell(inFile);
|
||||
fseek(inFile, 0, SEEK_SET);
|
||||
|
||||
void* buffer = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, fileSize);
|
||||
fread(buffer, 1, fileSize, inFile);
|
||||
void* buffer = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, fileSize);
|
||||
fread(buffer, 1, fileSize, inFile);
|
||||
|
||||
char key[] = "default_key";
|
||||
rc4_sbox_t sbox;
|
||||
rc4_init(&sbox, key, strlen(key));
|
||||
rc4_transform(&sbox, buffer, fileSize);
|
||||
char key[] = "default_key";
|
||||
rc4_sbox_t sbox;
|
||||
rc4_init(&sbox, key, strlen(key));
|
||||
rc4_transform(&sbox, buffer, fileSize);
|
||||
|
||||
fwrite(buffer, 1, fileSize, outFile);
|
||||
if(fwrite(buffer, 1, fileSize, outFile) == fileSize)
|
||||
ok = TRUE;
|
||||
|
||||
fclose(outFile);
|
||||
}
|
||||
fclose(inFile);
|
||||
fclose(outFile);
|
||||
}
|
||||
fclose(inFile);
|
||||
}
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ScMgr = OpenSCManager(
|
||||
|
@ -795,6 +810,7 @@ int __stdcall WinMain(
|
|||
if (Command == CMD_STOP)
|
||||
ok = Kmd_Stop_Service(Driver_Name);
|
||||
|
||||
exit:
|
||||
if (! ok)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -138,6 +138,18 @@ void CCheckableMessageBox::setIconPixmap(const QPixmap &p)
|
|||
d->pixmapLabel->setVisible(!p.isNull());
|
||||
}
|
||||
|
||||
Qt::TextFormat CCheckableMessageBox::textFormat() const
|
||||
{
|
||||
return d->messageLabel->textFormat();
|
||||
}
|
||||
|
||||
void CCheckableMessageBox::setTextFormat(Qt::TextFormat format)
|
||||
{
|
||||
d->messageLabel->setTextFormat(format);
|
||||
d->messageLabel->setWordWrap(format == Qt::RichText
|
||||
|| (format == Qt::AutoText && Qt::mightBeRichText(d->messageLabel->text())));
|
||||
}
|
||||
|
||||
bool CCheckableMessageBox::isChecked() const
|
||||
{
|
||||
return d->checkBox->isChecked();
|
||||
|
|
|
@ -12,6 +12,7 @@ class MISCHELPERS_EXPORT CCheckableMessageBox : public QDialog
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString text READ text WRITE setText)
|
||||
Q_PROPERTY(Qt::TextFormat textFormat READ textFormat WRITE setTextFormat)
|
||||
Q_PROPERTY(QPixmap iconPixmap READ iconPixmap WRITE setIconPixmap)
|
||||
Q_PROPERTY(bool isChecked READ isChecked WRITE setChecked)
|
||||
Q_PROPERTY(QString checkBoxText READ checkBoxText WRITE setCheckBoxText)
|
||||
|
@ -35,6 +36,9 @@ public:
|
|||
QString text() const;
|
||||
void setText(const QString &);
|
||||
|
||||
Qt::TextFormat textFormat() const;
|
||||
void setTextFormat(Qt::TextFormat format);
|
||||
|
||||
bool isChecked() const;
|
||||
void setChecked(bool s);
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
#include "stdafx.h"
|
||||
#include "NetworkAccessManager.h"
|
||||
#include "Common.h"
|
||||
|
||||
CNetworkAccessManager::CNetworkAccessManager(int TimeOut, QObject* parent)
|
||||
:QNetworkAccessManager(parent)
|
||||
{
|
||||
m_TimeOut = TimeOut;
|
||||
connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedRequest(QNetworkReply*)));
|
||||
#ifndef QT_NO_OPENSSL
|
||||
connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(sslErrors(QNetworkReply*, const QList<QSslError>&)));
|
||||
#endif
|
||||
|
||||
m_uTimerID = startTimer(1000);
|
||||
}
|
||||
|
||||
CNetworkAccessManager::~CNetworkAccessManager()
|
||||
{
|
||||
killTimer(m_uTimerID);
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::timerEvent(QTimerEvent* pEvent)
|
||||
{
|
||||
if (pEvent->timerId() != m_uTimerID)
|
||||
return;
|
||||
|
||||
foreach(QNetworkReply *pReply, m_Requests.keys())
|
||||
{
|
||||
if(m_Requests[pReply] < GetCurTick())
|
||||
pReply->abort();
|
||||
}
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::SetTimeOut(QNetworkReply *pReply)
|
||||
{
|
||||
m_Requests[pReply] = GetCurTick() + m_TimeOut;
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::StopTimeOut(QNetworkReply *pReply)
|
||||
{
|
||||
m_Requests.remove(pReply);
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::Abort(QNetworkReply *pReply)
|
||||
{
|
||||
pReply->abort();
|
||||
StopTimeOut(pReply);
|
||||
pReply->deleteLater();
|
||||
}
|
||||
|
||||
QNetworkReply* CNetworkAccessManager::createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData )
|
||||
{
|
||||
QNetworkReply* pReply = QNetworkAccessManager::createRequest(op, req, outgoingData);
|
||||
connect(pReply, SIGNAL(downloadProgress (qint64, qint64)), this, SLOT(OnData(qint64, qint64)));
|
||||
connect(pReply, SIGNAL(uploadProgress (qint64, qint64)), this, SLOT(OnData(qint64, qint64)));
|
||||
SetTimeOut(pReply);
|
||||
return pReply;
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::finishedRequest(QNetworkReply *pReply)
|
||||
{
|
||||
StopTimeOut(pReply);
|
||||
}
|
||||
|
||||
void CNetworkAccessManager::OnData(qint64 bytesSent, qint64 bytesTotal)
|
||||
{
|
||||
// Reset TimeOut, as long as data are being transferred its not a timeout
|
||||
SetTimeOut((QNetworkReply*)sender());
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void CNetworkAccessManager::sslErrors(QNetworkReply *pReply, const QList<QSslError> &error)
|
||||
{
|
||||
//pReply->ignoreSslErrors();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "../mischelpers_global.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
class MISCHELPERS_EXPORT CNetworkAccessManager : public QNetworkAccessManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CNetworkAccessManager(int TimeOut, QObject* parent = NULL);
|
||||
~CNetworkAccessManager();
|
||||
|
||||
void Abort(QNetworkReply* pReply);
|
||||
|
||||
private slots:
|
||||
void finishedRequest(QNetworkReply *pReply);
|
||||
void OnData(qint64 bytesSent, qint64 bytesTotal);
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void sslErrors(QNetworkReply *pReply, const QList<QSslError> &error);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent* pEvent);
|
||||
int m_uTimerID;
|
||||
|
||||
QNetworkReply* createRequest ( Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0 );
|
||||
|
||||
void SetTimeOut(QNetworkReply *pReply);
|
||||
void StopTimeOut(QNetworkReply *pReply);
|
||||
|
||||
int m_TimeOut;
|
||||
QMap<QNetworkReply*, quint64> m_Requests;
|
||||
};
|
|
@ -57,12 +57,12 @@ public slots:
|
|||
if (Progress == -1)
|
||||
{
|
||||
if (m_pProgressBar->maximum() != 0)
|
||||
m_pProgressBar->setMinimum(0);
|
||||
m_pProgressBar->setMaximum(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pProgressBar->maximum() != 100)
|
||||
m_pProgressBar->setMinimum(100);
|
||||
m_pProgressBar->setMaximum(100);
|
||||
|
||||
m_pProgressBar->setValue(Progress);
|
||||
}
|
||||
|
|
|
@ -191,6 +191,7 @@
|
|||
<ClCompile Include="Common\MultiLineInputDialog.cpp" />
|
||||
<ClCompile Include="Common\PanelView.cpp" />
|
||||
<ClCompile Include="Common\qRC4.cpp" />
|
||||
<ClCompile Include="Common\NetworkAccessManager.cpp" />
|
||||
<ClCompile Include="Common\Settings.cpp" />
|
||||
<ClCompile Include="Common\SettingsWidgets.cpp" />
|
||||
<ClCompile Include="Common\SmartGridWidget.cpp" />
|
||||
|
@ -233,6 +234,7 @@
|
|||
<QtMoc Include="Common\TreeWidgetEx.h" />
|
||||
<ClInclude Include="Common\IconExtreactor.h" />
|
||||
<ClInclude Include="Common\qRC4.h" />
|
||||
<QtMoc Include="Common\NetworkAccessManager.h" />
|
||||
<ClInclude Include="Common\Xml.h" />
|
||||
<ClInclude Include="MiscHelpers.h" />
|
||||
<ClInclude Include="mischelpers_global.h" />
|
||||
|
|
|
@ -90,6 +90,9 @@
|
|||
<ClCompile Include="Common\qRC4.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\NetworkAccessManager.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MiscHelpers.h">
|
||||
|
@ -186,5 +189,8 @@
|
|||
<QtMoc Include="Common\TreeWidgetEx.h">
|
||||
<Filter>Common</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Common\NetworkAccessManager.h">
|
||||
<Filter>Common</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -181,7 +181,7 @@ QList<SBoxSnapshot> CSandBox::GetSnapshots(QString* pCurrent) const
|
|||
|
||||
BoxSnapshot.NameStr = ini.value(Snapshot + "/Name").toString();
|
||||
BoxSnapshot.InfoStr = ini.value(Snapshot + "/Description").toString();
|
||||
BoxSnapshot.SnapDate = ini.value(Snapshot + "/SnapshotDate").toDateTime();
|
||||
BoxSnapshot.SnapDate = QDateTime::fromTime_t(ini.value(Snapshot + "/SnapshotDate").toULongLong());
|
||||
|
||||
Snapshots.append(BoxSnapshot);
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ SB_PROGRESS CSandBox::TakeSnapshot(const QString& Name)
|
|||
return SB_ERR(tr("Failed to copy RegHive to snapshot"));
|
||||
|
||||
ini.setValue("Snapshot_" + ID + "/Name", Name);
|
||||
ini.setValue("Snapshot_" + ID + "/SnapshotDate", QDateTime::currentDateTime());
|
||||
ini.setValue("Snapshot_" + ID + "/SnapshotDate", QDateTime::currentDateTime().toTime_t());
|
||||
QString Current = ini.value("Current/Snapshot").toString();
|
||||
if(!Current.isEmpty())
|
||||
ini.setValue("Snapshot_" + ID + "/Parent", Current);
|
||||
|
|
|
@ -72,10 +72,11 @@ SB_STATUS CSbieUtils::Start(EComponent Component)
|
|||
|
||||
void CSbieUtils::Start(EComponent Component, QStringList& Ops)
|
||||
{
|
||||
if ((Component & eDriver) != 0 && GetServiceStatus(SBIEDRV) != SERVICE_RUNNING)
|
||||
Ops.append(QString::fromWCharArray(L"kmdutil.exe|start|" SBIEDRV));
|
||||
// Note: Service aways starts the driver
|
||||
if ((Component & eService) != 0 && GetServiceStatus(SBIESVC) != SERVICE_RUNNING)
|
||||
Ops.append(QString::fromWCharArray(L"kmdutil.exe|start|" SBIESVC));
|
||||
else if ((Component & eDriver) != 0 && GetServiceStatus(SBIEDRV) != SERVICE_RUNNING)
|
||||
Ops.append(QString::fromWCharArray(L"kmdutil.exe|start|" SBIEDRV));
|
||||
}
|
||||
|
||||
SB_STATUS CSbieUtils::Stop(EComponent Component)
|
||||
|
@ -282,12 +283,12 @@ void CSbieUtils::RemoveContextMenu()
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Shortcuts
|
||||
|
||||
bool CreateShortcut(CSbieAPI* pApi, const QString &LinkPath, const QString &LinkName, const QString &boxname, const QString &arguments, const QString &iconPath, int iconIndex, const QString &workdir, BOOL run_elevated = 0)
|
||||
bool CSbieUtils::CreateShortcut(CSbieAPI* pApi, const QString &LinkPath, const QString &LinkName, const QString &boxname, const QString &arguments, const QString &iconPath, int iconIndex, const QString &workdir, bool bRunElevated)
|
||||
{
|
||||
QString StartExe = pApi->GetStartPath();
|
||||
|
||||
QString StartArgs;
|
||||
if (run_elevated)
|
||||
if (bRunElevated)
|
||||
StartArgs += "/elevated ";
|
||||
StartArgs += "/box:" + boxname;
|
||||
if (!arguments.isEmpty())
|
||||
|
@ -329,35 +330,7 @@ bool CreateShortcut(CSbieAPI* pApi, const QString &LinkPath, const QString &Link
|
|||
return (SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
void CreateDesktopShortcut(CSbieAPI* pApi, const QString &BoxName, const QString &LinkPath, const QString &IconPath, quint32 IconIndex, const QString &WorkDir)
|
||||
{
|
||||
WCHAR path[512];
|
||||
HRESULT hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, path);
|
||||
if (hr != 0 || *path == L'\0')
|
||||
return;
|
||||
|
||||
QString LinkName;
|
||||
int pos = LinkPath.lastIndexOf(L'\\');
|
||||
if (pos == -1)
|
||||
return;
|
||||
if (pos == 2 && LinkPath.length() == 3)
|
||||
LinkName = QObject::tr("Drive %1").arg(LinkPath.left(1));
|
||||
else {
|
||||
LinkName = LinkPath.mid(pos + 1);
|
||||
pos = LinkName.indexOf(QRegExp("[" + QRegExp::escape("\":;,*?.") + "]"));
|
||||
if (pos != -1)
|
||||
LinkName = LinkName.left(pos);
|
||||
}
|
||||
|
||||
QString Path = QString::fromWCharArray(path);
|
||||
if (Path.right(1) != "\\")
|
||||
Path.append("\\");
|
||||
Path += "[" + BoxName + "] " + LinkName;
|
||||
|
||||
CreateShortcut(pApi, Path, LinkName, BoxName, LinkPath , IconPath, IconIndex, WorkDir);
|
||||
}
|
||||
|
||||
bool GetStartMenuShortcut(CSbieAPI* pApi, QString &BoxName, QString &LinkPath, QString &IconPath, quint32& IconIndex, QString &WorkDir)
|
||||
bool CSbieUtils::GetStartMenuShortcut(CSbieAPI* pApi, QString &BoxName, QString &LinkPath, QString &IconPath, quint32& IconIndex, QString &WorkDir)
|
||||
{
|
||||
WCHAR MapName[128];
|
||||
wsprintf(MapName, SANDBOXIE L"_StartMenu_WorkArea_%08X_%08X", GetCurrentProcessId(), GetTickCount());
|
||||
|
@ -409,12 +382,4 @@ bool GetStartMenuShortcut(CSbieAPI* pApi, QString &BoxName, QString &LinkPath, Q
|
|||
if (BoxName.isEmpty() || LinkPath.isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSbieUtils::CreateDesktopShortcut(const QString& BoxName, CSbieAPI* pApi)
|
||||
{
|
||||
QString LinkPath, IconPath, WorkDir;
|
||||
quint32 IconIndex;
|
||||
if (::GetStartMenuShortcut(pApi, QString(BoxName), LinkPath, IconPath, IconIndex, WorkDir))
|
||||
::CreateDesktopShortcut(pApi, BoxName, LinkPath, IconPath, IconIndex, WorkDir);
|
||||
}
|
||||
}
|
|
@ -30,7 +30,8 @@ public:
|
|||
static void AddContextMenu(const QString& StartPath);
|
||||
static void RemoveContextMenu();
|
||||
|
||||
static void CreateDesktopShortcut(const QString& BoxName, class CSbieAPI* pApi);
|
||||
static bool CreateShortcut(class CSbieAPI* pApi, const QString &LinkPath, const QString &LinkName, const QString &boxname, const QString &arguments, const QString &iconPath, int iconIndex, const QString &workdir, bool bRunElevated = false);
|
||||
static bool GetStartMenuShortcut(class CSbieAPI* pApi, QString &BoxName, QString &LinkPath, QString &IconPath, quint32& IconIndex, QString &WorkDir);
|
||||
|
||||
private:
|
||||
static SB_STATUS ElevateOps(const QStringList& Ops);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<enum>QTabWidget::West</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>6</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<attribute name="title">
|
||||
|
@ -1300,20 +1300,7 @@ Note: Forced Programs and Force Folders settings for a sandbox do not apply to
|
|||
<layout class="QGridLayout" name="gridLayout_34">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_32">
|
||||
<item row="8" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
@ -1326,6 +1313,33 @@ Note: Forced Programs and Force Folders settings for a sandbox do not apply to
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="chkPipeTrace">
|
||||
<property name="text">
|
||||
<string>Pipe Trace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" rowspan="5">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Log all access events as seen by the driver to the resource access log.
|
||||
|
||||
This options set the event amsk to "*" - All access events
|
||||
You can customize the logging using the ini by specifying
|
||||
"A" - Allowed accesses
|
||||
"D" - Denidec accesses
|
||||
"I" - Ignore access requests
|
||||
instead of "*".</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="font">
|
||||
|
@ -1346,13 +1360,6 @@ Note: Forced Programs and Force Folders settings for a sandbox do not apply to
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="chkIpcTrace">
|
||||
<property name="text">
|
||||
<string>IPC Trace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="chkKeyTrace">
|
||||
<property name="text">
|
||||
|
@ -1360,13 +1367,6 @@ Note: Forced Programs and Force Folders settings for a sandbox do not apply to
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="chkPipeTrace">
|
||||
<property name="text">
|
||||
<string>Pipe Trace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="chkFileTrace">
|
||||
<property name="text">
|
||||
|
@ -1374,23 +1374,30 @@ Note: Forced Programs and Force Folders settings for a sandbox do not apply to
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" rowspan="5">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<item row="9" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="chkIpcTrace">
|
||||
<property name="text">
|
||||
<string>Log all access events as seen by the driver to the resource access log.
|
||||
|
||||
This options set the event amsk to "*" - All access events
|
||||
You can customize the logging using the ini by specifying
|
||||
"A" - Allowed accesses
|
||||
"D" - Denidec accesses
|
||||
"I" - Ignore access requests
|
||||
instead of "*".</string>
|
||||
<string>IPC Trace</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkDbgTrace">
|
||||
<property name="text">
|
||||
<string>Log Debug Output to the Trace Log</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -1419,8 +1426,8 @@ instead of "*".</string>
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>530</width>
|
||||
<height>251</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="dbgLayout">
|
||||
|
|
|
@ -54,6 +54,36 @@
|
|||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="5" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifications">
|
||||
<property name="text">
|
||||
<string>Show Notifications for relevant log Messages</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="chkShowTray">
|
||||
<property name="text">
|
||||
<string>Show Sys-Tray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="chkDarkTheme">
|
||||
<property name="text">
|
||||
|
@ -61,14 +91,27 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="chkShowTray">
|
||||
<item row="10" column="0">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkShellMenu">
|
||||
<property name="text">
|
||||
<string>Show Sys-Tray</string>
|
||||
<string>Add 'Run Sandboxed' to the explorer context menu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<item row="10" column="2">
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -81,16 +124,20 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Tray options</string>
|
||||
<string>On main window close:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="chkAutoStart">
|
||||
<property name="text">
|
||||
<string>Start with Windows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -104,76 +151,36 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="chkAutoStart">
|
||||
<property name="text">
|
||||
<string>Start with Windows</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>On main window close:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="onClose"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="uiLang"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="chkWatchConfig">
|
||||
<property name="text">
|
||||
<string>Watch Sandboxie.ini for changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkNotifications">
|
||||
<property name="text">
|
||||
<string>Show Notifications for relevant log Messages</string>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
<property name="text">
|
||||
<string>Tray options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="onClose"/>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="chkShellMenu">
|
||||
<widget class="QCheckBox" name="chkAutoUpdate">
|
||||
<property name="text">
|
||||
<string>Add 'Run Sandboxed' to the explorer context menu</string>
|
||||
<string>Check periodicaly for updates of Sandboxie-Plus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -66,12 +66,65 @@ bool CSbieModel::TestProcPath(const QList<QVariant>& Path, const QString& BoxNam
|
|||
return Path.size() == Index;
|
||||
}
|
||||
|
||||
QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList)
|
||||
QString CSbieModel::FindParent(const QVariant& Name, const QMap<QString, QStringList>& Groups)
|
||||
{
|
||||
for(auto I = Groups.begin(); I != Groups.end(); ++I)
|
||||
{
|
||||
if (I.value().contains(Name.toString(), Qt::CaseInsensitive))
|
||||
return I.key();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QList<QVariant> CSbieModel::MakeBoxPath(const QVariant& Name, const QMap<QString, QStringList>& Groups)
|
||||
{
|
||||
QString ParentID = FindParent(Name, Groups);
|
||||
|
||||
QList<QVariant> Path;
|
||||
if (!ParentID.isEmpty() && ParentID != Name)
|
||||
{
|
||||
Path = MakeBoxPath(ParentID, Groups);
|
||||
Path.append(ParentID);
|
||||
}
|
||||
return Path;
|
||||
}
|
||||
|
||||
QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList, const QMap<QString, QStringList>& Groups)
|
||||
{
|
||||
QList<QVariant> Added;
|
||||
QMap<QList<QVariant>, QList<STreeNode*> > New;
|
||||
QHash<QVariant, STreeNode*> Old = m_Map;
|
||||
|
||||
foreach(const QString& Group, Groups.keys())
|
||||
{
|
||||
if (Group.isEmpty())
|
||||
continue;
|
||||
QVariant ID = Group;
|
||||
|
||||
QHash<QVariant, STreeNode*>::iterator I = Old.find(ID);
|
||||
SSandBoxNode* pNode = I != Old.end() ? static_cast<SSandBoxNode*>(I.value()) : NULL;
|
||||
if (!pNode)
|
||||
{
|
||||
pNode = static_cast<SSandBoxNode*>(MkNode(ID));
|
||||
pNode->Values.resize(columnCount());
|
||||
if (m_bTree)
|
||||
pNode->Path = MakeBoxPath(ID, Groups);
|
||||
pNode->pBox = NULL;
|
||||
New[pNode->Path].append(pNode);
|
||||
Added.append(ID);
|
||||
|
||||
pNode->Icon = m_BoxIcons[eYelow].first;
|
||||
pNode->IsBold = true;
|
||||
|
||||
pNode->Values[eName].Raw = Group;
|
||||
pNode->Values[eStatus].Raw = tr("Box Groupe");
|
||||
}
|
||||
else
|
||||
{
|
||||
I.value() = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const CSandBoxPtr& pBox, BoxList)
|
||||
{
|
||||
QVariant ID = pBox->GetName();
|
||||
|
@ -84,6 +137,8 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList)
|
|||
{
|
||||
pNode = static_cast<SSandBoxNode*>(MkNode(ID));
|
||||
pNode->Values.resize(columnCount());
|
||||
if (m_bTree)
|
||||
pNode->Path = MakeBoxPath(ID, Groups);
|
||||
pNode->pBox = pBox;
|
||||
New[pNode->Path].append(pNode);
|
||||
Added.append(ID);
|
||||
|
@ -102,7 +157,7 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList)
|
|||
|
||||
QMap<quint32, CBoxedProcessPtr> ProcessList = pBox->GetProcessList();
|
||||
|
||||
bool HasActive = Sync(pBox, ProcessList, New, Old, Added);
|
||||
bool HasActive = Sync(pBox, pNode->Path, ProcessList, New, Old, Added);
|
||||
int inUse = (HasActive ? 1 : 0);
|
||||
int boxType = eYelow;
|
||||
if(pBoxEx->HasLogApi())
|
||||
|
@ -166,7 +221,7 @@ QList<QVariant> CSbieModel::Sync(const QMap<QString, CSandBoxPtr>& BoxList)
|
|||
return Added;
|
||||
}
|
||||
|
||||
bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QMap<quint32, CBoxedProcessPtr>& ProcessList, QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old, QList<QVariant>& Added)
|
||||
bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, const QMap<quint32, CBoxedProcessPtr>& ProcessList, QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old, QList<QVariant>& Added)
|
||||
{
|
||||
QString BoxName = pBox->GetName();
|
||||
|
||||
|
@ -180,12 +235,12 @@ bool CSbieModel::Sync(const CSandBoxPtr& pBox, const QMap<quint32, CBoxedProcess
|
|||
|
||||
QHash<QVariant, STreeNode*>::iterator I = Old.find(ID);
|
||||
SSandBoxNode* pNode = I != Old.end() ? static_cast<SSandBoxNode*>(I.value()) : NULL;
|
||||
if (!pNode || (m_bTree ? !TestProcPath(pNode->Path, BoxName, pProcess, ProcessList) : !pNode->Path.isEmpty()))
|
||||
if (!pNode || (m_bTree ? !TestProcPath(pNode->Path.mid(Path.length()), BoxName, pProcess, ProcessList) : !pNode->Path.isEmpty())) // todo: improve that
|
||||
{
|
||||
pNode = static_cast<SSandBoxNode*>(MkNode(ID));
|
||||
pNode->Values.resize(columnCount());
|
||||
if(m_bTree)
|
||||
pNode->Path = MakeProcPath(BoxName, pProcess, ProcessList);
|
||||
if (m_bTree)
|
||||
pNode->Path = Path + MakeProcPath(BoxName, pProcess, ProcessList);
|
||||
pNode->pBox = pBox;
|
||||
pNode->pProcess = pProcess;
|
||||
New[pNode->Path].append(pNode);
|
||||
|
@ -295,6 +350,32 @@ CBoxedProcessPtr CSbieModel::GetProcess(const QModelIndex &index) const
|
|||
return pNode->pProcess;
|
||||
}
|
||||
|
||||
QVariant CSbieModel::GetID(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
SSandBoxNode* pNode = static_cast<SSandBoxNode*>(index.internalPointer());
|
||||
ASSERT(pNode);
|
||||
|
||||
return pNode->ID;
|
||||
}
|
||||
|
||||
CSbieModel::ETypes CSbieModel::GetType(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return eNone;
|
||||
|
||||
SSandBoxNode* pNode = static_cast<SSandBoxNode*>(index.internalPointer());
|
||||
ASSERT(pNode);
|
||||
|
||||
if (pNode->pProcess)
|
||||
return eProcess;
|
||||
if (pNode->pBox)
|
||||
return eBox;
|
||||
return eGroup;
|
||||
}
|
||||
|
||||
int CSbieModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return eCount;
|
||||
|
|
|
@ -12,10 +12,19 @@ public:
|
|||
CSbieModel(QObject *parent = 0);
|
||||
~CSbieModel();
|
||||
|
||||
QList<QVariant> Sync(const QMap<QString, CSandBoxPtr>& BoxList);
|
||||
QList<QVariant> Sync(const QMap<QString, CSandBoxPtr>& BoxList, const QMap<QString, QStringList>& Groups = QMap<QString, QStringList>());
|
||||
|
||||
CSandBoxPtr GetSandBox(const QModelIndex &index) const;
|
||||
CBoxedProcessPtr GetProcess(const QModelIndex &index) const;
|
||||
QVariant GetID(const QModelIndex &index) const;
|
||||
|
||||
enum ETypes
|
||||
{
|
||||
eNone = 0,
|
||||
eGroup,
|
||||
eBox,
|
||||
eProcess
|
||||
} GetType(const QModelIndex &index) const;
|
||||
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
@ -33,7 +42,7 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
bool Sync(const CSandBoxPtr& pBox, const QMap<quint32, CBoxedProcessPtr>& ProcessList, QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old, QList<QVariant>& Added);
|
||||
bool Sync(const CSandBoxPtr& pBox, const QList<QVariant>& Path, const QMap<quint32, CBoxedProcessPtr>& ProcessList, QMap<QList<QVariant>, QList<STreeNode*> >& New, QHash<QVariant, STreeNode*>& Old, QList<QVariant>& Added);
|
||||
|
||||
struct SSandBoxNode: STreeNode
|
||||
{
|
||||
|
@ -52,6 +61,9 @@ protected:
|
|||
QList<QVariant> MakeProcPath(const CBoxedProcessPtr& pProcess, const QMap<quint32, CBoxedProcessPtr>& ProcessList);
|
||||
bool TestProcPath(const QList<QVariant>& Path, const QString& BoxName, const CBoxedProcessPtr& pProcess, const QMap<quint32, CBoxedProcessPtr>& ProcessList, int Index = 0);
|
||||
|
||||
QString FindParent(const QVariant& Name, const QMap<QString, QStringList>& Groups);
|
||||
QList<QVariant> MakeBoxPath(const QVariant& Name, const QMap<QString, QStringList>& Groups);
|
||||
|
||||
//virtual QVariant GetDefaultIcon() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -99,6 +99,8 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
connect(theAPI, SIGNAL(StatusChanged()), this, SLOT(OnStatusChanged()));
|
||||
connect(theAPI, SIGNAL(BoxClosed(const QString&)), this, SLOT(OnBoxClosed(const QString&)));
|
||||
|
||||
m_RequestManager = NULL;
|
||||
|
||||
QString appTitle = tr("Sandboxie-Plus v%1").arg(GetVersion());
|
||||
this->setWindowTitle(appTitle);
|
||||
|
||||
|
@ -111,15 +113,15 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
m_bConnectPending = false;
|
||||
m_bStopPending = false;
|
||||
|
||||
CreateMenus();
|
||||
|
||||
m_pMainWidget = new QWidget();
|
||||
m_pMainLayout = new QVBoxLayout(m_pMainWidget);
|
||||
m_pMainLayout->setMargin(2);
|
||||
m_pMainLayout->setSpacing(0);
|
||||
this->setCentralWidget(m_pMainWidget);
|
||||
|
||||
m_pToolBar = new QToolBar();
|
||||
m_pMainLayout->insertWidget(0, m_pToolBar);
|
||||
|
||||
CreateToolBar();
|
||||
|
||||
m_pLogSplitter = new QSplitter();
|
||||
m_pLogSplitter->setOrientation(Qt::Vertical);
|
||||
|
@ -181,6 +183,104 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
m_pApiCallLog->setEnabled(false);
|
||||
//
|
||||
|
||||
|
||||
// Tray
|
||||
QIcon Icon;
|
||||
Icon.addFile(":/SandMan.png");
|
||||
m_pTrayIcon = new QSystemTrayIcon(Icon, this);
|
||||
m_pTrayIcon->setToolTip("Sandboxie-Plus");
|
||||
connect(m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnSysTray(QSystemTrayIcon::ActivationReason)));
|
||||
m_bIconEmpty = false;
|
||||
|
||||
m_pTrayMenu = new QMenu();
|
||||
m_pTrayMenu->addAction(m_pEmptyAll);
|
||||
m_pTrayMenu->addAction(m_pDisableForce);
|
||||
m_pTrayMenu->addSeparator();
|
||||
m_pTrayMenu->addAction(m_pExit);
|
||||
|
||||
bool bAutoRun = QApplication::arguments().contains("-autorun");
|
||||
|
||||
m_pTrayIcon->show(); // Note: qt bug; without a first show hide does not work :/
|
||||
if(!bAutoRun && !theConf->GetBool("Options/ShowSysTray", true))
|
||||
m_pTrayIcon->hide();
|
||||
//
|
||||
|
||||
|
||||
restoreGeometry(theConf->GetBlob("MainWindow/Window_Geometry"));
|
||||
//m_pBoxTree->restoreState(theConf->GetBlob("MainWindow/BoxTree_Columns"));
|
||||
m_pMessageLog->GetView()->header()->restoreState(theConf->GetBlob("MainWindow/LogList_Columns"));
|
||||
QByteArray Columns = theConf->GetBlob("MainWindow/ResMonList_Columns");
|
||||
if (!Columns.isEmpty())
|
||||
((QTreeViewEx*)m_pResourceLog->GetView())->OnResetColumns();
|
||||
else
|
||||
((QTreeViewEx*)m_pResourceLog->GetView())->restoreState(Columns);
|
||||
Columns = theConf->GetBlob("MainWindow/ApiLogList_Columns");
|
||||
if (!Columns.isEmpty())
|
||||
((QTreeViewEx*)m_pApiCallLog->GetView())->OnResetColumns();
|
||||
else
|
||||
((QTreeViewEx*)m_pApiCallLog->GetView())->restoreState(Columns);
|
||||
m_pLogSplitter->restoreState(theConf->GetBlob("MainWindow/Log_Splitter"));
|
||||
m_pPanelSplitter->restoreState(theConf->GetBlob("MainWindow/Panel_Splitter"));
|
||||
m_pLogTabs->setCurrentIndex(theConf->GetInt("MainWindow/LogTab", 0));
|
||||
|
||||
if (theConf->GetBool("Options/NoStatusBar", false))
|
||||
statusBar()->hide();
|
||||
//else if (theConf->GetBool("Options/NoSizeGrip", false))
|
||||
// statusBar()->setSizeGripEnabled(false);
|
||||
|
||||
m_pKeepTerminated->setChecked(theConf->GetBool("Options/KeepTerminated"));
|
||||
|
||||
m_pProgressDialog = new CProgressDialog("", this);
|
||||
m_pProgressDialog->setWindowModality(Qt::ApplicationModal);
|
||||
connect(m_pProgressDialog, SIGNAL(Cancel()), this, SLOT(OnCancelAsync()));
|
||||
|
||||
m_pPopUpWindow = new CPopUpWindow(this);
|
||||
connect(m_pPopUpWindow, SIGNAL(RecoveryRequested(const QString&)), this, SLOT(OpenRecovery(const QString&)));
|
||||
|
||||
if (!bAutoRun)
|
||||
show();
|
||||
|
||||
//connect(theAPI, SIGNAL(LogMessage(const QString&, bool)), this, SLOT(OnLogMessage(const QString&, bool)));
|
||||
connect(theAPI, SIGNAL(LogSbieMessage(quint32, const QStringList&, quint32)), this, SLOT(OnLogSbieMessage(quint32, const QStringList&, quint32)));
|
||||
connect(theAPI, SIGNAL(NotAuthorized(bool, bool&)), this, SLOT(OnNotAuthorized(bool, bool&)), Qt::DirectConnection);
|
||||
connect(theAPI, SIGNAL(QueuedRequest(quint32, quint32, quint32, const QVariantMap&)), this, SLOT(OnQueuedRequest(quint32, quint32, quint32, const QVariantMap&)), Qt::QueuedConnection);
|
||||
connect(theAPI, SIGNAL(FileToRecover(const QString&, const QString&, quint32)), this, SLOT(OnFileToRecover(const QString&, const QString&, quint32)), Qt::QueuedConnection);
|
||||
connect(theAPI, SIGNAL(ConfigReloaded()), this, SLOT(OnIniReloaded()));
|
||||
|
||||
m_uTimerID = startTimer(250);
|
||||
|
||||
if (CSbieUtils::IsRunning(CSbieUtils::eAll) || theConf->GetBool("Options/StartIfStopped", true))
|
||||
{
|
||||
SB_STATUS Status = ConnectSbie();
|
||||
CheckResults(QList<SB_STATUS>() << Status);
|
||||
}
|
||||
}
|
||||
|
||||
CSandMan::~CSandMan()
|
||||
{
|
||||
if(m_pEnableMonitoring->isChecked())
|
||||
theAPI->EnableMonitor(false);
|
||||
|
||||
killTimer(m_uTimerID);
|
||||
|
||||
m_pTrayIcon->hide();
|
||||
|
||||
theConf->SetBlob("MainWindow/Window_Geometry", saveGeometry());
|
||||
//theConf->SetBlob("MainWindow/BoxTree_Columns", m_pBoxTree->saveState());
|
||||
theConf->SetBlob("MainWindow/LogList_Columns", m_pMessageLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/ResMonList_Columns", m_pResourceLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/ApiLogList_Columns", m_pApiCallLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/Log_Splitter", m_pLogSplitter->saveState());
|
||||
theConf->SetBlob("MainWindow/Panel_Splitter", m_pPanelSplitter->saveState());
|
||||
theConf->SetValue("MainWindow/LogTab", m_pLogTabs->currentIndex());
|
||||
|
||||
theAPI = NULL;
|
||||
|
||||
theGUI = NULL;
|
||||
}
|
||||
|
||||
void CSandMan::CreateMenus()
|
||||
{
|
||||
connect(menuBar(), SIGNAL(hovered(QAction*)), this, SLOT(OnMenuHover(QAction*)));
|
||||
|
||||
m_pMenuFile = menuBar()->addMenu(tr("&Sandbox"));
|
||||
|
@ -236,12 +336,21 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
|
||||
|
||||
m_pMenuHelp = menuBar()->addMenu(tr("&Help"));
|
||||
m_pSupport = m_pMenuHelp->addAction(tr("Support Sandboxie-Plus on Patreon"), this, SLOT(OnAbout()));
|
||||
//m_pMenuHelp->addAction(tr("Support Sandboxie-Plus on Patreon"), this, SLOT(OnHelp()));
|
||||
m_pSupport = m_pMenuHelp->addAction(tr("Support Sandboxie-Plus with a Donation"), this, SLOT(OnHelp()));
|
||||
m_pForum = m_pMenuHelp->addAction(tr("Visit Support Forum"), this, SLOT(OnHelp()));
|
||||
m_pManual = m_pMenuHelp->addAction(tr("Online Documentation"), this, SLOT(OnHelp()));
|
||||
m_pMenuHelp->addSeparator();
|
||||
m_pUpdate = m_pMenuHelp->addAction(tr("Check for Updates"), this, SLOT(CheckForUpdates()));
|
||||
m_pMenuHelp->addSeparator();
|
||||
m_pAboutQt = m_pMenuHelp->addAction(tr("About the Qt Framework"), this, SLOT(OnAbout()));
|
||||
//m_pMenuHelp->addSeparator();
|
||||
m_pAbout = m_pMenuHelp->addAction(QIcon(":/SandMan.png"), tr("About Sandboxie-Plus"), this, SLOT(OnAbout()));
|
||||
}
|
||||
|
||||
void CSandMan::CreateToolBar()
|
||||
{
|
||||
m_pToolBar = new QToolBar();
|
||||
m_pMainLayout->insertWidget(0, m_pToolBar);
|
||||
|
||||
m_pToolBar->addAction(m_pMenuSettings);
|
||||
m_pToolBar->addSeparator();
|
||||
|
@ -280,102 +389,9 @@ CSandMan::CSandMan(QWidget *parent)
|
|||
m_pToolBar->addWidget(new QLabel(" "));
|
||||
QLabel* pSupport = new QLabel("<a href=\"https://www.patreon.com/DavidXanatos\">Support Sandboxie-Plus on Patreon</a>");
|
||||
pSupport->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
connect(pSupport, SIGNAL(linkActivated(const QString&)), this, SLOT(OnAbout()));
|
||||
connect(pSupport, SIGNAL(linkActivated(const QString&)), this, SLOT(OnHelp()));
|
||||
m_pToolBar->addWidget(pSupport);
|
||||
m_pToolBar->addWidget(new QLabel(" "));
|
||||
|
||||
|
||||
|
||||
QIcon Icon;
|
||||
Icon.addFile(":/SandMan.png");
|
||||
m_pTrayIcon = new QSystemTrayIcon(Icon, this);
|
||||
m_pTrayIcon->setToolTip("Sandboxie-Plus");
|
||||
connect(m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnSysTray(QSystemTrayIcon::ActivationReason)));
|
||||
m_bIconEmpty = false;
|
||||
|
||||
m_pTrayMenu = new QMenu();
|
||||
m_pTrayMenu->addAction(m_pEmptyAll);
|
||||
m_pTrayMenu->addAction(m_pDisableForce);
|
||||
m_pTrayMenu->addSeparator();
|
||||
m_pTrayMenu->addAction(m_pExit);
|
||||
|
||||
bool bAutoRun = QApplication::arguments().contains("-autorun");
|
||||
|
||||
m_pTrayIcon->show(); // Note: qt bug; without a first show hide does not work :/
|
||||
if(!bAutoRun && !theConf->GetBool("Options/ShowSysTray", true))
|
||||
m_pTrayIcon->hide();
|
||||
|
||||
restoreGeometry(theConf->GetBlob("MainWindow/Window_Geometry"));
|
||||
//m_pBoxTree->restoreState(theConf->GetBlob("MainWindow/BoxTree_Columns"));
|
||||
m_pMessageLog->GetView()->header()->restoreState(theConf->GetBlob("MainWindow/LogList_Columns"));
|
||||
QByteArray Columns = theConf->GetBlob("MainWindow/ResMonList_Columns");
|
||||
if (!Columns.isEmpty())
|
||||
((QTreeViewEx*)m_pResourceLog->GetView())->OnResetColumns();
|
||||
else
|
||||
((QTreeViewEx*)m_pResourceLog->GetView())->restoreState(Columns);
|
||||
Columns = theConf->GetBlob("MainWindow/ApiLogList_Columns");
|
||||
if (!Columns.isEmpty())
|
||||
((QTreeViewEx*)m_pApiCallLog->GetView())->OnResetColumns();
|
||||
else
|
||||
((QTreeViewEx*)m_pApiCallLog->GetView())->restoreState(Columns);
|
||||
m_pLogSplitter->restoreState(theConf->GetBlob("MainWindow/Log_Splitter"));
|
||||
m_pPanelSplitter->restoreState(theConf->GetBlob("MainWindow/Panel_Splitter"));
|
||||
m_pLogTabs->setCurrentIndex(theConf->GetInt("MainWindow/LogTab", 0));
|
||||
|
||||
if (theConf->GetBool("Options/NoStatusBar", false))
|
||||
statusBar()->hide();
|
||||
//else if (theConf->GetBool("Options/NoSizeGrip", false))
|
||||
// statusBar()->setSizeGripEnabled(false);
|
||||
|
||||
m_pKeepTerminated->setChecked(theConf->GetBool("Options/KeepTerminated"));
|
||||
|
||||
m_pProgressDialog = new CProgressDialog("Maintenance operation progress...", this);
|
||||
m_pProgressDialog->setWindowModality(Qt::ApplicationModal);
|
||||
connect(m_pProgressDialog, SIGNAL(Cancel()), this, SLOT(OnCancelAsync()));
|
||||
|
||||
m_pPopUpWindow = new CPopUpWindow(this);
|
||||
connect(m_pPopUpWindow, SIGNAL(RecoveryRequested(const QString&)), this, SLOT(OpenRecovery(const QString&)));
|
||||
|
||||
if (!bAutoRun)
|
||||
show();
|
||||
|
||||
//connect(theAPI, SIGNAL(LogMessage(const QString&, bool)), this, SLOT(OnLogMessage(const QString&, bool)));
|
||||
connect(theAPI, SIGNAL(LogSbieMessage(quint32, const QStringList&, quint32)), this, SLOT(OnLogSbieMessage(quint32, const QStringList&, quint32)));
|
||||
connect(theAPI, SIGNAL(NotAuthorized(bool, bool&)), this, SLOT(OnNotAuthorized(bool, bool&)), Qt::DirectConnection);
|
||||
connect(theAPI, SIGNAL(QueuedRequest(quint32, quint32, quint32, const QVariantMap&)), this, SLOT(OnQueuedRequest(quint32, quint32, quint32, const QVariantMap&)), Qt::QueuedConnection);
|
||||
connect(theAPI, SIGNAL(FileToRecover(const QString&, const QString&, quint32)), this, SLOT(OnFileToRecover(const QString&, const QString&, quint32)), Qt::QueuedConnection);
|
||||
connect(theAPI, SIGNAL(ConfigReloaded()), this, SLOT(OnIniReloaded()));
|
||||
|
||||
m_uTimerID = startTimer(250);
|
||||
|
||||
if (CSbieUtils::IsRunning(CSbieUtils::eAll) || theConf->GetBool("Options/StartIfStopped", true))
|
||||
{
|
||||
SB_STATUS Status = ConnectSbie();
|
||||
CheckResults(QList<SB_STATUS>() << Status);
|
||||
}
|
||||
}
|
||||
|
||||
CSandMan::~CSandMan()
|
||||
{
|
||||
if(m_pEnableMonitoring->isChecked())
|
||||
theAPI->EnableMonitor(false);
|
||||
|
||||
killTimer(m_uTimerID);
|
||||
|
||||
m_pTrayIcon->hide();
|
||||
|
||||
theConf->SetBlob("MainWindow/Window_Geometry", saveGeometry());
|
||||
//theConf->SetBlob("MainWindow/BoxTree_Columns", m_pBoxTree->saveState());
|
||||
theConf->SetBlob("MainWindow/LogList_Columns", m_pMessageLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/ResMonList_Columns", m_pResourceLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/ApiLogList_Columns", m_pApiCallLog->GetView()->header()->saveState());
|
||||
theConf->SetBlob("MainWindow/Log_Splitter", m_pLogSplitter->saveState());
|
||||
theConf->SetBlob("MainWindow/Panel_Splitter", m_pPanelSplitter->saveState());
|
||||
theConf->SetValue("MainWindow/LogTab", m_pLogTabs->currentIndex());
|
||||
|
||||
theAPI = NULL;
|
||||
|
||||
theGUI = NULL;
|
||||
}
|
||||
|
||||
void CSandMan::OnExit()
|
||||
|
@ -503,6 +519,35 @@ void CSandMan::timerEvent(QTimerEvent* pEvent)
|
|||
m_pBoxView->Refresh();
|
||||
|
||||
OnSelectionChanged();
|
||||
|
||||
int iCheckUpdates = theConf->GetInt("Options/CheckForUpdates", 2);
|
||||
if (iCheckUpdates != 0)
|
||||
{
|
||||
time_t NextUpdateCheck = theConf->GetUInt64("Options/NextCheckForUpdates", 0);
|
||||
if (NextUpdateCheck == 0)
|
||||
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(7).toTime_t());
|
||||
else if(QDateTime::currentDateTime().toTime_t() >= NextUpdateCheck)
|
||||
{
|
||||
if (iCheckUpdates == 2)
|
||||
{
|
||||
bool bCheck = false;
|
||||
iCheckUpdates = CCheckableMessageBox::question(this, "Sandboxie-Plus", tr("Do you want to check if there is a new version of Sandboxie-Plus?")
|
||||
, tr("Don't show this message again."), &bCheck, QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::Yes, QMessageBox::Information) == QDialogButtonBox::Ok ? 1 : 0;
|
||||
|
||||
if (bCheck)
|
||||
theConf->SetValue("Options/CheckForUpdates", iCheckUpdates);
|
||||
}
|
||||
|
||||
if (iCheckUpdates == 0)
|
||||
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(7).toTime_t());
|
||||
else
|
||||
{
|
||||
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(1).toTime_t());
|
||||
|
||||
CheckForUpdates(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSandMan::OnBoxClosed(const QString& BoxName)
|
||||
|
@ -980,6 +1025,7 @@ void CSandMan::OnReloadIni()
|
|||
|
||||
void CSandMan::OnIniReloaded()
|
||||
{
|
||||
m_pBoxView->ReloadGroups();
|
||||
m_pPopUpWindow->ReloadHiddenMessages();
|
||||
}
|
||||
|
||||
|
@ -1026,10 +1072,12 @@ void CSandMan::AddAsyncOp(const CSbieProgressPtr& pProgress)
|
|||
m_pAsyncProgress.insert(pProgress.data(), pProgress);
|
||||
connect(pProgress.data(), SIGNAL(Message(const QString&)), this, SLOT(OnAsyncMessage(const QString&)));
|
||||
connect(pProgress.data(), SIGNAL(Finished()), this, SLOT(OnAsyncFinished()));
|
||||
|
||||
m_pProgressDialog->OnStatusMessage("");
|
||||
m_pProgressDialog->show();
|
||||
|
||||
if (pProgress->IsFinished()) // Note: the operation runs asynchroniusly it may have already finished so we need to test for that
|
||||
OnAsyncFinished(pProgress.data());
|
||||
|
||||
m_pProgressDialog->show();
|
||||
}
|
||||
|
||||
void CSandMan::OnAsyncFinished()
|
||||
|
@ -1139,6 +1187,211 @@ QString CSandMan::GetVersion()
|
|||
return Version;
|
||||
}
|
||||
|
||||
void CSandMan::CheckForUpdates(bool bManual)
|
||||
{
|
||||
m_pProgressDialog->OnStatusMessage(tr("Checking for updates..."));
|
||||
m_pProgressDialog->show();
|
||||
|
||||
if(m_RequestManager == NULL)
|
||||
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
|
||||
|
||||
QUrlQuery Query;
|
||||
Query.addQueryItem("software", "sandboxie-plus");
|
||||
//QString Branche = theConf->GetString("Options/ReleaseBranche");
|
||||
//if (!Branche.isEmpty())
|
||||
// Query.addQueryItem("branche", Branche);
|
||||
Query.addQueryItem("version", GetVersion());
|
||||
//Query.addQueryItem("version", QString::number(VERSION_MJR) + "." + QString::number(VERSION_MIN) + "." + QString::number(VERSION_REV) + "." + QString::number(VERSION_UPD));
|
||||
Query.addQueryItem("system", "windows-" + QSysInfo::kernelVersion() + "-" + QSysInfo::currentCpuArchitecture());
|
||||
Query.addQueryItem("language", QString::number(m_LanguageId));
|
||||
QString UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey");
|
||||
if (!UpdateKey.isEmpty())
|
||||
Query.addQueryItem("update_key", UpdateKey);
|
||||
Query.addQueryItem("auto", bManual ? "0" : "1");
|
||||
|
||||
QUrl Url("https://xanasoft.com/update.php");
|
||||
Url.setQuery(Query);
|
||||
|
||||
QNetworkRequest Request = QNetworkRequest(Url);
|
||||
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
//Request.setRawHeader("Accept-Encoding", "gzip");
|
||||
QNetworkReply* pReply = m_RequestManager->get(Request);
|
||||
pReply->setProperty("manual", bManual);
|
||||
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateCheck()));
|
||||
}
|
||||
|
||||
void CSandMan::OnUpdateCheck()
|
||||
{
|
||||
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
||||
QByteArray Reply = pReply->readAll();
|
||||
bool bManual = pReply->property("manual").toBool();
|
||||
pReply->deleteLater();
|
||||
|
||||
m_pProgressDialog->hide();
|
||||
|
||||
QVariantMap Data = QJsonDocument::fromJson(Reply).toVariant().toMap();
|
||||
if (Data.isEmpty() || Data["error"].toBool())
|
||||
{
|
||||
QString Error = Data.isEmpty() ? tr("server not reachable") : Data["errorMsg"].toString();
|
||||
OnLogMessage(tr("Failed to check for updates, error: %1").arg(Error), !bManual);
|
||||
if (bManual)
|
||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to check for updates, error: %1").arg(Error));
|
||||
return;
|
||||
}
|
||||
|
||||
bool bNothing = true;
|
||||
|
||||
QStringList IgnoredUpdates = theConf->GetStringList("Options/IgnoredUpdates");
|
||||
|
||||
QString UserMsg = Data["userMsg"].toString();
|
||||
if (!UserMsg.isEmpty())
|
||||
{
|
||||
QString MsgHash = QCryptographicHash::hash(Data["userMsg"].toByteArray(), QCryptographicHash::Md5).toHex().left(8);
|
||||
if (!IgnoredUpdates.contains(MsgHash))
|
||||
{
|
||||
CCheckableMessageBox mb(this);
|
||||
mb.setWindowTitle("Sandboxie-Plus");
|
||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||
mb.setIconPixmap(ico.pixmap(64, 64));
|
||||
mb.setText(UserMsg);
|
||||
mb.setCheckBoxText(tr("Don't show this announcement in future."));
|
||||
mb.setStandardButtons(QDialogButtonBox::Close);
|
||||
mb.exec();
|
||||
|
||||
if (mb.isChecked())
|
||||
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << MsgHash);
|
||||
|
||||
bNothing = false;
|
||||
}
|
||||
}
|
||||
|
||||
QString Version = Data["version"].toString();
|
||||
if (!Version.isEmpty() && Version != GetVersion())
|
||||
{
|
||||
if (bManual || !IgnoredUpdates.contains(Version)) // when checked manually always show result
|
||||
{
|
||||
bNothing = false;
|
||||
//QDateTime Updated = QDateTime::fromTime_t(Data["updated"].toULongLong());
|
||||
|
||||
QString UpdateMsg = Data["updateMsg"].toString();
|
||||
QString UpdateUrl = Data["updateUrl"].toString();
|
||||
|
||||
QString DownloadUrl = Data["downloadUrl"].toString();
|
||||
// 'sha256'
|
||||
// 'signature'
|
||||
|
||||
QString FullMessage = UpdateMsg.isEmpty() ? tr("<p>There is a new version of Sandboxie-Plus available.<br /><font color='red'>New version:</font> <b>%1</b></p>").arg(Version) : UpdateMsg;
|
||||
if (!DownloadUrl.isEmpty())
|
||||
FullMessage += tr("<p>Do you want to download the latest version?</p>");
|
||||
else if (!UpdateUrl.isEmpty())
|
||||
FullMessage += tr("<p>Do you want to go to the <a href=\"%1\">download page</a>?</p>").arg(UpdateUrl);
|
||||
|
||||
CCheckableMessageBox mb(this);
|
||||
mb.setWindowTitle("Sandboxie-Plus");
|
||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||
mb.setIconPixmap(ico.pixmap(64, 64));
|
||||
//mb.setTextFormat(Qt::RichText);
|
||||
mb.setText(FullMessage);
|
||||
mb.setCheckBoxText(tr("Ignore this update, notify me anout the next one."));
|
||||
mb.setCheckBoxVisible(!bManual);
|
||||
|
||||
if (!UpdateUrl.isEmpty() || !DownloadUrl.isEmpty()) {
|
||||
mb.setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
|
||||
mb.setDefaultButton(QDialogButtonBox::Yes);
|
||||
}
|
||||
else
|
||||
mb.setStandardButtons(QDialogButtonBox::Ok);
|
||||
|
||||
mb.exec();
|
||||
|
||||
if (mb.isChecked())
|
||||
theConf->SetValue("Options/IgnoredUpdates", IgnoredUpdates << Version);
|
||||
|
||||
if (mb.clickedStandardButton() == QDialogButtonBox::Yes)
|
||||
{
|
||||
if (!DownloadUrl.isEmpty())
|
||||
{
|
||||
QNetworkRequest Request = QNetworkRequest(DownloadUrl);
|
||||
Request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
//Request.setRawHeader("Accept-Encoding", "gzip");
|
||||
QNetworkReply* pReply = m_RequestManager->get(Request);
|
||||
connect(pReply, SIGNAL(finished()), this, SLOT(OnUpdateDownload()));
|
||||
connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(OnUpdateProgress(qint64, qint64)));
|
||||
|
||||
m_pProgressDialog->OnStatusMessage(tr("Downloading new version..."));
|
||||
m_pProgressDialog->show();
|
||||
}
|
||||
else
|
||||
QDesktopServices::openUrl(UpdateUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bNothing)
|
||||
{
|
||||
theConf->SetValue("Options/NextCheckForUpdates", QDateTime::currentDateTime().addDays(7).toTime_t());
|
||||
|
||||
if (bManual)
|
||||
QMessageBox::information(this, "Sandboxie-Plus", tr("No new updates found, your Sandboxie-Plus is up to date."));
|
||||
}
|
||||
}
|
||||
|
||||
void CSandMan::OnUpdateProgress(qint64 bytes, qint64 bytesTotal)
|
||||
{
|
||||
if (bytesTotal != 0)
|
||||
m_pProgressDialog->OnProgressMessage("", 100 * bytes / bytesTotal);
|
||||
}
|
||||
|
||||
void CSandMan::OnUpdateDownload()
|
||||
{
|
||||
QString TempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
if (TempDir.right(1) != "/")
|
||||
TempDir += "/";
|
||||
|
||||
m_pProgressDialog->OnProgressMessage("", -1);
|
||||
|
||||
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
|
||||
quint64 Size = pReply->bytesAvailable();
|
||||
QString Name = pReply->request().url().fileName();
|
||||
if (Name.isEmpty() || Name.right(4).compare(".exe", Qt::CaseInsensitive) != 0)
|
||||
Name = "Sandboxie-Plus-Install.exe";
|
||||
|
||||
QString FilePath = TempDir + Name;
|
||||
|
||||
QFile File(FilePath);
|
||||
if (File.open(QFile::WriteOnly)) {
|
||||
while (pReply->bytesAvailable() > 0)
|
||||
File.write(pReply->read(4096));
|
||||
File.close();
|
||||
}
|
||||
|
||||
pReply->deleteLater();
|
||||
|
||||
m_pProgressDialog->hide();
|
||||
|
||||
if (File.size() != Size) {
|
||||
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to download update from: %1").arg(pReply->request().url().toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
QString Message = tr("<p>New Sandboxie-Plus has been downloaded to the following location:</p><p><a href=\"%2\">%1</a></p><p>Do you want to begin the installation. If any programs are running sandboxed, they will be terminated.</p>")
|
||||
.arg(FilePath).arg("File:///" + TempDir);
|
||||
if (QMessageBox("Sandboxie-Plus", Message, QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape, QMessageBox::NoButton).exec() == QMessageBox::Yes)
|
||||
QProcess::startDetached(FilePath);
|
||||
}
|
||||
|
||||
void CSandMan::OnHelp()
|
||||
{
|
||||
if (sender() == m_pSupport)
|
||||
QDesktopServices::openUrl(QUrl("https://xanasoft.com/go.php?to=donate"));
|
||||
else if (sender() == m_pForum)
|
||||
QDesktopServices::openUrl(QUrl("https://xanasoft.com/go.php?to=forum"));
|
||||
else if (sender() == m_pManual)
|
||||
QDesktopServices::openUrl(QUrl("https://xanasoft.com/go.php?to=sbie-docs"));
|
||||
else
|
||||
QDesktopServices::openUrl(QUrl("https://www.patreon.com/DavidXanatos"));
|
||||
}
|
||||
|
||||
void CSandMan::OnAbout()
|
||||
{
|
||||
if (sender() == m_pAbout)
|
||||
|
@ -1172,8 +1425,6 @@ void CSandMan::OnAbout()
|
|||
}
|
||||
else if (sender() == m_pAboutQt)
|
||||
QMessageBox::aboutQt(this);
|
||||
else
|
||||
QDesktopServices::openUrl(QUrl("https://www.patreon.com/DavidXanatos"));
|
||||
}
|
||||
|
||||
void CSandMan::SetDarkTheme(bool bDark)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../MiscHelpers/Common/TreeViewEx.h"
|
||||
#include "../MiscHelpers/Common/PanelView.h"
|
||||
#include "../MiscHelpers/Common/ProgressDialog.h"
|
||||
#include "../MiscHelpers/Common/NetworkAccessManager.h"
|
||||
#include "Models/ResMonModel.h"
|
||||
#include "Models/ApiMonModel.h"
|
||||
#include <QTranslator>
|
||||
|
@ -42,6 +43,9 @@ public:
|
|||
void AddAsyncOp(const CSbieProgressPtr& pProgress);
|
||||
static void CheckResults(QList<SB_STATUS> Results);
|
||||
|
||||
QAction* GetNewAction() { return m_pNew; }
|
||||
QAction* GetEmptyAllAction() { return m_pEmptyAll; }
|
||||
|
||||
protected:
|
||||
SB_STATUS ConnectSbie();
|
||||
SB_STATUS ConnectSbieImpl();
|
||||
|
@ -64,6 +68,8 @@ protected:
|
|||
|
||||
QMap<CSbieProgress*, CSbieProgressPtr> m_pAsyncProgress;
|
||||
|
||||
CNetworkAccessManager* m_RequestManager;
|
||||
|
||||
public slots:
|
||||
void OnMessage(const QString&);
|
||||
|
||||
|
@ -88,6 +94,8 @@ public slots:
|
|||
|
||||
void OnBoxClosed(const QString& BoxName);
|
||||
|
||||
void CheckForUpdates(bool bManual = true);
|
||||
|
||||
private slots:
|
||||
void OnSelectionChanged();
|
||||
|
||||
|
@ -108,11 +116,19 @@ private slots:
|
|||
void OnSetLogging();
|
||||
|
||||
void OnExit();
|
||||
void OnHelp();
|
||||
void OnAbout();
|
||||
|
||||
void OnSysTray(QSystemTrayIcon::ActivationReason Reason);
|
||||
|
||||
void OnUpdateCheck();
|
||||
void OnUpdateProgress(qint64 bytes, qint64 bytesTotal);
|
||||
void OnUpdateDownload();
|
||||
|
||||
private:
|
||||
void CreateMenus();
|
||||
void CreateToolBar();
|
||||
|
||||
QWidget* m_pMainWidget;
|
||||
QVBoxLayout* m_pMainLayout;
|
||||
|
||||
|
@ -170,8 +186,11 @@ private:
|
|||
QAction* m_pEnableLogging;
|
||||
|
||||
QMenu* m_pMenuHelp;
|
||||
QAction* m_pAbout;
|
||||
QAction* m_pSupport;
|
||||
QAction* m_pForum;
|
||||
QAction* m_pManual;
|
||||
QAction* m_pUpdate;
|
||||
QAction* m_pAbout;
|
||||
QAction* m_pAboutQt;
|
||||
|
||||
QSystemTrayIcon* m_pTrayIcon;
|
||||
|
|
|
@ -53,6 +53,13 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
|
||||
connect(m_pSbieModel, SIGNAL(ToolTipCallback(const QVariant&, QString&)), this, SLOT(OnToolTipCallback(const QVariant&, QString&)), Qt::DirectConnection);
|
||||
|
||||
m_pMenu->addAction(theGUI->GetNewAction());
|
||||
//m_pMenu->addAction(theGUI->GetEmptyAllAction());
|
||||
m_pAddGroupe = m_pMenu->addAction(QIcon(":/Actions/Group"), tr("Add Group"), this, SLOT(OnGroupAction()));
|
||||
m_pDelGroupe = m_pMenu->addAction(QIcon(":/Actions/Remove"), tr("Remove Group"), this, SLOT(OnGroupAction()));
|
||||
m_iMenuTop = m_pMenu->actions().count();
|
||||
//m_pMenu->addSeparator();
|
||||
|
||||
m_pMenuRun = m_pMenu->addMenu(QIcon(":/Actions/Run"), tr("Run"));
|
||||
m_pMenuRunAny = m_pMenuRun->addAction(tr("Run Program"), this, SLOT(OnSandBoxAction()));
|
||||
m_pMenuRunMenu = m_pMenuRun->addAction(tr("Run from Start Menu"), this, SLOT(OnSandBoxAction()));
|
||||
|
@ -82,6 +89,8 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent)
|
|||
m_pMenuPresetsNoAdmin->setCheckable(true);
|
||||
m_pMenuOptions = m_pMenu->addAction(QIcon(":/Actions/Options"), tr("Sandbox Options"), this, SLOT(OnSandBoxAction()));
|
||||
m_pMenuRename = m_pMenu->addAction(QIcon(":/Actions/Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||
m_iMoveTo = m_pMenu->actions().count();
|
||||
m_pMenuMoveTo = m_pMenu->addMenu(QIcon(":/Actions/Group"), tr("Move to Group"));
|
||||
m_pMenuRemove = m_pMenu->addAction(QIcon(":/Actions/Remove"), tr("Remove Sandbox"), this, SLOT(OnSandBoxAction()));
|
||||
m_iMenuBox = m_pMenu->actions().count();
|
||||
|
||||
|
@ -123,7 +132,7 @@ CSbieView::~CSbieView()
|
|||
|
||||
void CSbieView::Refresh()
|
||||
{
|
||||
QList<QVariant> Added = m_pSbieModel->Sync(theAPI->GetAllBoxes());
|
||||
QList<QVariant> Added = m_pSbieModel->Sync(theAPI->GetAllBoxes(), m_Groups);
|
||||
|
||||
if (m_pSbieModel->IsTree())
|
||||
{
|
||||
|
@ -168,7 +177,8 @@ void CSbieView::OnMenu(const QPoint& Point)
|
|||
int iProcessCount = 0;
|
||||
int iSandBoxeCount = 0;
|
||||
int iSuspendedCount = 0;
|
||||
foreach(const QModelIndex& Index, m_pSbieTree->selectedRows())
|
||||
QModelIndexList Rows = m_pSbieTree->selectedRows();
|
||||
foreach(const QModelIndex& Index, Rows)
|
||||
{
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
|
||||
pProcess = m_pSbieModel->GetProcess(ModelIndex);
|
||||
|
@ -188,10 +198,16 @@ void CSbieView::OnMenu(const QPoint& Point)
|
|||
|
||||
QList<QAction*> MenuActions = m_pMenu->actions();
|
||||
|
||||
for (int i = 0; i < m_iMenuBox; i++)
|
||||
for (int i = 0; i < m_iMenuTop; i++)
|
||||
MenuActions[i]->setVisible(iSandBoxeCount == 0 && iProcessCount == 0);
|
||||
m_pDelGroupe->setVisible(!Rows.isEmpty() && iSandBoxeCount == 0 && iProcessCount == 0);
|
||||
|
||||
for (int i = m_iMenuTop; i < m_iMenuBox; i++)
|
||||
MenuActions[i]->setVisible(iSandBoxeCount > 0 && iProcessCount == 0);
|
||||
m_pMenuRun->setEnabled(iSandBoxeCount == 1);
|
||||
|
||||
MenuActions[m_iMoveTo]->setVisible(!Rows.isEmpty() && iProcessCount == 0);
|
||||
|
||||
if(iSandBoxeCount == 1)
|
||||
UpdateRunMenu(pBox);
|
||||
|
||||
|
@ -247,6 +263,134 @@ void CSbieView::OnMenu(const QPoint& Point)
|
|||
CPanelView::OnMenu(Point);
|
||||
}
|
||||
|
||||
int CSbieView__ParseGroup(const QString& Grouping, QMap<QString, QStringList>& m_Groups, const QString& Parent = "", int Index = 0)
|
||||
{
|
||||
QRegExp RegExp("[,()]", Qt::CaseInsensitive, QRegExp::RegExp);
|
||||
for (; ; )
|
||||
{
|
||||
int pos = Grouping.indexOf(RegExp, Index);
|
||||
QString Name;
|
||||
if (pos == -1) {
|
||||
Name = Grouping.mid(Index);
|
||||
Index = Grouping.length();
|
||||
}
|
||||
else {
|
||||
Name = Grouping.mid(Index, pos - Index);
|
||||
Index = pos + 1;
|
||||
}
|
||||
if (!Name.isEmpty())
|
||||
m_Groups[Parent].append(Name);
|
||||
if (pos == -1)
|
||||
break;
|
||||
if (Grouping.at(pos) == "(")
|
||||
Index = CSbieView__ParseGroup(Grouping, m_Groups, Name, Index);
|
||||
else if (Grouping.at(pos) == ")")
|
||||
break;
|
||||
}
|
||||
return Index;
|
||||
}
|
||||
|
||||
void CSbieView::ReloadGroups()
|
||||
{
|
||||
m_Groups.clear();
|
||||
|
||||
QString Grouping = theAPI->GetUserSettings()->GetText("BoxDisplayOrder");
|
||||
|
||||
CSbieView__ParseGroup(Grouping, m_Groups);
|
||||
|
||||
// update move to menu
|
||||
foreach(QAction* pAction, m_pMenuMoveTo->actions())
|
||||
m_pMenuMoveTo->removeAction(pAction);
|
||||
foreach(const QString& Group, m_Groups.keys())
|
||||
{
|
||||
QAction* pAction = m_pMenuMoveTo->addAction(Group.isEmpty() ? tr("[None]") : Group, this, SLOT(OnGroupAction()));
|
||||
pAction->setData(Group);
|
||||
}
|
||||
}
|
||||
|
||||
QString CSbieView__SerializeGroup(QMap<QString, QStringList>& m_Groups, const QString& Parent = "")
|
||||
{
|
||||
QStringList Grouping;
|
||||
foreach(const QString& Name, m_Groups[Parent])
|
||||
{
|
||||
if (m_Groups.contains(Name))
|
||||
Grouping.append(Name + "(" + CSbieView__SerializeGroup(m_Groups, Name) + ")");
|
||||
else
|
||||
Grouping.append(Name);
|
||||
}
|
||||
return Grouping.join(",");
|
||||
}
|
||||
|
||||
void CSbieView::OnGroupAction()
|
||||
{
|
||||
QAction* Action = qobject_cast<QAction*>(sender());
|
||||
|
||||
if (Action == m_pAddGroupe)
|
||||
{
|
||||
QString Name = QInputDialog::getText(this, "Sandboxie-Plus", tr("Please enter a new group name"), QLineEdit::Normal);
|
||||
if (Name.isEmpty() || m_Groups.contains(Name))
|
||||
return;
|
||||
m_Groups[Name] = QStringList();
|
||||
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(m_pSbieTree->currentIndex());
|
||||
QString Parent;
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
Parent = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
|
||||
if (!Parent.isEmpty())
|
||||
m_Groups[Parent].append(Name);
|
||||
}
|
||||
else if (Action == m_pDelGroupe)
|
||||
{
|
||||
if (QMessageBox("Sandboxie-Plus", tr("Do you really want remove the selected group(s)?"), QMessageBox::Warning, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton).exec() != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
foreach(const QModelIndex& Index, m_pSbieTree->selectedRows())
|
||||
{
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
{
|
||||
QString Group = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
m_Groups.remove(Group);
|
||||
|
||||
// remove from parents
|
||||
for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I)
|
||||
I.value().removeAll(Group);
|
||||
}
|
||||
}
|
||||
|
||||
m_pSbieModel->Clear(); //todo improve that, also move boxes to grant parent?
|
||||
}
|
||||
else // move to groupe
|
||||
{
|
||||
QString Group = Action->data().toString();
|
||||
|
||||
foreach(const QModelIndex& Index, m_pSbieTree->selectedRows())
|
||||
{
|
||||
QModelIndex ModelIndex = m_pSortProxy->mapToSource(Index);
|
||||
QString Name;
|
||||
if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eGroup)
|
||||
Name = m_pSbieModel->GetID(ModelIndex).toString();
|
||||
else if (m_pSbieModel->GetType(ModelIndex) == CSbieModel::eBox)
|
||||
Name = m_pSbieModel->GetSandBox(ModelIndex)->GetName();
|
||||
if (Name.isEmpty() || Name == Group)
|
||||
continue;
|
||||
|
||||
// remove from old
|
||||
for (auto I = m_Groups.begin(); I != m_Groups.end(); ++I)
|
||||
I.value().removeAll(Name);
|
||||
|
||||
// add to new
|
||||
m_Groups[Group].append(Name);
|
||||
}
|
||||
|
||||
m_pSbieModel->Clear(); //todo improve that
|
||||
}
|
||||
|
||||
QString Grouping = CSbieView__SerializeGroup(m_Groups);
|
||||
theAPI->GetUserSettings()->SetText("BoxDisplayOrder", Grouping);
|
||||
}
|
||||
|
||||
void CSbieView::OnSandBoxAction()
|
||||
{
|
||||
QList<SB_STATUS> Results;
|
||||
|
@ -337,7 +481,39 @@ void CSbieView::OnSandBoxAction()
|
|||
}
|
||||
else if (Action == m_pMenuMkLink)
|
||||
{
|
||||
CSbieUtils::CreateDesktopShortcut(SandBoxes.first()->GetName(), theAPI);
|
||||
QString BoxName = SandBoxes.first()->GetName();
|
||||
QString LinkPath, IconPath, WorkDir;
|
||||
quint32 IconIndex;
|
||||
if (!CSbieUtils::GetStartMenuShortcut(theAPI, BoxName, LinkPath, IconPath, IconIndex, WorkDir))
|
||||
return;
|
||||
|
||||
QString LinkName;
|
||||
int pos = LinkPath.lastIndexOf(L'\\');
|
||||
if (pos == -1)
|
||||
return;
|
||||
if (pos == 2 && LinkPath.length() == 3)
|
||||
LinkName = QObject::tr("Drive %1").arg(LinkPath.left(1));
|
||||
else {
|
||||
LinkName = LinkPath.mid(pos + 1);
|
||||
pos = LinkName.indexOf(QRegExp("[" + QRegExp::escape("\":;,*?.") + "]"));
|
||||
if (pos != -1)
|
||||
LinkName = LinkName.left(pos);
|
||||
}
|
||||
|
||||
QString Path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).replace("/", "\\");
|
||||
//Path = QFileDialog::getExistingDirectory(this, tr("Select Directory to create Shorcut in"), Path).replace("/", "\\");
|
||||
//if (Path.isEmpty())
|
||||
// return;
|
||||
|
||||
if (Path.right(1) != "\\")
|
||||
Path.append("\\");
|
||||
Path += "[" + BoxName + "] " + LinkName;
|
||||
|
||||
Path = QFileDialog::getSaveFileName(this, tr("Create Shortcut to sandbox %1").arg(BoxName), Path, QString("Shortcut files (*.lnk)")).replace("/", "\\");
|
||||
if (Path.isEmpty())
|
||||
return;
|
||||
|
||||
CSbieUtils::CreateShortcut(theAPI, Path, LinkName, BoxName, LinkPath, IconPath, IconIndex, WorkDir);
|
||||
}
|
||||
else // custom run menu command
|
||||
{
|
||||
|
@ -422,13 +598,14 @@ void CSbieView::ProcessSelection(const QItemSelection& selected, const QItemSele
|
|||
return;
|
||||
|
||||
QItemSelectionModel* selectionModel = m_pSbieTree->selectionModel();
|
||||
|
||||
QItemSelection selection = selectionModel->selection();
|
||||
QItemSelection invalid;
|
||||
|
||||
/*
|
||||
QModelIndex root_parent = m_pSbieTree->currentIndex().parent();
|
||||
while (root_parent.isValid() && root_parent.parent().isValid())
|
||||
root_parent = root_parent.parent();
|
||||
|
||||
QItemSelection invalid;
|
||||
foreach(const QModelIndex& index, selection.indexes())
|
||||
{
|
||||
QModelIndex parent = index.parent();
|
||||
|
@ -437,7 +614,16 @@ void CSbieView::ProcessSelection(const QItemSelection& selected, const QItemSele
|
|||
|
||||
if (parent != root_parent)
|
||||
invalid.select(index, index);
|
||||
}*/
|
||||
|
||||
int Type = m_pSbieModel->GetType(m_pSortProxy->mapToSource(m_pSbieTree->currentIndex()));
|
||||
|
||||
foreach(const QModelIndex& index, selection.indexes())
|
||||
{
|
||||
if (m_pSbieModel->GetType(m_pSortProxy->mapToSource(index)) != Type)
|
||||
invalid.select(index, index);
|
||||
}
|
||||
|
||||
selectionModel->select(invalid, QItemSelectionModel::Deselect);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ signals:
|
|||
|
||||
public slots:
|
||||
void Refresh();
|
||||
void ReloadGroups();
|
||||
|
||||
private slots:
|
||||
void OnToolTipCallback(const QVariant& ID, QString& ToolTip);
|
||||
|
@ -29,6 +30,7 @@ private slots:
|
|||
void OnDoubleClicked(const QModelIndex& index);
|
||||
void ProcessSelection(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
|
||||
void OnGroupAction();
|
||||
void OnSandBoxAction();
|
||||
void OnProcessAction();
|
||||
|
||||
|
@ -39,6 +41,8 @@ protected:
|
|||
|
||||
virtual void UpdateRunMenu(const CSandBoxPtr& pBox);
|
||||
|
||||
QMap<QString, QStringList> m_Groups;
|
||||
|
||||
private:
|
||||
|
||||
QVBoxLayout* m_pMainLayout;
|
||||
|
@ -47,7 +51,9 @@ private:
|
|||
CSbieModel* m_pSbieModel;
|
||||
QSortFilterProxyModel* m_pSortProxy;
|
||||
|
||||
|
||||
QAction* m_pAddGroupe;
|
||||
QAction* m_pDelGroupe;
|
||||
int m_iMenuTop;
|
||||
QMenu* m_pMenuRun;
|
||||
QAction* m_pMenuRunAny;
|
||||
QAction* m_pMenuRunMenu;
|
||||
|
@ -68,6 +74,8 @@ private:
|
|||
QAction* m_pMenuRecover;
|
||||
QAction* m_pMenuCleanUp;
|
||||
QAction* m_pMenuRemove;
|
||||
QMenu* m_pMenuMoveTo;
|
||||
int m_iMoveTo;
|
||||
QAction* m_pMenuRename;
|
||||
int m_iMenuBox;
|
||||
|
||||
|
|
|
@ -234,6 +234,7 @@ COptionsWindow::COptionsWindow(const QSharedPointer<CSbieIni>& pBox, const QStri
|
|||
connect(ui.chkKeyTrace, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged()));
|
||||
connect(ui.chkIpcTrace, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged()));
|
||||
connect(ui.chkGuiTrace, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged()));
|
||||
connect(ui.chkDbgTrace, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged()));
|
||||
|
||||
connect(ui.chkHideOtherBoxes, SIGNAL(clicked(bool)), this, SLOT(OnAdvancedChanged()));
|
||||
connect(ui.btnAddProcess, SIGNAL(pressed()), this, SLOT(OnAddProcess()));
|
||||
|
@ -356,7 +357,7 @@ void COptionsWindow::LoadConfig()
|
|||
LoadStop();
|
||||
|
||||
{
|
||||
ui.chkStartBlockMsg->setEnabled(ui.radStartAll->isChecked());
|
||||
ui.chkStartBlockMsg->setEnabled(!ui.radStartAll->isChecked());
|
||||
ui.chkStartBlockMsg->setChecked(m_pBox->GetBool("NotifyStartRunAccessDenied", true));
|
||||
|
||||
m_StartChanged = false;
|
||||
|
@ -392,6 +393,7 @@ void COptionsWindow::LoadConfig()
|
|||
ReadAdvancedCheck("KeyTrace", ui.chkKeyTrace, "*");
|
||||
ReadAdvancedCheck("IpcTrace", ui.chkIpcTrace, "*");
|
||||
ReadAdvancedCheck("GuiTrace", ui.chkGuiTrace, "*");
|
||||
ui.chkDbgTrace->setChecked(m_pBox->GetBool("DebugTrace", false));
|
||||
|
||||
ui.chkHideOtherBoxes->setChecked(m_pBox->GetBool("HideOtherBoxes", false));
|
||||
QStringList Processes = m_pBox->GetTextList("HideHostProcess", false);
|
||||
|
@ -507,6 +509,7 @@ void COptionsWindow::SaveConfig()
|
|||
WriteAdvancedCheck(ui.chkKeyTrace, "KeyTrace", "*");
|
||||
WriteAdvancedCheck(ui.chkIpcTrace, "IpcTrace", "*");
|
||||
WriteAdvancedCheck(ui.chkGuiTrace, "GuiTrace", "*");
|
||||
WriteAdvancedCheck(ui.chkDbgTrace, "DebugTrace", "y");
|
||||
|
||||
WriteAdvancedCheck(ui.chkHideOtherBoxes, "HideOtherBoxes");
|
||||
|
||||
|
@ -992,7 +995,7 @@ void COptionsWindow::OnRestrictStart()
|
|||
else
|
||||
DelAccessEntry(eIPC, "<StartRunAccess>", eClosed, "*");
|
||||
|
||||
ui.chkStartBlockMsg->setEnabled(ui.radStartAll->isChecked());
|
||||
ui.chkStartBlockMsg->setEnabled(!ui.radStartAll->isChecked());
|
||||
//m_StartChanged = true;
|
||||
}
|
||||
|
||||
|
@ -1011,6 +1014,8 @@ void COptionsWindow::OnDelStartProg()
|
|||
void COptionsWindow::OnBlockINet()
|
||||
{
|
||||
bool Enable = ui.chkBlockINet->isChecked();
|
||||
ui.chkINetBlockPrompt->setEnabled(Enable);
|
||||
ui.chkINetBlockMsg->setEnabled(Enable);
|
||||
if (Enable)
|
||||
SetAccessEntry(eFile, "!<InternetAccess>", eClosed, "InternetAccessDevices");
|
||||
else
|
||||
|
@ -1030,14 +1035,6 @@ void COptionsWindow::OnDelINetProg()
|
|||
//m_INetBlockChanged = true;
|
||||
}
|
||||
|
||||
void COptionsWindow::OnINetBlockChanged()
|
||||
{
|
||||
ui.chkINetBlockPrompt->setEnabled(ui.chkBlockINet->isChecked());
|
||||
ui.chkINetBlockMsg->setEnabled(ui.chkBlockINet->isChecked());
|
||||
|
||||
m_INetBlockChanged = true;
|
||||
}
|
||||
|
||||
void COptionsWindow::AddProgToGroup(QTreeWidget* pTree, const QString& Groupe)
|
||||
{
|
||||
QString Value = SelectProgram();
|
||||
|
|
|
@ -87,7 +87,7 @@ private slots:
|
|||
void OnGeneralChanged();
|
||||
void OnStartChanged() { m_StartChanged = true; }
|
||||
//void OnRestrictionChanged() { m_RestrictionChanged = true; }
|
||||
void OnINetBlockChanged();
|
||||
void OnINetBlockChanged() { m_INetBlockChanged = true; }
|
||||
void OnRecoveryChanged() { m_RecoveryChanged = true; }
|
||||
void OnAdvancedChanged();
|
||||
void OnDebugChanged();
|
||||
|
|
|
@ -28,6 +28,13 @@ CSettingsWindow::CSettingsWindow(QWidget *parent)
|
|||
|
||||
ui.chkAutoStart->setChecked(IsAutorunEnabled());
|
||||
|
||||
switch (theConf->GetInt("Options/CheckForUpdates", 2)) {
|
||||
case 0: ui.chkAutoUpdate->setCheckState(Qt::Unchecked); break;
|
||||
case 1: ui.chkAutoUpdate->setCheckState(Qt::Checked); break;
|
||||
case 2: ui.chkAutoUpdate->setCheckState(Qt::PartiallyChecked); break;
|
||||
}
|
||||
|
||||
|
||||
ui.chkShellMenu->setCheckState((Qt::CheckState)CSbieUtils::IsContextMenu());
|
||||
|
||||
ui.chkDarkTheme->setChecked(theConf->GetBool("Options/DarkTheme", false));
|
||||
|
@ -140,6 +147,12 @@ void CSettingsWindow::apply()
|
|||
|
||||
AutorunEnable(ui.chkAutoStart->isChecked());
|
||||
|
||||
switch (ui.chkAutoUpdate->checkState()) {
|
||||
case Qt::Unchecked: theConf->SetValue("Options/CheckForUpdates", 0); break;
|
||||
case Qt::PartiallyChecked: theConf->SetValue("Options/CheckForUpdates", 2); break;
|
||||
case Qt::Checked: theConf->SetValue("Options/CheckForUpdates", 1); break;
|
||||
}
|
||||
|
||||
if (ui.chkShellMenu->checkState() != CSbieUtils::IsContextMenu())
|
||||
{
|
||||
if (ui.chkShellMenu->isChecked())
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
|
||||
CSettings* theConf = NULL;
|
||||
|
||||
void PackDriver();
|
||||
void UnPackDrivers();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -25,11 +22,6 @@ int main(int argc, char *argv[])
|
|||
QtSingleApplication app(argc, argv);
|
||||
|
||||
//InitConsole(false);
|
||||
if (app.arguments().contains("-rc4"))
|
||||
{
|
||||
PackDriver();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SB_STATUS Status = CSbieUtils::DoAssist();
|
||||
if (Status.GetStatus()) {
|
||||
|
@ -42,8 +34,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
theConf = new CSettings("Sandboxie-Plus");
|
||||
|
||||
UnPackDrivers();
|
||||
|
||||
//QThreadPool::globalInstance()->setMaxThreadCount(theConf->GetInt("Options/MaxThreadPool", 10));
|
||||
|
||||
CSandMan* pWnd = new CSandMan();
|
||||
|
@ -58,118 +48,3 @@ int main(int argc, char *argv[])
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TransformFile(const QString& InName, const QString& OutName, const QString& Key = "default_key")
|
||||
{
|
||||
QFile InFile(InName);
|
||||
QFile OutFile(OutName);
|
||||
if (InFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (OutFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
rc4_sbox_s sbox;
|
||||
rc4_init(&sbox, Key.toLatin1());
|
||||
OutFile.write(rc4_transform(&sbox, InFile.readAll()));
|
||||
OutFile.flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TestFile(const QString& OutName)
|
||||
{
|
||||
QThread::sleep(3);
|
||||
return QFile::exists(OutName);
|
||||
}
|
||||
|
||||
void PackDriver()
|
||||
{
|
||||
int pos = QCoreApplication::arguments().indexOf("-rc4");
|
||||
QString InName = QCoreApplication::arguments().at(pos + 1);
|
||||
QString OutName = InName;
|
||||
if (OutName.right(4) == ".rc4")
|
||||
OutName.truncate(OutName.length() - 4);
|
||||
else
|
||||
OutName.append(".rc4");
|
||||
|
||||
if (TransformFile(InName, OutName))
|
||||
printf("success\r\n");
|
||||
else
|
||||
printf("failed\r\n");
|
||||
}
|
||||
|
||||
bool NotifyCert()
|
||||
{
|
||||
QString Caption = QObject::tr(
|
||||
"<h3>Important Notie</h3>"
|
||||
);
|
||||
QString Text = QObject::tr(
|
||||
"<p>Sandboxie requires a driver to operate (SbieDrv.sys), Windows however denies loading a driver file that has not been digitally signed using an expensive <b>EV-Code Signing Certificate</b>. "
|
||||
"Such certificates cost upwards of 1000$ per year!</p>"
|
||||
"<p>Luckily brave hackers have Leaked a few of these Certificates over the years, one of them was found by the author of this software and put to good use.</p>"
|
||||
"<p>Unfortunately, such certificates have been abused by malware authors resulting in many Anti Malware Fools being Lazy and flagging Everything signed with them Wrongfully as Malware. "
|
||||
"This Prejudice is Damaging the Open Source Ecosystem as most nonprofit developers can't afford to waste this kind of money every year only to pay that <u>Windows Kernel \"Tax\"</u>.</p>"
|
||||
"<p>Therefore, the required driver is provided in an obfuscated form and before use must be unpacked. "
|
||||
"<font color='red'>When doing so said said Anti Viruses will complain and attempt to destroy the freshly created file.</font> "
|
||||
"Please be aware that this is a <u>false positive</u> caused by the necessary use of a compromitted certificate. "
|
||||
"If this happens you will be notified and offered the option to repeat the unpacking operation, for the operation to succeed you will need to <u>configure an aproproate exemption</u>.</p>"
|
||||
|
||||
"<p></p>"
|
||||
"<p><b>If you want the project to obtain a genuine EV-Code Signing Certificate please visit the <a href=\"https://xanasoft.com/\">Homepage</a> <font color='red'>and please donate</font></b>.</p>"
|
||||
"<p></p>"
|
||||
|
||||
"<p>If you want to proceed with the unpacking of the driver pres YES.</p>"
|
||||
);
|
||||
QMessageBox *msgBox = new QMessageBox(NULL);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->setWindowTitle("Sandboxie-Plus");
|
||||
msgBox->setText(Caption);
|
||||
msgBox->setInformativeText(Text);
|
||||
msgBox->setStandardButtons(QMessageBox::Yes);
|
||||
msgBox->addButton(QMessageBox::No);
|
||||
msgBox->setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
QIcon ico(QLatin1String(":/SandMan.png"));
|
||||
msgBox->setIconPixmap(ico.pixmap(64, 64));
|
||||
|
||||
return msgBox->exec() == QMessageBox::Yes;
|
||||
}
|
||||
|
||||
void UnPackDrivers()
|
||||
{
|
||||
bool notifyNotOk = false;
|
||||
QDir appDir(QApplication::applicationDirPath());
|
||||
foreach(const QString& FileName, appDir.entryList(QStringList("*.sys.rc4"), QDir::Files))
|
||||
{
|
||||
QString InName = QApplication::applicationDirPath() + "/" + FileName;
|
||||
QString OutName = InName.mid(0, InName.length() - 4);
|
||||
|
||||
QFileInfo InInfo(InName);
|
||||
QFileInfo OutInfo(OutName);
|
||||
if (InInfo.size() != OutInfo.size() /*|| InInfo.lastModified() > OutInfo.lastModified()*/)
|
||||
{
|
||||
if (theConf->GetBool("Options/NotifyUnPack", true)) {
|
||||
if (!NotifyCert()) {
|
||||
notifyNotOk = true;
|
||||
break;
|
||||
}
|
||||
theConf->SetValue("Options/NotifyUnPack", false);
|
||||
}
|
||||
|
||||
retry:
|
||||
if (!TransformFile(InName, OutName))
|
||||
QMessageBox::warning(NULL, "Sandboxie-Plus", QObject::tr("Failed to decrypt %1 ensure app directory is writable.").arg(FileName));
|
||||
else if (!TestFile(OutName))
|
||||
{
|
||||
if (QMessageBox("Sandboxie-Plus",
|
||||
QObject::tr("The decrypted file %1 seam to have been removed. Retry file extraction?").arg(FileName),
|
||||
QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::Cancel, QMessageBox::NoButton).exec() == QMessageBox::Yes)
|
||||
goto retry;
|
||||
notifyNotOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notifyNotOk)
|
||||
QMessageBox::warning(NULL, "Sandboxie-Plus", QObject::tr("Without the Driver Sandboxie-Plus wont be able to run properly."));
|
||||
}
|
Loading…
Reference in New Issue