2021-10-16 16:19:51 +01:00
|
|
|
/*
|
|
|
|
*
|
2023-08-06 19:14:29 +01:00
|
|
|
* Copyright 2020-2023 David Xanatos, xanasoft.com
|
2021-10-16 16:19:51 +01:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "SbieIni.h"
|
|
|
|
#include "../SbieAPI.h"
|
2023-04-20 20:52:30 +01:00
|
|
|
#include "../SbieDefs.h"
|
2021-10-16 16:19:51 +01:00
|
|
|
|
|
|
|
#include <ntstatus.h>
|
|
|
|
#define WIN32_NO_STATUS
|
|
|
|
typedef long NTSTATUS;
|
|
|
|
|
|
|
|
#include "..\..\Sandboxie\core\drv\api_flags.h"
|
|
|
|
|
|
|
|
CSbieIni::CSbieIni(const QString& Section, class CSbieAPI* pAPI, QObject* parent) : QObject(parent)
|
|
|
|
{
|
2022-01-13 22:52:58 +00:00
|
|
|
Q_ASSERT(!Section.isEmpty());
|
2021-10-16 16:19:51 +01:00
|
|
|
m_Name = Section;
|
|
|
|
m_pAPI = pAPI;
|
|
|
|
m_RefreshOnChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSbieIni::~CSbieIni()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::SetText(const QString& Setting, const QString& Value)
|
|
|
|
{
|
|
|
|
if (GetText(Setting) == Value)
|
|
|
|
return SB_OK;
|
|
|
|
return m_pAPI->SbieIniSet(m_Name, Setting, Value, CSbieAPI::eIniUpdate, m_RefreshOnChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::SetNum(const QString& Setting, int Value)
|
|
|
|
{
|
|
|
|
return SetText(Setting, QString::number(Value));
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::SetNum64(const QString& Setting, __int64 Value)
|
|
|
|
{
|
|
|
|
return SetText(Setting, QString::number(Value));
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::SetBool(const QString& Setting, bool Value)
|
|
|
|
{
|
|
|
|
return SetText(Setting, Value ? "y" : "n");
|
|
|
|
}
|
|
|
|
|
2022-11-29 15:49:16 +00:00
|
|
|
SB_STATUS CSbieIni::SetBoolSafe(const QString& Setting, bool Value)
|
|
|
|
{
|
2022-12-06 09:33:17 +00:00
|
|
|
QString StrValue = Value ? "y" : "n";
|
|
|
|
bool bAdd = true;
|
2022-11-29 15:49:16 +00:00
|
|
|
QStringList Values = GetTextList(Setting, false);
|
2022-12-06 09:33:17 +00:00
|
|
|
foreach(const QString & CurValue, Values) {
|
|
|
|
if (CurValue.contains(","))
|
2022-11-29 15:49:16 +00:00
|
|
|
continue;
|
2022-12-06 09:33:17 +00:00
|
|
|
if (CurValue == StrValue)
|
|
|
|
bAdd = false;
|
|
|
|
else
|
|
|
|
DelValue(Setting, CurValue);
|
2022-11-29 15:49:16 +00:00
|
|
|
}
|
2022-12-06 09:33:17 +00:00
|
|
|
if(bAdd)
|
|
|
|
return InsertText(Setting, StrValue);
|
|
|
|
return SB_OK;
|
2022-11-29 15:49:16 +00:00
|
|
|
}
|
|
|
|
|
2022-06-27 07:33:15 +01:00
|
|
|
QString CSbieIni::GetText(const QString& Setting, const QString& Default, bool bWithGlobal, bool bNoExpand, bool withTemplates) const
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
2022-06-27 07:33:15 +01:00
|
|
|
int flags = (bWithGlobal ? 0 : CONF_GET_NO_GLOBAL);
|
|
|
|
if (!withTemplates)
|
|
|
|
flags |= CONF_GET_NO_TEMPLS;
|
|
|
|
if (bNoExpand)
|
|
|
|
flags |= CONF_GET_NO_EXPAND;
|
|
|
|
|
2021-10-16 16:19:51 +01:00
|
|
|
QString Value = m_pAPI->SbieIniGet(m_Name, Setting, flags);
|
|
|
|
if (Value.isNull()) Value = Default;
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-08-10 19:14:37 +01:00
|
|
|
int CSbieIni::GetNum(const QString& Setting, int Default, bool bWithGlobal, bool withTemplates) const
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
2022-08-10 19:14:37 +01:00
|
|
|
QString StrValue = GetText(Setting, QString(), bWithGlobal, true, withTemplates);
|
2021-10-16 16:19:51 +01:00
|
|
|
bool ok;
|
|
|
|
int Value = StrValue.toInt(&ok);
|
|
|
|
if (!ok) return Default;
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-08-10 19:14:37 +01:00
|
|
|
__int64 CSbieIni::GetNum64(const QString& Setting, __int64 Default, bool bWithGlobal, bool withTemplates) const
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
2022-08-10 19:14:37 +01:00
|
|
|
QString StrValue = GetText(Setting, QString(), bWithGlobal, true, withTemplates);
|
2021-10-16 16:19:51 +01:00
|
|
|
bool ok;
|
2023-07-01 17:54:53 +01:00
|
|
|
__int64 Value = StrValue.toLongLong(&ok);
|
2021-10-16 16:19:51 +01:00
|
|
|
if (!ok) return Default;
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-08-10 19:14:37 +01:00
|
|
|
bool CSbieIni::GetBool(const QString& Setting, bool Default, bool bWithGlobal, bool withTemplates) const
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
2022-11-29 15:49:16 +00:00
|
|
|
QStringList Values = GetTextList(Setting, withTemplates, false, bWithGlobal);
|
|
|
|
foreach(const QString &StrValue, Values) {
|
|
|
|
if (StrValue.contains(","))
|
|
|
|
continue;
|
|
|
|
if (StrValue.compare("y", Qt::CaseInsensitive) == 0)
|
|
|
|
return true;
|
|
|
|
if (StrValue.compare("n", Qt::CaseInsensitive) == 0)
|
|
|
|
return false;
|
|
|
|
}
|
2021-10-16 16:19:51 +01:00
|
|
|
return Default;
|
|
|
|
}
|
|
|
|
|
2022-01-13 22:52:58 +00:00
|
|
|
QStringList CSbieIni::GetTextList(const QString &Setting, bool withTemplates, bool bExpand, bool bWithGlobal) const
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
|
|
|
QStringList TextList;
|
|
|
|
|
2022-01-13 22:52:58 +00:00
|
|
|
int flags = (bWithGlobal ? 0 : CONF_GET_NO_GLOBAL);
|
2021-10-16 16:19:51 +01:00
|
|
|
if (!withTemplates)
|
|
|
|
flags |= CONF_GET_NO_TEMPLS;
|
2022-01-13 22:52:58 +00:00
|
|
|
if (!bExpand)
|
2021-10-16 16:19:51 +01:00
|
|
|
flags |= CONF_GET_NO_EXPAND;
|
|
|
|
|
|
|
|
for (int index = 0; ; index++)
|
|
|
|
{
|
|
|
|
QString Value = m_pAPI->SbieIniGet(m_Name, Setting, index | flags);
|
|
|
|
if (Value.isNull())
|
|
|
|
break;
|
|
|
|
TextList.append(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TextList;
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::UpdateTextList(const QString &Setting, const QStringList& List, bool withTemplates)
|
|
|
|
{
|
|
|
|
QStringList OldSettings = GetTextList(Setting, withTemplates);
|
|
|
|
QStringList NewSettings;
|
|
|
|
foreach(const QString& Value, List) {
|
|
|
|
if (!OldSettings.removeOne(Value))
|
|
|
|
NewSettings.append(Value);
|
|
|
|
}
|
|
|
|
// delete removed or changed settings
|
|
|
|
foreach(const QString& Value, OldSettings)
|
|
|
|
DelValue(Setting, Value);
|
|
|
|
// add new or changed settings
|
|
|
|
foreach(const QString& Value, NewSettings)
|
2023-04-13 18:46:51 +01:00
|
|
|
AppendText(Setting, Value);
|
2021-10-16 16:19:51 +01:00
|
|
|
return SB_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList CSbieIni::GetTemplates() const
|
|
|
|
{
|
|
|
|
QStringList Templates;
|
2022-06-27 07:33:15 +01:00
|
|
|
Templates.append("GlobalSettings");
|
2021-10-16 16:19:51 +01:00
|
|
|
|
|
|
|
for (int tmpl_index = 0; ; tmpl_index++)
|
|
|
|
{
|
|
|
|
QString TmplName = m_pAPI->SbieIniGet(m_Name, "Template", tmpl_index | CONF_GET_NO_TEMPLS);
|
|
|
|
if (TmplName.isNull())
|
|
|
|
break;
|
|
|
|
Templates.append(TmplName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Templates;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList CSbieIni::GetTextListTmpl(const QString &Setting, const QString& Template) const
|
|
|
|
{
|
|
|
|
QStringList TextList;
|
|
|
|
|
|
|
|
for (int index = 0; ; index++)
|
|
|
|
{
|
2022-06-27 07:33:15 +01:00
|
|
|
QString Value = m_pAPI->SbieIniGet((Template != "GlobalSettings") ? "Template_" + Template : Template, Setting, index | CONF_GET_NO_GLOBAL | CONF_GET_NO_EXPAND);
|
2021-10-16 16:19:51 +01:00
|
|
|
if (Value.isNull())
|
|
|
|
break;
|
|
|
|
TextList.append(Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TextList;
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::InsertText(const QString& Setting, const QString& Value)
|
|
|
|
{
|
|
|
|
return m_pAPI->SbieIniSet(m_Name, Setting, Value, CSbieAPI::eIniInsert, m_RefreshOnChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::AppendText(const QString& Setting, const QString& Value)
|
|
|
|
{
|
|
|
|
return m_pAPI->SbieIniSet(m_Name, Setting, Value, CSbieAPI::eIniAppend, m_RefreshOnChange);
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::DelValue(const QString& Setting, const QString& Value)
|
|
|
|
{
|
|
|
|
return m_pAPI->SbieIniSet(m_Name, Setting, Value, CSbieAPI::eIniDelete, m_RefreshOnChange);
|
|
|
|
}
|
|
|
|
|
2023-04-20 20:52:30 +01:00
|
|
|
void CSbieIni::SetTextMap(const QString& Setting, const QMap<QString, QStringList> Map)
|
|
|
|
{
|
|
|
|
QStringList Mapping;
|
|
|
|
foreach(const QString& Group, Map.keys())
|
|
|
|
{
|
|
|
|
QString CurrentLine;
|
|
|
|
foreach(const QString & Name, Map[Group]) {
|
|
|
|
if (Setting.length() + 1 + Group.length() + 1 + CurrentLine.length() + 1 + Name.length() >= CONF_LINE_LEN) { // limit line length
|
|
|
|
Mapping.append(Group + ":" + CurrentLine);
|
|
|
|
CurrentLine.clear();
|
|
|
|
}
|
|
|
|
if (!CurrentLine.isEmpty()) CurrentLine.append(",");
|
|
|
|
CurrentLine.append(Name);
|
|
|
|
}
|
|
|
|
if(!CurrentLine.isEmpty())
|
|
|
|
Mapping.append(Group + ":" + CurrentLine);
|
|
|
|
}
|
|
|
|
DelValue(Setting);
|
|
|
|
foreach(const QString & Value, Mapping)
|
|
|
|
AppendText(Setting, Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
QMap<QString, QStringList> CSbieIni::GetTextMap(const QString& Setting)
|
|
|
|
{
|
|
|
|
QMap<QString, QStringList> Map;
|
|
|
|
foreach(const QString &CurrentLine, GetTextList(Setting, false)) {
|
|
|
|
int pos = CurrentLine.lastIndexOf(":");
|
|
|
|
Map[pos == -1 ? "" : CurrentLine.left(pos)].append(CurrentLine.mid(pos+1).split(","));
|
|
|
|
}
|
|
|
|
return Map;
|
|
|
|
}
|
|
|
|
|
2021-10-16 16:19:51 +01:00
|
|
|
QList<QPair<QString, QString>> CSbieIni::GetIniSection(qint32* pStatus, bool withTemplates) const
|
|
|
|
{
|
|
|
|
qint32 status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
int flags = CONF_GET_NO_EXPAND;
|
|
|
|
if (!withTemplates)
|
|
|
|
flags |= CONF_GET_NO_TEMPLS;
|
|
|
|
|
|
|
|
QList<QPair<QString, QString>> Settings;
|
|
|
|
for (int setting_index = 0; ; setting_index++)
|
|
|
|
{
|
|
|
|
QString setting_name = m_pAPI->SbieIniGet(m_Name, "", setting_index | flags, &status);
|
|
|
|
if (status == STATUS_RESOURCE_NAME_NOT_FOUND) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (int value_index = 0; ; value_index++)
|
|
|
|
{
|
|
|
|
QString setting_value = m_pAPI->SbieIniGet(m_Name, setting_name, value_index | CONF_GET_NO_GLOBAL | flags, &status);
|
|
|
|
if (status == STATUS_RESOURCE_NAME_NOT_FOUND) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
Settings.append(qMakePair(setting_name, setting_value));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pStatus) *pStatus = status;
|
|
|
|
return Settings;
|
|
|
|
}
|
|
|
|
|
2023-05-27 08:03:42 +01:00
|
|
|
SB_STATUS CSbieIni::RenameSection(const QString& NewName, bool deleteOld) // Note: deleteOld is used when duplicating a box
|
2021-10-16 16:19:51 +01:00
|
|
|
{
|
|
|
|
qint32 status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
if (m_Name.isEmpty() || NewName.isEmpty())
|
|
|
|
return SB_ERR();
|
|
|
|
bool SameName = (bool)(NewName.compare(m_Name, Qt::CaseInsensitive) == 0);
|
|
|
|
|
2022-12-07 10:58:37 +00:00
|
|
|
// Get all Settings
|
2021-10-16 16:19:51 +01:00
|
|
|
QList<QPair<QString, QString>> Settings = GetIniSection(&status);
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
return SB_ERR(SB_FailedCopyConf, QVariantList() << m_Name << (quint32)status, status);
|
|
|
|
|
|
|
|
// check if such a box already exists
|
|
|
|
if (!SameName)
|
|
|
|
{
|
|
|
|
m_pAPI->SbieIniGet(NewName, "", CONF_GET_NO_EXPAND, &status);
|
|
|
|
if (status != STATUS_RESOURCE_NAME_NOT_FOUND)
|
|
|
|
return SB_ERR(SB_AlreadyExists, QVariantList() << NewName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the name is the same we first delete than write,
|
2022-12-07 16:32:40 +00:00
|
|
|
// else we first write and than delete, for safety reasons
|
2021-10-16 16:19:51 +01:00
|
|
|
if (deleteOld && SameName)
|
|
|
|
goto do_delete;
|
|
|
|
|
|
|
|
do_write:
|
2022-12-07 10:58:37 +00:00
|
|
|
// Apply all Settings
|
2021-10-16 16:19:51 +01:00
|
|
|
for (QList<QPair<QString, QString>>::iterator I = Settings.begin(); I != Settings.end(); ++I)
|
|
|
|
{
|
|
|
|
SB_STATUS Status = m_pAPI->SbieIniSet(NewName, I->first, I->second, CSbieAPI::eIniInsert, true);
|
|
|
|
if (Status.IsError())
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
do_delete:
|
2023-08-06 19:14:29 +01:00
|
|
|
// Delete ini section
|
2021-10-16 16:19:51 +01:00
|
|
|
if (deleteOld)
|
|
|
|
{
|
|
|
|
SB_STATUS Status = m_pAPI->SbieIniSet(m_Name, "*", "", CSbieAPI::eIniUpdate, true);
|
|
|
|
if (Status.IsError())
|
|
|
|
return SB_ERR(SB_DeleteFailed, QVariantList() << m_Name << (quint32)Status.GetStatus(), Status.GetStatus());
|
|
|
|
deleteOld = false;
|
|
|
|
|
|
|
|
if (SameName)
|
|
|
|
goto do_write;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_RefreshOnChange)
|
|
|
|
m_pAPI->CommitIniChanges();
|
|
|
|
|
2023-05-27 08:03:42 +01:00
|
|
|
m_Name = NewName;
|
|
|
|
|
2021-10-16 16:19:51 +01:00
|
|
|
return SB_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
SB_STATUS CSbieIni::RemoveSection()
|
|
|
|
{
|
|
|
|
return m_pAPI->SbieIniSet(m_Name, "*", "", CSbieAPI::eIniUpdate, m_RefreshOnChange);
|
2022-12-07 16:32:40 +00:00
|
|
|
}
|