fixed #I7DFN9 #I7DF5I #I72LFX #I72P8K #I5XHG7

This commit is contained in:
lidecheng 2023-09-05 09:07:25 +08:00
parent 779441b092
commit 120794a195
57 changed files with 5659 additions and 959 deletions

View File

@ -1,5 +1,11 @@
[Desktop Entry]
Name=backup-daemon
Name[zh_CN]=备份还原守护进程
Name[zh_HK]=備份還原守護進程
Name[bo_CN]=གྲབས་ཉར་སོར་ལོག་ལྟ་སྲུང་འཕེལ་རིམ་
Name[mn]=ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠵᠤ ᠰᠠᠬᠢᠬᠤ ᠠᠬᠢᠴᠠ
Type=Application
Comment=The daemon process of kybackup.
Exec=/usr/bin/backup-daemon %U
Icon=yhkylin-backup-tools
NoDisplay=true

View File

@ -2,6 +2,7 @@
#include <QStorageInfo>
#include <QDateTime>
#include <QDebug>
#include <QRegularExpression>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
@ -54,6 +55,21 @@ bool CustomizeDataBackupProxy::checkEnvEx()
return false;
}
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
emit checkResult(int(BackupResult::DU_ERR));
return false;
}
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
Utils::mkpath(m_backupWrapper.m_prefixDestPath);

View File

@ -4,6 +4,7 @@
#include <QDateTime>
#include <QDebug>
#include <QTimer>
#include <QRegularExpression>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
@ -60,6 +61,21 @@ bool CustomizeSystemBackupProxy::checkEnvEx()
return false;
}
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
emit checkResult(int(BackupResult::DU_ERR));
return false;
}
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
Utils::mkpath(m_backupWrapper.m_prefixDestPath);
@ -230,6 +246,7 @@ QStringList CustomizeSystemBackupProxy::getRsyncArgs(CustomizeSystemBackupScene
args << "--ignore-missing-args";
break ;
case CustomizeSystemBackupScene::MKSQUASHFS :
// 在mksquashfs时排除bind挂载的任意一方时都备份不上
Utils::excludeFstabBindPath(excludes);
// --exclude=排除路径设置
for (QString item : m_backupWrapper.m_backupExcludePaths) {

View File

@ -115,18 +115,20 @@ bool CustomizeSystemRestoreProxy::doPrepare()
if (!mountImg())
return false;
// 2、停止安全防护
QProcess::execute("systemctl stop kysec-init.service");
// 2、停止安全初始化服务以防过高的CPU占有率因为还原时安全初始化服务会逐个文件打标记造成cpu占有率超高系统卡顿
Utils::stopKysecInit();
// 停止网络服务,以防网络更新
Utils::stopNetwork();
// 3、以读写方式重新挂载boot分区因为有的机器默认以只读挂载
remountBoot();
Utils::remountBoot();
// 4、是否有/boot/efi目录有则认为有efi分区需重新rw挂载
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
efiPath.replace("//", "/");
if (!Utils::isDirEmpty(efiPath)) {
// 重新rw读写挂载
remountEfi();
Utils::remountEfi();
}
qDebug() << "CustomizeSystemRestoreProxy::doPrepare invoke end";

View File

@ -29,16 +29,11 @@ rootpath=$2
m_mountPath=$3
m_default_uuid=$4
BACKUP=
if [[ -e "${rootpath}/backup/BACKUP/snapshots" ]]; then
BACKUP="/BACKUP"
fi
m_backuplistPath=${m_mountPath}${BACKUP}"/snapshots/backuplist.xml"
EXCLUDEFILE=${m_mountPath}${BACKUP}"/snapshots/.exclude"
PLOGFILEDIR="${m_mountPath}${BACKUP}/log"
m_backuplistPath="${m_mountPath}/snapshots/backuplist.xml"
EXCLUDEFILE="${m_mountPath}/snapshots/.exclude"
PLOGFILEDIR="${m_mountPath}/log"
PLOGFILE="$PLOGFILEDIR/log-$(date +%Y%m%d%H%M)"
LOGFILE="${m_mountPath}${BACKUP}/log.txt" #LOGFILE="/tmp/log.txt"
LOGFILE="${m_mountPath}/log.txt" #LOGFILE="/tmp/log.txt"
#是否是出厂备份
m_isFactory=false
@ -49,7 +44,7 @@ PERSONAL_BACKUPFILE=".user.txt"
m_isRetainUserData=false
#如果/backup不存在则创建该目录
mkdir -p ${m_mountPath}${BACKUP}
mkdir -p ${m_mountPath}
if [ $? -ne 0 ]; then
echo "Could not create /backup in initrd!"
exit 20
@ -111,7 +106,7 @@ getBackupInfo() {
#该函数是对backup-daemon/parsebackuplist.cpp中相应函数的替换
createBackupList() {
local backuplistDir=${m_mountPath}${BACKUP}"/snapshots/"
local backuplistDir="${m_mountPath}/snapshots/"
if [ ! -e "$backuplistDir" ]; then
mkdir -p $backuplistDir
@ -653,8 +648,8 @@ backuping() {
#0:backup 1:restore
generateExcludeFile 0
echo "/" > ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
cp $EXCLUDEFILE ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE
echo "/" > ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
cp $EXCLUDEFILE ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE
#echo "Begin to backup efi directory..." >>$PLOGFILE
#echo "Begin to backup efi directory..."
@ -826,8 +821,8 @@ deleteItemByComment() {
}
DeleteFactoryBackup() {
if [ -e "/backup${BACKUP}/snapshots/{${factory_uuid}}" ]; then
rm /backup${BACKUP}/snapshots/{${factory_uuid}} -rf
if [ -e "/backup/snapshots/{${factory_uuid}}" ]; then
rm /backup/snapshots/{${factory_uuid}} -rf
fi
local comment=$(findCommentByUuid "{${factory_uuid}}")
@ -862,7 +857,7 @@ backupAuto() { #备份
# echo "BYbobbi: m_uuid is $m_uuid"
m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
m_comment=$m_time #这个是全局变量
dst="${m_mountPath}${BACKUP}/snapshots/$m_uuid/data"
dst="${m_mountPath}/snapshots/$m_uuid/data"
#echo "dst: $dst"
mkdir -p $dst
m_size=$global_system_usedDisk
@ -942,7 +937,7 @@ backupAuto() { #备份
rm -f $tmpFile
#写文件
metainfo_file="${m_mountPath}${BACKUP}/snapshots/$m_uuid/$METAINFO"
metainfo_file="${m_mountPath}/snapshots/$m_uuid/$METAINFO"
#echo "metainfo_file="$metainfo_file
#第1行清空写
#这里写的不是xml文件是一个文本文件这时候的状态是backup unfinished
@ -958,12 +953,13 @@ backupAuto() { #备份
#返回值:
getLastUsefulBackupPointUuid() {
local xxx currentUuid foundComment
local xxx currentUuid foundComment currentComment
currentUuid=""
currentState=false
currentType=true
lastUsefulBackupPointUuid=""
foundComment=0 #是否发现了要修改的comment
currentComment=""
lastbackupname=""
#如果不定义IFS则echo $line会去掉前后空格导致写到文件中去时没有格式
@ -975,7 +971,7 @@ getLastUsefulBackupPointUuid() {
#echo "xxx: $xxx"
if [[ "$xxx" =~ "<Comment>" ]]; then
lastbackupname=$xxx
currentComment=$xxx
fi
if [[ "$xxx" =~ "<Uuid>" ]]; then
@ -1004,6 +1000,7 @@ getLastUsefulBackupPointUuid() {
if [[ "$xxx" =~ "</BackupPoint>" ]]; then
if [ "$currentState" = true -a "$currentType" = true ]; then #"/backup"是不是一个独立的盘
lastUsefulBackupPointUuid=$currentUuid
lastbackupname=$currentComment
fi
fi
done <"$m_backuplistPath"
@ -1041,7 +1038,7 @@ restoreAuto() { #还原
local m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
writeLogFile "${m_time},${uuid},4,grub系统还原,,,${lastbackupname}" #grub时只有一键还原没有增量还原
restoreDir="${m_mountPath}${BACKUP}/snapshots/$uuid"
restoreDir="${m_mountPath}/snapshots/$uuid"
if [ ! -e "$restoreDir" ]; then
echo "full restore directory not exists!"
@ -1165,18 +1162,29 @@ restoreAuto() { #还原
echo "restore other directories end"
echo "restore other directories end" >>$PLOGFILE
sync
#还原时清空目录
#if [ -e "$rootpath/home/data" ]; then
# rm -r "$rootpath/home/data" ]
#fi
#mkdir -p "$rootpath/home/data" ]
grub-install
}
#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
updateBackupAutoFinishedState() {
echo "this is updateBackupAutoFinishedState"
}
restoreBackupSelf() {
restoreDir="${rootpath}/var/log/yhkylin-backup-tools"
echo $restoreDir
if [ ! -e "$restoreDir" ]; then
echo "restoreBackupSelf error: no files"
return 1
fi
# 还原rsync/kybackup/backup-daemon等程序
rsync -avAXHr ${restoreDir}/backup-daemon ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1
rsync -avAXHr ${restoreDir}/kybackup ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1
rm -rf ${restoreDir}
}
#-----------------------------------------------------------------
@ -1187,13 +1195,16 @@ if [ "${rootpath}" = "/" ]; then
# exit
fi
getBackupInfo
#echo "m_restoreUuid="$m_restoreUuid
#echo "m_enabled="$m_enabled
#不加引号报错
if [ "$m_restoreUuid" = "" ] || [ "$m_enabled" = "" ]; then
echo "bootinfo file is not correct!"
exit 3
# 还原自身不需要挂载备份分区
if [ $backupORrestore != "--restorebackupself" ]; then
getBackupInfo
#echo "m_restoreUuid="$m_restoreUuid
#echo "m_enabled="$m_enabled
#不加引号报错
if [ "$m_restoreUuid" = "" ] || [ "$m_enabled" = "" ]; then
echo "bootinfo file is not correct!"
exit 3
fi
fi
mkdir -p ${rootpath}/var/log
@ -1241,6 +1252,8 @@ elif [ $backupORrestore = "--factoryrestore" ]; then
#umountBackup
echo "This is factorybackup"
elif [ $backupORrestore = "--restorebackupself" ]; then
restoreBackupSelf
else
echo "Not correct command"
exit 18

View File

@ -65,6 +65,7 @@ ExistCopyExec /bin/ls /bin
ExistCopyExec /bin/mount /bin
ExistCopyExec /bin/sync /bin
ExistCopyExec /sbin/reboot /bin
ExistCopyExec /sbin/grub-install /bin
#fix wrong timezone in initrd(#)
#ExistCopyExec /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

View File

@ -30,6 +30,7 @@ echo $*
BACKUP_FLAG=backup
RESTORE_FLAG=restore
ROLLBACK_FLAG=rollback-backup
IS_NORMAL=
#. /scripts/security-functions
show_text_mesg()
@ -133,7 +134,7 @@ is_990_9a0=$(get_is_990_9a0)
factory_restore_warnning()
{
if [ x${is_990_9a0} == x"true" ]; then
if [[ x${is_990_9a0} == x"true" && x${FACTORY_RESTORE} == "xy" ]]; then
local is_sure=
while :
do
@ -156,7 +157,7 @@ factory_restore_warnning()
factory_restore_warnning_again()
{
if [ x${is_990_9a0} == x"true" ]; then
if [[ x${is_990_9a0} == x"true" && x"$FACTORY_RESTORE" = "xy" ]]; then
local is_sure=
while :
do
@ -310,6 +311,7 @@ for x in $(cat /proc/cmdline); do
FACTORY_RESTORE=y
;;
*)
IS_NORMAL=y
;;
esac
done

View File

@ -52,6 +52,7 @@ bool MountBackupProcess::umountBackupPartition()
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
backupPath.replace("//","/");
QStringList arguments;
arguments << "-R";
arguments << backupPath;
m_p->start("umount", arguments);
if (!m_p->waitForStarted()) {

View File

@ -17,6 +17,7 @@
<Type>2</Type>
<Position>0</Position>
<UserId>1000</UserId>
<PrefixDestPath>/</PrefixDestPath>
</BackupPoint>
</backupList>
*/
@ -299,7 +300,10 @@ void ParseBackupList::getCustomizePaths(QStringList &customizePaths)
QDomElement elePrefixPath = node.firstChildElement(PREFIXDESTPATH);
if (!elePrefixPath.isNull()) {
customizePaths << elePrefixPath.text() + BACKUP_SNAPSHOTS_PATH;
QString prefixPath = elePrefixPath.text() + BACKUP_SNAPSHOTS_PATH;
prefixPath.replace("//", "/");
if (!customizePaths.contains(prefixPath))
customizePaths << prefixPath;
}
}
}
@ -512,10 +516,10 @@ ParseBackupList::ParseResult ParseBackupList::updateItem(const BackupPoint & bac
if (i < list.count()) {
// 移除旧节点,更新后的节点放到最后
root.removeChild(list.at(i));
QDomElement newNode = doc.createElement(BACKUPPOINT);
backupPointToElementNode(backupPoint, doc, newNode);
root.appendChild(newNode);
}
QDomElement newNode = doc.createElement(BACKUPPOINT);
backupPointToElementNode(backupPoint, doc, newNode);
root.appendChild(newNode);
QFile xmlFile(m_xmlPath);
if (!xmlFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {

View File

@ -120,30 +120,36 @@ void SystemBackupProxy::deleteFailedData()
bool SystemBackupProxy::isIncBackup()
{
QString backupPath;
ParseBackupList::BackupPoint point;
if (m_backupWrapper.m_uuid.isEmpty()) {
QString xmlPath(Utils::getSysRootPath() + BACKUP_XML_PATH);
xmlPath.replace("//", "/");
ParseBackupList parser(xmlPath);
ParseBackupList::BackupPoint point;
point = parser.getLastSysBackupPoint();
if (point.m_uuid.isEmpty())
return false;
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + point.m_uuid + "/data";
backupPath.replace("//", "/");
if (Utils::isDirExist(backupPath)) {
m_backupWrapper.m_baseUuid = point.m_uuid;
m_backupWrapper.m_bIncrement = true;
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
return true;
}
} else {
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
m_backupPoint = parse.findBackupPointByUuid(m_backupWrapper.m_uuid);
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
backupPath.replace("//", "/");
if (!m_backupPoint.m_backupName.isEmpty()) {
m_backupWrapper.m_bIncrement = true;
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
return true;
}
}
backupPath.replace("//", "/");
if (Utils::isDirExist(backupPath) && !point.m_backupName.isEmpty()) {
m_backupWrapper.m_baseUuid = point.m_uuid;
m_backupWrapper.m_bIncrement = true;
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
return true;
}
return false;
}
@ -399,10 +405,11 @@ bool SystemBackupProxy::recordBackupPoint()
m_backupPoint.m_size = Utils::StringBySize(m_size);
m_backupPoint.m_time = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss");
m_backupPoint.m_state = BACKUP_PARSE_STATE_FAIL_STRTING;
m_backupPoint.m_path = m_backupWrapper.m_prefixDestPath;
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
xmlPath.replace("//", "/");
ParseBackupList parse(xmlPath);
if (m_backupWrapper.m_uuid.isEmpty() || !m_backupWrapper.m_bIncrement) {
if (m_backupWrapper.m_uuid.isEmpty() /*|| !m_backupWrapper.m_bIncrement*/) {
if (parse.addItem(m_backupPoint) != ParseBackupList::SUCCESS) {
emit checkResult(int(BackupResult::WRITE_STORAGEINFO_ADD_ITEM_FAIL));
return false;

View File

@ -113,6 +113,9 @@ bool SystemRestoreProxy::restoreEfi()
{
qDebug() << "SystemRestoreProxy::restoreEfi invoke begin";
// 以读写方式重新挂载boot分区因为有的机器默认以只读挂载
Utils::remountBoot();
// 是否有/boot/efi目录
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
efiPath.replace("//", "/");
@ -122,7 +125,7 @@ bool SystemRestoreProxy::restoreEfi()
sync();
// 2、重新rw读写挂载
remountEfi();
Utils::remountEfi();
// 3、同步efi
return rsyncEfi();
@ -149,34 +152,6 @@ void SystemRestoreProxy::repairEfi()
}
}
/**
* @brief rw读写挂载efi分区
*/
void SystemRestoreProxy::remountEfi()
{
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief rw读写挂载boot分区
*/
void SystemRestoreProxy::remountBoot()
{
QString mountPath = Utils::getSysRootPath() + "/boot";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief efi
*/
@ -286,7 +261,7 @@ QStringList SystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
args << "--exclude=/usr/bin/rsync";
args << "--exclude=/usr/share/rsync";
args << "--exclude=/usr/share/initramfs-tools/hooks/kybackup-hooks";
args << "--exclude=/usr/share/initramfs-tools/scripts/local-bottom/kybackup";
args << "--exclude=/usr/share/initramfs-tools/scripts/*/kybackup";
// 还原后仍然保持激活状态
args << "--exclude=/etc/LICENSE";
@ -363,16 +338,15 @@ QStringList SystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
*/
void SystemRestoreProxy::restoreSystem()
{
// 停止安全防护
QProcess::execute("systemctl stop kysec-init.service");
// 停止安全初始化服务以防过高的CPU占有率因为还原时安全初始化服务会逐个文件打标记造成cpu占有率超高系统卡顿
Utils::stopKysecInit();
// 停止网络服务,以防网络更新
Utils::stopNetwork();
// 本地系统备份没有img挂载故下面两个路径相等
m_srcPath = m_backupPath;
QString destPath = Utils::getSysRootPath();
// 以读写方式重新挂载boot分区因为有的机器默认以只读挂载
remountBoot();
QStringList args;
// 自动更新的备份还原时保留用户数据
if (m_curUuid == AUTO_BACKUP_UUID || m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
@ -395,6 +369,15 @@ void SystemRestoreProxy::restoreSystem()
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,,," + m_backupPoint.m_backupName);
// 华为9a0等机型设定1分钟后关机重启原因运行时还原备份还原工具本身可能会造成运行中的备份还原崩溃从而无法执行到后面的自动重启代码故在此预设。
// 不再只华为机型使用此方法,将全部机型都改为此方法,缩短操作链
// if (Utils::isHuawei990())
{
QString msg;
Utils::executeCMD("shutdown -r +1", msg);
qDebug() << msg;
}
Utils::updateSyncFile();
Utils::wait(2);
QString fileIfSync = Utils::getSysRootPath() + FILE_IF_SYNC;
@ -417,7 +400,9 @@ void SystemRestoreProxy::restoreSystem()
removeHome(QString(Utils::getSysRootPath() + "/data/home").replace("//", "/"));
}
QProcess::execute("sync");
// 最后再一次还原home目录以查缺补漏因为系统还原过程中~/.config等目录中的部分文件可能会更新会引起部分bug如任务栏固定图标还原不完整等
this->rsyncAgain();
::sync();
// 2209后新增了一些依赖还原到以前的4.0.13版后缺少依赖无法运行故此最后还得还原backup-daemon和kybackup本身
// 兼容Qt库从5.12.8升级到5.15,系统还原的最后也将备份还原工具本身还原
// QString version = Utils::getBackupVersion();
@ -425,22 +410,32 @@ void SystemRestoreProxy::restoreSystem()
if (Utils::getSysRootPath() != CASPER_ROOT_PATH)
{
// initrd.img已经还原为旧状态需要将新版本的backup-auto-efi等脚本文件更新到initrd.img中这样我们修改后的新逻辑才能生效
// QString msg;
// Utils::executeCMD("update-initramfs -u", msg);
// qDebug() << msg;
// 解决bug:182576 【2203自适应升级2309】【2303自适应升级2309】升级成功还原系统失败应该是有更新包修改了UEFI固件查找引导器文件的引导地址
// 故系统还原完成后重新执行下grub-install命令
QString msg;
Utils::executeCMD("update-initramfs -u", msg);
Utils::executeCMD("grub-install", msg);
qDebug() << msg;
// 写入标记rsync_backup_self:${UUID}到文件/etc/file_if_sync中表示需要还原backup-daemon和kybackup本身
QString line("rsync_backup_self:");
line += m_curUuid;
Utils::syncWriteFile(fileIfSync, line);
// QString line("rsync_backup_self:");
// line += m_curUuid;
// Utils::syncWriteFile(fileIfSync, line);
// this->undoRestoreData();
// 加一层保险(因为有些机型上使用"update-initramfs -u"命令会失败华为9006c的2203版等
// QString version = Utils::getBackupVersion();
// if (Utils::isHuawei990() && version.contains("4.0.13"))
this->rsyncBackupSelf();
::sync();
// Utils::wait(5);
}
Utils::wait(5);
emit this->workResult(result);
Utils::wait(2);
Utils::wait(3);
reboot(RB_AUTOBOOT);
} else {
emit this->workResult(result);
@ -545,3 +540,78 @@ void SystemRestoreProxy::removeHome(const QString& path)
qDebug() << "SystemRestoreProxy::removeHome invoke end";
}
/**
* @brief
* @note
* 1~/.config等目录中的部分文件可能会更新bug
* a.
* b. desktop文件
* c. 1%
*/
void SystemRestoreProxy::rsyncAgain()
{
// 保留用户数据还原直接
if (m_bRetainUserData)
return ;
QString destPath = Utils::getSysRootPath() + "/home/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/home/";
args << destPath;
process->start(args);
}
/**
* @brief initrd阶段执行备份还原脚本时再进行还原
* @note
*/
void SystemRestoreProxy::undoRestoreData()
{
QString destPath = Utils::getSysRootPath() + "/var/log/yhkylin-backup-tools/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/usr/bin/backup-daemon";
args << destPath;
process->start(args);
args.clear();
args << "-avAHXr";
args << m_srcPath + "/usr/bin/kybackup";
args << destPath;
process->start(args);
}
/**
* @brief
* @note undoRestoreData基础上增加的一层保险使"update-initramfs -u"9006c的2203版等
* /etc/profile.d//etc/init.d/.sh脚本文件以开机时自动执行
*/
void SystemRestoreProxy::rsyncBackupSelf()
{
QString destPath = Utils::getSysRootPath() + "/usr/bin/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/usr/bin/kybackup";
args << destPath;
process->start(args);
args.clear();
args << "-avAHXr";
args << m_srcPath + "/usr/bin/backup-daemon";
args << destPath;
process->start(args);
}

View File

@ -32,10 +32,6 @@ private:
bool restoreEfi();
// 修复efi目录
void repairEfi();
// 以读写方式重新挂载efi分区
void remountEfi();
// 以读写方式重新挂载boot分区
void remountBoot();
// 同步efi
bool rsyncEfi();
// 系统还原
@ -45,6 +41,20 @@ private:
// 获取备份点里存在家目录的用户列表
QStringList getBackupPointUsers();
QStringList getBackupPointUsers(const QString& path);
// 待还原数据
void undoRestoreData();
// 还原备份还原工具自身
void rsyncBackupSelf();
/**
* @brief
* @note
* 1~/.config等目录中的部分文件可能会更新bug
* a.
* b. desktop文件
* c. 1%
*/
void rsyncAgain();
/**
* @brief rsync命令参数

View File

@ -3,6 +3,7 @@
#include <QDateTime>
#include <QDebug>
#include <QTimer>
#include <QRegularExpression>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
@ -45,6 +46,21 @@ bool UDiskDataBackupProxy::checkEnvEx()
return false;
}
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
emit checkResult(int(BackupResult::DU_ERR));
return false;
}
QString backupPath(m_backupWrapper.m_prefixDestPath);
backupPath.replace("//", "/");
QStorageInfo udisk(backupPath);

View File

@ -4,6 +4,7 @@
#include <QDateTime>
#include <QDebug>
#include <QTimer>
#include <QRegularExpression>
#include "../common/utils.h"
#include "../common/mydusizetool.h"
#include "mymountproxy.h"
@ -65,6 +66,21 @@ bool UDiskSystemBackupProxy::checkEnvEx()
return false;
}
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
emit checkResult(int(BackupResult::DU_ERR));
return false;
}
QString backupPath(m_backupWrapper.m_prefixDestPath);
backupPath.replace("//", "/");
QStorageInfo udisk(backupPath);
@ -293,8 +309,9 @@ QStringList UDiskSystemBackupProxy::getRsyncArgs(UDiskSystemBackupScene scene)
args << "--ignore-missing-args";
break ;
case UDiskSystemBackupScene::MKSQUASHFS :
// 在mksquashfs时排除bind挂载的任意一方时都备份不上
Utils::excludeFstabBindPath(excludes);
// --exclude=排除路径设置
// -e 排除路径设置
for (QString item : m_backupWrapper.m_backupExcludePaths) {
if (excludes.contains(item))
continue;

View File

@ -116,6 +116,9 @@ bool UDiskSystemRestoreProxy::restoreEfi()
{
qDebug() << "UDiskSystemRestoreProxy::restoreEfi invoke begin";
// 以读写方式重新挂载boot分区因为有的机器默认以只读挂载
Utils::remountBoot();
// 是否有/boot/efi目录
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
efiPath.replace("//", "/");
@ -124,7 +127,7 @@ bool UDiskSystemRestoreProxy::restoreEfi()
repairEfi();
// 2、重新rw读写挂载
remountEfi();
Utils::remountEfi();
// 3、同步efi
return rsyncEfi();
@ -152,34 +155,6 @@ void UDiskSystemRestoreProxy::repairEfi()
}
}
/**
* @brief rw读写挂载efi分区
*/
void UDiskSystemRestoreProxy::remountEfi()
{
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief rw读写挂载boot分区
*/
void UDiskSystemRestoreProxy::remountBoot()
{
QString mountPath = Utils::getSysRootPath() + "/boot";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
QProcess::execute("mount", args);
}
/**
* @brief efi
*/
@ -244,7 +219,7 @@ QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
args << "--exclude=/data/home";
args << "--exclude=/data/root";
// 云桌面背景路径属于用户数据
// 云图片作为桌面背景路径属于用户数据
args << "--exclude=/var/lib/AccountsService";
// 域用户相关信息,还原后保持不退域
@ -289,7 +264,7 @@ QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
args << "--exclude=/usr/bin/rsync";
args << "--exclude=/usr/share/rsync";
args << "--exclude=/usr/share/initramfs-tools/hooks/kybackup-hooks";
args << "--exclude=/usr/share/initramfs-tools/scripts/local-bottom/kybackup";
args << "--exclude=/usr/share/initramfs-tools/scripts/*/kybackup";
// 还原后仍然保持激活状态
args << "--exclude=/etc/LICENSE";
@ -397,9 +372,6 @@ bool UDiskSystemRestoreProxy::doPrepare()
} else
m_srcPath = m_backupPath;
// 以读写方式重新挂载boot分区因为有的机器默认以只读挂载
remountBoot();
qDebug() << "UDiskSystemRestoreProxy::doPrepare invoke end";
return true;
}
@ -418,8 +390,10 @@ void UDiskSystemRestoreProxy::restoreSystem()
return ;
}
// 停止安全防护
QProcess::execute("systemctl stop kysec-init.service");
// 停止安全初始化服务以防过高的CPU占有率因为还原时安全初始化服务会逐个文件打标记造成cpu占有率超高系统卡顿
Utils::stopKysecInit();
// 停止网络服务,以防网络更新
Utils::stopNetwork();
QString destPath = Utils::getSysRootPath();
@ -427,6 +401,7 @@ void UDiskSystemRestoreProxy::restoreSystem()
// 自动更新的备份还原时保留用户数据
if (m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
args = getRsyncArgs(SystemRestoreScene::RESTORE_SYSTEM_WITH_DATA);
m_bRetainUserData = true;
} else {
args = getRsyncArgs(SystemRestoreScene::SYSTEM_RESTORE);
}
@ -445,6 +420,15 @@ void UDiskSystemRestoreProxy::restoreSystem()
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,,," + m_backupPoint.m_backupName);
// 华为9a0等机型设定1分钟后关机重启原因运行时还原备份还原工具本身可能会造成运行中的备份还原崩溃从而无法执行到后面的自动重启代码故在此预设。
// 不再只华为机型使用此方法,将全部机型都改为此方法,缩短操作链
// if (Utils::isHuawei990())
{
QString msg;
Utils::executeCMD("shutdown -r +1", msg);
qDebug() << msg;
}
Utils::updateSyncFile();
Utils::wait(2);
QString fileIfSync = Utils::getSysRootPath() + FILE_IF_SYNC;
@ -471,6 +455,10 @@ void UDiskSystemRestoreProxy::restoreSystem()
Utils::wait(5);
}
// 最后再一次还原home目录以查缺补漏因为系统还原过程中~/.config等目录中的部分文件可能会更新会引起部分bug如任务栏固定图标还原不完整等
this->rsyncAgain();
::sync();
// 2209后新增了一些依赖还原到以前的4.0.13版后缺少依赖无法运行故此最后还得还原backup-daemon和kybackup本身
// 兼容Qt库从5.12.8升级到5.15,系统还原的最后也将备份还原工具本身还原
// QString version = Utils::getBackupVersion();
@ -478,16 +466,28 @@ void UDiskSystemRestoreProxy::restoreSystem()
if (Utils::getSysRootPath() != CASPER_ROOT_PATH)
{
// initrd.img已经还原为旧状态需要将新版本的backup-auto-efi等脚本文件更新到initrd.img中这样我们修改后的新逻辑才能生效
// QString msg;
// Utils::executeCMD("update-initramfs -u", msg);
// qDebug() << msg;
// 解决bug:182576 【2203自适应升级2309】【2303自适应升级2309】升级成功还原系统失败应该是有更新包修改了UEFI固件查找引导器文件的引导地址
// 故系统还原完成后重新执行下grub-install命令
QString msg;
Utils::executeCMD("update-initramfs -u", msg);
Utils::executeCMD("grub-install", msg);
qDebug() << msg;
// 写入标记rsync_backup_self:${UUID}到文件/etc/file_if_sync中表示需要还原backup-daemon和kybackup本身
QString line("rsync_backup_self:");
line += m_curUuid;
Utils::syncWriteFile(fileIfSync, line);
// QString line("rsync_backup_self:");
// line += m_curUuid;
// Utils::syncWriteFile(fileIfSync, line);
// this->undoRestoreData();
// 加一层保险(因为有些机型上使用"update-initramfs -u"命令会失败华为9006c的2203版等
// QString version = Utils::getBackupVersion();
// if (Utils::isHuawei990() && version.contains("4.0.13"))
this->rsyncBackupSelf();
::sync();
Utils::wait(5);
}
}
@ -497,7 +497,7 @@ void UDiskSystemRestoreProxy::restoreSystem()
m_isFinished = true;
if (result) {
Utils::wait(2);
Utils::wait(3);
reboot(RB_AUTOBOOT);
}
});
@ -567,4 +567,79 @@ bool UDiskSystemRestoreProxy::checkUdiskExists()
return true;
}
/**
* @brief
* @note
* 1~/.config等目录中的部分文件可能会更新bug
* a.
* b. desktop文件
* c. 1%
*/
void UDiskSystemRestoreProxy::rsyncAgain()
{
// 保留用户数据还原直接
if (m_bRetainUserData)
return ;
QString destPath = Utils::getSysRootPath() + "/home/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/home/";
args << destPath;
process->start(args);
}
/**
* @brief initrd阶段执行备份还原脚本时再进行还原
* @note
*/
void UDiskSystemRestoreProxy::undoRestoreData()
{
QString destPath = Utils::getSysRootPath() + "/var/log/yhkylin-backup-tools/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/usr/bin/backup-daemon";
args << destPath;
process->start(args);
args.clear();
args << "-avAHXr";
args << m_srcPath + "/usr/bin/kybackup";
args << destPath;
process->start(args);
}
/**
* @brief
* @note undoRestoreData基础上增加的一层保险使"update-initramfs -u"9006c的2203版等
* /etc/profile.d//etc/init.d/.sh脚本文件以开机时自动执行
*/
void UDiskSystemRestoreProxy::rsyncBackupSelf()
{
QString destPath = Utils::getSysRootPath() + "/usr/bin/";
destPath.replace("//", "/");
Utils::mkpath(destPath);
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
QStringList args;
args << "-avAHXr";
args << m_srcPath + "/usr/bin/kybackup";
args << destPath;
process->start(args);
args.clear();
args << "-avAHXr";
args << m_srcPath + "/usr/bin/backup-daemon";
args << destPath;
process->start(args);
}

View File

@ -35,10 +35,6 @@ private:
bool restoreEfi();
// 修复efi目录
void repairEfi();
// 以读写方式重新挂载efi分区
void remountEfi();
// 以读写方式重新挂载boot分区
void remountBoot();
// 同步efi
bool rsyncEfi();
// 系统还原
@ -47,6 +43,20 @@ private:
bool doPrepare();
// 异机还原时更新grub.cfg中的分区UUID
void updateGrubUUid();
// 待还原数据
void undoRestoreData();
// 还原备份还原工具自身
void rsyncBackupSelf();
/**
* @brief
* @note
* 1~/.config等目录中的部分文件可能会更新bug
* a.
* b. desktop文件
* c. 1%
*/
void rsyncAgain();
/**
* @brief rsync命令参数
@ -74,6 +84,8 @@ private:
ParseBackupList::BackupPoint m_backupPoint;
// 强制结束标志(stop后没反应的情况系统处于睡眠状态)
bool m_isForce;
// 是否保留用户数据
bool m_bRetainUserData = false;
};
#endif // UDISKSYSTEMRESTOREPROXY_H

View File

@ -758,7 +758,8 @@ bool Utils::writeBackupLog(QString line)
*/
bool Utils::syncWriteFile(const QString &fileName, const QString& content)
{
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(std::fopen(fileName.toStdString().data(), "a+"), std::fclose);
qDebug() << fileName << content;
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(std::fopen(fileName.toStdString().data(), "w"), std::fclose);
if (!fp) {
std::perror("file opening failed!");
@ -1521,3 +1522,49 @@ QString Utils::getBackupVersion()
return version;
}
/**
* @brief rw读写挂载efi分区
*/
void Utils::remountEfi()
{
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
Utils::executeCmd("mount", args);
}
/**
* @brief rw读写挂载boot分区
*/
void Utils::remountBoot()
{
QString mountPath = Utils::getSysRootPath() + "/boot";
mountPath.replace("//", "/");
QStringList args;
args << "-o"
<< "rw,remount"
<< mountPath;
Utils::executeCmd("mount", args);
}
/**
* @brief
*/
void Utils::stopKysecInit()
{
Utils::executeCmd("systemctl stop kysec-init.service");
}
/**
* @brief
*/
void Utils::stopNetwork()
{
Utils::executeCmd("service network-manager stop");
}

View File

@ -401,6 +401,26 @@ public:
*/
static QString getBackupVersion();
/**
* @brief rw读写挂载efi分区
*/
static void remountEfi();
/**
* @brief rw读写挂载boot分区
*/
static void remountBoot();
/**
* @brief
*/
static void stopKysecInit();
/**
* @brief
*/
static void stopNetwork();
/**
* @brief
* @param logfile

View File

@ -78,10 +78,7 @@ Or click "Update Backup" button, pop up data backup list window. As shown in fig
![Fig 15 data backup list -big](image/15.png)
Then, click "Next" button, enter backup checking page --> backup preparing --> backuping --> backup finished. Such as system backup.
- **Update Data Backup** -- On the basis of a data backup, update the backup data.
- **Data Recovery** -- Recovery the data to its previous backup state, and the function is similar to system restore.
![Fig 16 Data recovery-big](image/16.png)

View File

@ -78,9 +78,7 @@
选择好备份路径后,单击“下一步”按钮,进入环境检测-->备份准备-->备份中-->备份完成等环节,和系统备份类似。
数据备份首页右下角的“备份管理”,可用来查看数据备份状态,删除无效备份。
- **数据增量备份** —— 在某个数据备份的基础上,更新备份点的数据。
- **数据还原** —— 还原到某个数据备份的状态,功能与系统还原相似。
![图 16 数据还原主界面-big](image/16.png)
@ -147,7 +145,6 @@ Tips如果制作镜像文件时带有数据分区则在下一步“安装
## 常见问题
- 无法使用备份还原
在安装操作系统时,必须要选中“创建备份还原分区”,备份还原才能使用。
- 备份分区空间不足
备份分区(/backup大小是安装系统时固定的一般也不会太大随着系统的使用量逐渐增大会造成备份空间不足无法进行备份的情况。此时可以备份到移动设备上不过备份速度会变慢。
建议系统只进行一个初装备份到备份分区,后面的系统备份都备份到移动设备上。比较重要的数据统一放到某个目录中,用数据备份功能进行备份。

12
debian/changelog vendored
View File

@ -1,3 +1,15 @@
yhkylin-backup-tools (4.1.0.1-ok7) v101; urgency=medium
* BUG :【备份还原】切换至平板模式时,窗口没有最大化
【备份还原】窗口选项菜单未翻译成中文
【备份还原】菜单-退出按钮显示Exit预期显示退出
【备份还原】gurb备份/还原系统时,显示乱码
* 需求号:无
* 其它改动:无
* 其它影响域:无
-- lidecheng <lidecheng@kylinos.cn> Mon, 04 Sep 2023 18:03:27 +0800
yhkylin-backup-tools (4.1.0.1-ok6) yangtze; urgency=medium
* BUG :【备份还原】【次要】删除备份成功的弹窗,关闭按钮无悬浮提示

View File

@ -180,6 +180,7 @@ void BackupPointListDialog::keyPressEvent(QKeyEvent* event)
{
switch (event->key()) {
case Qt::Key_Escape:
this->close();
case Qt::Key_Up:
case Qt::Key_Down:
case Qt::Key_Left:

View File

@ -315,17 +315,17 @@ bool BackupListWidget::checkPathLimit(const QString &path)
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
// if ( path.contains(QRegularExpression(".*`.*`.*"))
// || path.contains(QRegularExpression(".*\\$\\(.*\\).*"))
// || path.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
// || path.contains(QRegularExpression("[;&|]+"))) {
// MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
// return false;
// }
if ( path.contains(QRegularExpression(".*`.*`.*"))
|| path.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| path.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| path.contains(QRegularExpression("[;&|]+"))) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
return false;
}
// 1、列表中是否已经存在
if (contains(path)) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
QObject::tr("Path already exists : ") + path,
QObject::tr("OK"));
return false;
@ -334,7 +334,7 @@ bool BackupListWidget::checkPathLimit(const QString &path)
// 2、路径是否存在
QFileInfo fileInfo(path);
if (!fileInfo.exists()) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
QObject::tr("The file or directory does not exist : ") + path,
QObject::tr("OK"));
return false;
@ -343,8 +343,9 @@ bool BackupListWidget::checkPathLimit(const QString &path)
// 3、是否是限定路径及其子路径
bool blimit = false;
QString dirCanBeSelected;
QString abstractPath = fileInfo.absoluteFilePath();
for (const QString &item : m_pathLimit) {
if (path.startsWith(item)) {
if (abstractPath.startsWith(item)) {
blimit = true;
break;
}
@ -357,7 +358,7 @@ bool BackupListWidget::checkPathLimit(const QString &path)
}
}
if (m_pathLimit.size() > 0 && !blimit) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
QObject::tr("Only data that exists in the follow directorys can be selected: %1.\n Path:%2 is not in them.").arg(dirCanBeSelected).arg(path),
QObject::tr("OK"));
return false;

View File

@ -1,6 +1,10 @@
#include "backuppositionselectdialog.h"
#include <QDialogButtonBox>
#include <QLineEdit>
#include <QPushButton>
#include "filefilterproxymodelforbackup.h"
#include "../../common/utils.h"
#include "../messageboxutils.h"
BackupPositionSelectDialog::BackupPositionSelectDialog(QWidget* parent) :
QFileDialog(parent)
@ -8,19 +12,85 @@ BackupPositionSelectDialog::BackupPositionSelectDialog(QWidget* parent) :
setWindowTitle(tr("Please select a path"));
setViewMode(QFileDialog::Detail);
setFileMode(QFileDialog::DirectoryOnly);
setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QList<QUrl> siderUrls;
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
QList<QString> localDisks = Utils::getLocalDisks();
for (const QString& path: localDisks) {
siderUrls << QUrl::fromLocalFile(path);
}
setSidebarUrls(siderUrls);
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
setProxyModel(proxy);
// 主题和文管重构了QFileDialog下面代码已经失效
// setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
// QList<QUrl> siderUrls;
// siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
// siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
// QList<QString> localDisks = Utils::getLocalDisks();
// for (const QString& path: localDisks) {
// siderUrls << QUrl::fromLocalFile(path);
// }
// setSidebarUrls(siderUrls);
// FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
// setProxyModel(proxy);
}
BackupPositionSelectDialog::~BackupPositionSelectDialog()
{}
bool BackupPositionSelectDialog::checkSelectedFiles()
{
QStringList selectFiles = selectedFiles();
for (const QString & fileName : selectFiles) {
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( fileName.contains(QRegularExpression(".*`.*`.*"))
|| fileName.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| fileName.contains(QRegularExpression("[;&|]+"))) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
return false;
}
// 主题重新实现了QFileDialog后很多功能已经丢失(如:文件夹过滤等),需要再次进行过滤,真难用
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
backupPath.replace("//", "/");
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return false;
} else if (fileName.endsWith(BACKUP_PATH)) {
QString subfile = fileName + "/snapshots";
if (Utils::isDirExist(subfile)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return false;
}
}
}
return true;
}
void BackupPositionSelectDialog::goAccept()
{
if (checkSelectedFiles())
accept();
}
// 主题和文管重构了QFileDialog需要使用下面代码绑定accept信号
void BackupPositionSelectDialog::showEvent(QShowEvent* event)
{
Q_UNUSED(event)
if (this->isVisible()) {
for (QWidget* widget : this->findChildren<QWidget*>()) {
if (widget->objectName() == "acceptButton") {
QPushButton * btn = qobject_cast<QPushButton*>(widget);
disconnect(btn, &QPushButton::clicked, 0, 0);
connect(btn, &QPushButton::clicked, [=](bool checked){
Q_UNUSED(checked)
this->goAccept();
});
}
}
}
}

View File

@ -9,6 +9,13 @@ class BackupPositionSelectDialog : public QFileDialog {
public:
explicit BackupPositionSelectDialog(QWidget* parent = nullptr);
virtual ~BackupPositionSelectDialog();
bool checkSelectedFiles();
public slots:
void goAccept();
protected:
void showEvent(QShowEvent* event) override;
};

View File

@ -20,17 +20,17 @@ bool FileFilterProxyModeForBackup::filterAcceptsRow(int sourceRow, const QModelI
QString fileName = fileModel->fileName(index0);
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// if (fileName.contains(QRegularExpression(".*`.*`.*")))
// return false;
// // 2、形如$()的文件夹名称
// if (fileName.contains(QRegularExpression(".*\\$\\(.*\\).*")))
// return false;
// // 3、形如${}的文件夹名称
// if (fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*")))
// return false;
// // 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
// if (fileName.contains(QRegularExpression("[;&|]+")))
// return false;
if (fileName.contains(QRegularExpression(".*`.*`.*")))
return false;
// 2、形如$()的文件夹名称
if (fileName.contains(QRegularExpression(".*\\$\\(.*\\).*")))
return false;
// 3、形如${}的文件夹名称
if (fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*")))
return false;
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if (fileName.contains(QRegularExpression("[;&|]+")))
return false;
QString filePath = fileModel->filePath(index0);
if (fileName == "backup") {

View File

@ -3,12 +3,13 @@
#include <QLineEdit>
#include <QPushButton>
#include "filefilterproxymodelforbackup.h"
#include "../messageboxutils.h"
MyFileSelect::MyFileSelect(QWidget* parent) :
QFileDialog(parent)
{
this->setFileMode(QFileDialog::ExistingFiles);
// sdk和文管重构了QFileDialog下面代码已经失效
// 主题和文管重构了QFileDialog下面代码已经失效
/*
this->setViewMode(QFileDialog::Detail);
this->setFilter(QDir::System | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
@ -27,15 +28,37 @@ MyFileSelect::MyFileSelect(QWidget* parent) :
*/
}
bool MyFileSelect::checkSelectedFiles()
{
QStringList selectFiles = selectedFiles();
for (const QString & fileName : selectFiles) {
// 防命令注入
// 1、形如mkdir '`id&>id_bak_test.txt`'中的文件夹名称
// 2、形如$()的文件夹名称
// 3、形如${}的文件夹名称
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
if ( fileName.contains(QRegularExpression(".*`.*`.*"))
|| fileName.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|| fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|| fileName.contains(QRegularExpression("[;&|]+"))) {
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
return false;
}
}
return true;
}
void MyFileSelect::goAccept()
{
accept();
if (checkSelectedFiles())
accept();
}
MyFileSelect::~MyFileSelect()
{}
// sdk和文管重构了QFileDialog需要使用下面代码绑定accept信号
// 主题和文管重构了QFileDialog需要使用下面代码绑定accept信号
void MyFileSelect::showEvent(QShowEvent* event)
{
Q_UNUSED(event)

View File

@ -9,6 +9,7 @@ public:
explicit MyFileSelect(QWidget* parent = nullptr);
virtual ~MyFileSelect();
bool checkSelectedFiles();
public slots:
void goAccept();

View File

@ -3,13 +3,13 @@
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPainter>
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
#include <unistd.h>
#include "globalbackupinfo.h"
#include "../common/mydefine.h"
#include "../common/utils.h"
#include "messageboxutils.h"
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
DeleteBackupDialog::DeleteBackupDialog(ParseBackupList::BackupPoint backupPonit, QWidget *parent) :
QDialog(parent),

View File

@ -0,0 +1,10 @@
#! /bin/bash
ts_file_list=(`ls *.ts`)
for ts in "${ts_file_list[@]}"
do
lrelease "${ts}"
done
mv *.qm resource/language/

View File

@ -146,14 +146,20 @@ FORMS += \
OTHER_FILES +=
TRANSLATIONS += qt_zh_CN.ts \
qt_bo_CN.ts
qt_bo_CN.ts \
qt_mn_MN.ts \
qt_zh_HK.ts
system(rm -f qt_zh_CN.qm)
!system(lrelease qt_zh_CN.ts): error("Failed to generate cp qt_zh_CN.qm")
system(cp qt_zh_CN.qm resource/language/)
system(rm -f qt_bo_CN.qm)
!system(lrelease qt_bo_CN.ts): error("Failed to generate qt_bo_CN.qm")
system(cp qt_bo_CN.qm resource/language/)
message($$system(./generate_translations_qm.sh))
#system(rm -f qt_zh_CN.qm)
#!system(lrelease qt_zh_CN.ts): error("Failed to generate cp qt_zh_CN.qm")
#system(cp qt_zh_CN.qm resource/language/)
#system(rm -f qt_bo_CN.qm)
#!system(lrelease qt_bo_CN.ts): error("Failed to generate qt_bo_CN.qm")
#system(cp qt_bo_CN.qm resource/language/)
#system(rm -f qt_mn_MN.qm)
#!system(lrelease qt_mn_MN.ts): error("Failed to generate qt_mn_MN.qm")
#system(cp qt_mn_MN.qm resource/language/)
RESOURCES += \
app.qrc

View File

@ -57,16 +57,17 @@ int main(int argc, char *argv[])
GlobelBackupInfo::instance().setIsWayland(true);
}
MainDialog w;
// 居中窗口
centerToScreen(&w);
a.setWindowIcon(QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS, QIcon(":/images/yhkylin-backup-tools.png")));
a.setActivationWindow(&w, true);
a.setApplicationName(QObject::tr("Backup & Restore"));
a.setApplicationVersion("4.1.0.0-0k17.18");
//如果是第一个实例,则绑定,方便下次调用
QObject::connect(&a,SIGNAL(messageReceived(const QString&)),&w,SLOT(sltMessageReceived(const QString&)));
w.show();
// 居中窗口
centerToScreen(&w);
return a.exec();
}
@ -82,53 +83,70 @@ void initApp(QApplication& a)
// 区分中英文
QString locale = QLocale::system().name();
// QT自身标准的翻译
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qt_");
translatorFileName += locale;
QTranslator *selfTransOfQt = new QTranslator();
if (selfTransOfQt->load(translatorFileName, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
if (selfTransOfQt->load(QLocale(), QString("qt"), QString("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
a.installTranslator(selfTransOfQt);
else
qDebug() << "load qt translator file failed!";
#endif
// 应用内的翻译
QTranslator *translator = new QTranslator();
if (locale == "zh_CN") {
//中文需要翻译
if (!translator->load(":/language/qt_zh_CN.qm")) //qtcreator启动后看到在资源目录下
qDebug() << "load translator file failed!";
else
a.installTranslator(translator);
} else if (locale == "bo_CN") {
//藏文需要翻译
if (!translator->load(":/language/qt_bo_CN.qm")) //qtcreator启动后看到在资源目录下
qDebug() << "load translator file failed!";
else
a.installTranslator(translator);
}
// 部分sdk控件用到翻译文件
QTranslator *transGui = new QTranslator();
if (locale == "zh_CN")
{
if(transGui->load(":/translations/gui_zh_CN.qm"))
if (locale == "zh_CN") {
if (transGui->load(":/translations/gui_zh_CN.qm"))
{
a.installTranslator(transGui);
}
} else if (locale == "bo_CN")
{
if(transGui->load(":/translations/gui_bo_CN.qm"))
} else if (locale == "bo_CN") {
if (transGui->load(":/translations/gui_bo_CN.qm"))
{
a.installTranslator(transGui);
}
} else if (locale == "mn_MN" || locale == "mn") {
if (transGui->load(":/translations/gui_mn.qm")) {
a.installTranslator(transGui);
}
} else if (locale == "zh_HK") {
if(transGui->load(":/translations/gui_zh_HK.qm")) {
a.installTranslator(transGui);
}
}
// 命令行参数
QCoreApplication::setApplicationName(QObject::tr("kybackup"));
QCoreApplication::setApplicationVersion("4.0.14");
// 应用内的翻译
QTranslator *translator = new QTranslator();
QString translatorResourceName(":/language/qt_");
translatorResourceName += locale;
translatorResourceName += ".qm";
if (!translator->load(translatorResourceName)) //qtcreator启动后看到在资源目录下
qDebug() << translatorResourceName << "load translator file failed!";
else {
a.installTranslator(translator);
qDebug() << translatorResourceName << "load translator file success!";
}
// if (locale == "zh_CN") {
// //中文需要翻译
// if (!translator->load(":/language/qt_zh_CN.qm")) //qtcreator启动后看到在资源目录下
// qDebug() << "load translator file failed!";
// else
// a.installTranslator(translator);
// } else if (locale == "bo_CN") {
// //藏文需要翻译
// if (!translator->load(":/language/qt_bo_CN.qm")) //qtcreator启动后看到在资源目录下
// qDebug() << "load translator file failed!";
// else
// a.installTranslator(translator);
// } else if (locale == "mn_MN") {
// //蒙古文需要翻译
// if (!translator->load(":/language/qt_mn_MN.qm")) //qtcreator启动后看到在资源目录下
// qDebug() << "load translator file failed!";
// else
// a.installTranslator(translator);
// }
// 命令行参数
QCommandLineParser parser;
parser.setApplicationDescription("kybackup helper");
parser.addHelpOption();
@ -219,7 +237,6 @@ void centerToScreen(QWidget* widget)
{
if (!widget)
return;
int x = widget->width();
int y = widget->height();

View File

@ -17,7 +17,6 @@
#include "aboutdialog.h"
#include "gsettingswrapper.h"
#include "component/mywidget.h"
#include "../common/dynamiccreator.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
@ -126,7 +125,7 @@ void MainDialog::initTileBar()
m_maxBtn = new QPushButton;
m_closeBtn = new QPushButton;
m_menuOptionBtn->setToolTip(tr("Main menu"));
m_menuOptionBtn->setToolTip(tr("Options"));
m_minBtn->setToolTip(tr("Minimize"));
m_maxBtn->setToolTip(tr("Maximize"));
m_closeBtn->setToolTip(tr("Close"));
@ -179,7 +178,7 @@ void MainDialog::initTileBar()
backupMain->addAction(m_backupHelp);
m_backupAbout = new QAction(tr("About"), m_titleWidget);
backupMain->addAction(m_backupAbout);
m_backupExit = new QAction(tr("Exit"), m_titleWidget);
m_backupExit = new QAction(tr("Quit"), m_titleWidget);
backupMain->addAction(m_backupExit);
m_titleLayout->addStretch();

View File

@ -5,6 +5,7 @@
#include "../common/mydefine.h"
#include "globalsignals.h"
#include "globalbackupinfo.h"
#include <QPushButton>
MyMessageBox::MyMessageBox(QWidget *parent) :
@ -48,8 +49,8 @@ void MessageBoxUtils::QMESSAGE_BOX_INFORMATION(QWidget* q_parent, const QString&
box->setMsgIcon(QMessageBox::Information);
box->setWindowTitle(typelabel);
box->setText(message);
box->setStandardButtons(QMessageBox::Ok);
box->setButtonText(QMessageBox::Ok, label);
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
box->setDefaultButton(okbtn);
box->exec();
}
@ -59,8 +60,8 @@ void MessageBoxUtils::QMESSAGE_BOX_WARNING(QWidget* q_parent, const QString& typ
box->setMsgIcon(QMessageBox::Warning);
box->setWindowTitle(typelabel);
box->setText(message);
box->setStandardButtons(QMessageBox::Ok);
box->setButtonText(QMessageBox::Ok, label);
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
box->setDefaultButton(okbtn);
box->exec();
}
@ -70,10 +71,11 @@ bool MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(QWidget *q_parent, const QStri
box->setMsgIcon(QMessageBox::Question);
box->setWindowTitle(typelabel);
box->setText(message);
box->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
box->setButtonText(QMessageBox::Ok, label_yes);
box->setButtonText(QMessageBox::Cancel, label_no);
if (box->exec() != QMessageBox::Ok) {
QPushButton * okbtn = box->addButton(label_yes, QMessageBox::AcceptRole);
box->addButton(label_no, QMessageBox::RejectRole);
box->setDefaultButton(okbtn);
box->exec();
if (box->clickedButton() != okbtn) {
return false;
}
@ -86,7 +88,7 @@ void MessageBoxUtils::QMESSAGE_BOX_CRITICAL(QWidget* q_parent, const QString& ty
box->setMsgIcon(QMessageBox::Critical);
box->setWindowTitle(typelabel);
box->setText(message);
box->setStandardButtons(QMessageBox::Ok);
box->setButtonText(QMessageBox::Ok, label);
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
box->setDefaultButton(okbtn);
box->exec();
}

View File

@ -50,13 +50,13 @@ DataBackup::DataBackup(QWidget *parent /*= nullptr*/) :
m_pInterface(nullptr)
{
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initSecondWidget_inc();
initThirdWidget();
initForthWidget();
initFifthWidget();
initLastWidget();
initHomePage();
initSetBackupPathsPage();
initSetIncPathsPage();
initCheckPage();
initNameBackupPage();
initBackupingPage();
initLastPage();
}
DataBackup::~DataBackup()
@ -71,7 +71,7 @@ DataBackup::~DataBackup()
/**
* @brief
*/
void DataBackup::initFirstWidget()
void DataBackup::initHomePage()
{
QWidget *homePage = new QWidget;
QVBoxLayout *vLayout = new QVBoxLayout;
@ -225,6 +225,7 @@ void DataBackup::initFirstWidget()
backupPointManage->setProperty("useButtonPalette", true);
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
bottomHBoxLayout->addWidget(backupPointManage);
@ -243,15 +244,19 @@ void DataBackup::initFirstWidget()
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::styleNameChanged, this, [=](bool isDark) {
Q_UNUSED(isDark)
// 深浅主题切换时,因为调色板已经更换,高亮等颜色已经改变,所以要重新加载图标。
// from席博文因为按钮的文字颜色换了一个类型因为设计非要什么半透明透明效果的Text就是半透明的buttontext就是不半透明。所以将ButtonText改为Text
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
});
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::themeColorChanged, this, [=]() {
// 强调色更换,高亮等颜色已经改变,所以要重新加载图标。
// from席博文因为按钮的文字颜色换了一个类型因为设计非要什么半透明透明效果的Text就是半透明的buttontext就是不半透明。所以将ButtonText改为Text
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
});
@ -288,7 +293,7 @@ void DataBackup::on_next_clicked(bool checked)
/**
* @brief
*/
void DataBackup::initSecondWidget()
void DataBackup::initSetBackupPathsPage()
{
QWidget *selectPathPage = new QWidget;
@ -515,25 +520,7 @@ void DataBackup::initSecondWidget()
if (!selectFiles.isEmpty()) {
QString fileName = selectFiles.at(0);
// sdk重新实现了QFileDialog后很多功能已经丢失(如:文件夹过滤等),需要再次进行过滤,真难用
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
backupPath.replace("//", "/");
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return ;
} else if (fileName.endsWith(BACKUP_PATH)) {
QString subfile = fileName + "/snapshots";
if (Utils::isDirExist(subfile)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return ;
}
} else if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
// 选择了移动设备挂载目录的子孙目录
// 移动设备只能选择挂载目录本身
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
@ -671,7 +658,7 @@ void DataBackup::getPathsLimit(QStringList &pathLimits, QList<QUrl> &siderUrls)
/**
* @brief ()
*/
void DataBackup::initSecondWidget_inc()
void DataBackup::initSetIncPathsPage()
{
QWidget *incSelectPathPage = new QWidget;
@ -935,9 +922,9 @@ void DataBackup::addOldBackupPaths(BackupListWidget *listWidget)
}
/**
* @brief
* @brief
*/
void DataBackup::initThirdWidget()
void DataBackup::initCheckPage()
{
QWidget *checkPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -1335,10 +1322,10 @@ void DataBackup::on_checkEnv_end(int result)
}
/**
* @brief
* @brief
*/
#define MAX_LEN_BACKUPNAME 64
void DataBackup::initForthWidget()
void DataBackup::initNameBackupPage()
{
QWidget *nameBackupPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -1616,9 +1603,9 @@ bool DataBackup::isExistsBackupName(const QString & backupName)
}
/**
* @brief
* @brief
*/
void DataBackup::initFifthWidget()
void DataBackup::initBackupingPage()
{
QWidget *backupingPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -1669,7 +1656,6 @@ void DataBackup::initFifthWidget()
hlayoutTopLine2->addWidget(label4);
hlayoutTopLine2->addSpacing(11);
vlayout->addLayout(hlayoutTopLine2);
vlayout->addSpacing(80);
// ------------ 中部布局begin-------------
@ -1706,8 +1692,8 @@ void DataBackup::initFifthWidget()
hlayoutCenterFont2->addStretch();
hlayoutCenterFont2->setAlignment(Qt::AlignCenter);
vlayout->addLayout(hlayoutCenterFont2);
vlayout->addSpacing(56);
// 第三行
QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
// 取消按钮
@ -1737,6 +1723,10 @@ void DataBackup::initFifthWidget()
// 不要使用电脑,以防数据丢失
labelTip->setDeplayText(tr("Do not use computer in case of data loss"));
cancel->setEnabled(true);
if (this->m_isIncrement)
cancel->setVisible(false);
else
cancel->setVisible(true);
// 开始备份
this->on_backup_start();
@ -1897,7 +1887,7 @@ void DataBackup::on_backup_end(bool result)
/**
* @brief
*/
void DataBackup::initLastWidget()
void DataBackup::initLastPage()
{
QWidget *last = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;

View File

@ -37,13 +37,13 @@ public:
~DataBackup();
private:
void initFirstWidget();
void initSecondWidget();
void initSecondWidget_inc();
void initThirdWidget();
void initForthWidget();
void initFifthWidget();
void initLastWidget();
void initHomePage();
void initSetBackupPathsPage();
void initSetIncPathsPage();
void initCheckPage();
void initNameBackupPage();
void initBackupingPage();
void initLastPage();
QList<ParseBackupList::BackupPoint> getBackupPointList();
bool isExistsBackupName(const QString & backupName);

View File

@ -39,10 +39,10 @@ DataRestore::DataRestore(QWidget *parent) :
m_pInterface = nullptr;
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initLastWidget();
initHomePage();
initCheckPage();
initRestoringPage();
initLastPage();
}
DataRestore::~DataRestore()
@ -54,7 +54,7 @@ DataRestore::~DataRestore()
/**
* @brief
*/
void DataRestore::initFirstWidget()
void DataRestore::initHomePage()
{
QWidget *homePage = new QWidget;
QVBoxLayout *vLayout = new QVBoxLayout;
@ -241,7 +241,7 @@ bool DataRestore::checkIsNeedReboot()
/**
* @brief --
*/
void DataRestore::initSecondWidget()
void DataRestore::initCheckPage()
{
QWidget *checkPage = new QWidget;
@ -611,7 +611,7 @@ void DataRestore::on_checkEnv_end(int result)
/**
* @brief -
*/
void DataRestore::initThirdWidget()
void DataRestore::initRestoringPage()
{
QWidget *restoringPage = new QWidget;
@ -847,7 +847,7 @@ void DataRestore::on_restore_end(bool result)
/**
* @brief
*/
void DataRestore::initLastWidget()
void DataRestore::initLastPage()
{
QWidget *last = new QWidget;

View File

@ -32,10 +32,10 @@ public:
virtual ~DataRestore();
private:
void initFirstWidget();
void initSecondWidget();
void initThirdWidget();
void initLastWidget();
void initHomePage();
void initCheckPage();
void initRestoringPage();
void initLastPage();
bool checkIsNeedReboot();

View File

@ -44,11 +44,11 @@ GhostImage::GhostImage(QWidget *parent) :
m_iPosition = BackupPosition::LOCAL;
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initForthWidget();
initLastWidget();
initHomePage();
initSetSavePathPage();
initCheckPage();
initGhostingPage();
initLastPage();
}
GhostImage::~GhostImage()
@ -63,7 +63,7 @@ GhostImage::~GhostImage()
/**
* @brief
*/
void GhostImage::initFirstWidget()
void GhostImage::initHomePage()
{
QWidget *homePage = new QWidget;
QVBoxLayout *vLayout = new QVBoxLayout;
@ -215,9 +215,9 @@ void GhostImage::on_next_clicked(bool checked)
}
/**
* @brief
* @brief
*/
void GhostImage::initSecondWidget()
void GhostImage::initSetSavePathPage()
{
QWidget *savePathPage = new QWidget;
// 纵向布局
@ -311,9 +311,9 @@ void GhostImage::initSecondWidget()
}
/**
* @brief
* @brief
*/
void GhostImage::initThirdWidget()
void GhostImage::initCheckPage()
{
QWidget *checkPage = new QWidget;
@ -742,9 +742,9 @@ QString GhostImage::createGhostImageName(const QString& backupName)
}
/**
* @brief
* @brief
*/
void GhostImage::initForthWidget()
void GhostImage::initGhostingPage()
{
QWidget *ghostingPage = new QWidget;
@ -1064,7 +1064,7 @@ void GhostImage::on_ghost_end(bool result)
/**
* @brief
*/
void GhostImage::initLastWidget()
void GhostImage::initLastPage()
{
QWidget *last = new QWidget;

View File

@ -35,11 +35,11 @@ public:
virtual ~GhostImage();
private:
void initFirstWidget();
void initSecondWidget();
void initThirdWidget();
void initForthWidget();
void initLastWidget();
void initHomePage();
void initSetSavePathPage();
void initCheckPage();
void initGhostingPage();
void initLastPage();
QString createGhostImageName(const QString& backupName);
signals:

View File

@ -150,6 +150,7 @@ void ManageBackupPointList::insertLines(const QList<ParseBackupList::BackupPoint
} else {
prefixPath_to_device = QObject::tr("Local Disk:") + " " + BACKUP_SNAPSHOTS_PATH;
}
prefixPath_to_device.replace("//", "/");
setItem(indexOfRow, Column_Index::Backup_Device, prefixPath_to_device);
if (backupPoint.m_state == BACKUP_PARSE_STATE_SUCCESS_STRTING) {
setItem(indexOfRow, Column_Index::Backup_State, tr("backup finished"));

View File

@ -15,7 +15,7 @@ OperationLog::OperationLog(QWidget *parent) :
QStackedWidget(parent)
{
// 界面手写代码创建,作为练手
initFirstWidget();
initHomePage();
}
OperationLog::~OperationLog()
@ -24,7 +24,7 @@ OperationLog::~OperationLog()
/**
* @brief
*/
void OperationLog::initFirstWidget()
void OperationLog::initHomePage()
{
QWidget *homePage = new QWidget;

View File

@ -24,7 +24,7 @@ public:
virtual ~OperationLog();
private:
void initFirstWidget();
void initHomePage();
void initOperationLogs(const QList<BackupWrapper>& list);
void setItem(int row, int column, const QString& text, int alignFlag = Qt::AlignLeft | Qt::AlignVCenter);
QString castTypeToString(int type);

View File

@ -173,6 +173,7 @@ void SelectRestorePoint::insertLines(const QList<ParseBackupList::BackupPoint> &
} else {
prefixPath_to_device = QObject::tr("Local Disk:") + " " + BACKUP_SNAPSHOTS_PATH;
}
prefixPath_to_device.replace("//", "/");
setItem(indexOfRow, Column_Index::Backup_Device, prefixPath_to_device);
setItem(indexOfRow, Column_Index::Backup_State, backupPoint.m_state);
setItem(indexOfRow, Column_Index::Prefix_Path, backupPoint.m_path);

View File

@ -45,12 +45,12 @@ SystemBackup::SystemBackup(QWidget *parent /*= nullptr*/) :
m_pInterface(nullptr)
{
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initForthWidget();
initFifthWidget();
initLastWidget();
initHomePage();
initSetBackupPathsPage();
initCheckPage();
initNameBackupPage();
initBackupingPage();
initLastPage();
}
SystemBackup::~SystemBackup()
@ -65,7 +65,7 @@ SystemBackup::~SystemBackup()
/**
* @brief
*/
void SystemBackup::initFirstWidget()
void SystemBackup::initHomePage()
{
QWidget *homePage = new QWidget;
QVBoxLayout *vLayout = new QVBoxLayout;
@ -167,6 +167,7 @@ void SystemBackup::initFirstWidget()
backupPointManage->setProperty("useButtonPalette", true);
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
bottomHBoxLayout->addWidget(backupPointManage);
@ -185,15 +186,19 @@ void SystemBackup::initFirstWidget()
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::styleNameChanged, this, [=](bool isDark) {
Q_UNUSED(isDark)
// 深浅主题切换时,因为调色板已经更换,高亮等颜色已经改变,所以要重新加载图标。
// from席博文因为按钮的文字颜色换了一个类型因为设计非要什么半透明透明效果的Text就是半透明的buttontext就是不半透明。所以将ButtonText改为Text
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
});
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::themeColorChanged, this, [=]() {
// 强调色更换,高亮等颜色已经改变,所以要重新加载图标。
// from席博文因为按钮的文字颜色换了一个类型因为设计非要什么半透明透明效果的Text就是半透明的buttontext就是不半透明。所以将ButtonText改为Text
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
pal.setColor(QPalette::Text, this->palette().highlight().color());
pal.setColor(QPalette::Button, this->palette().base().color());
backupPointManage->setPalette(pal);
});
@ -228,9 +233,9 @@ void SystemBackup::on_next_clicked(bool checked)
}
/**
* @brief
* @brief
*/
void SystemBackup::initSecondWidget()
void SystemBackup::initSetBackupPathsPage()
{
QWidget *selectPathPage = new QWidget;
// 纵向布局
@ -354,25 +359,7 @@ void SystemBackup::initSecondWidget()
if (!selectFiles.isEmpty()) {
QString fileName = selectFiles.at(0);
// sdk重新实现了QFileDialog后很多功能已经丢失需要再次进行过滤真难用
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
backupPath.replace("//", "/");
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return ;
} else if (fileName.endsWith(BACKUP_PATH)) {
QString subfile = fileName + "/snapshots";
if (Utils::isDirExist(subfile)) {
// 不能嵌套备份,请选择其它目录
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
QObject::tr("Cannot nest backups, please select another directory."),
QObject::tr("OK"));
return ;
}
} else if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
// 选择了移动设备挂载目录的子孙目录
// 移动设备只能选择挂载目录本身
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
@ -423,9 +410,9 @@ void SystemBackup::initSecondWidget()
}
/**
* @brief
* @brief
*/
void SystemBackup::initThirdWidget()
void SystemBackup::initCheckPage()
{
QWidget *checkPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -748,8 +735,12 @@ void SystemBackup::on_checkEnv_start()
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE){
QString prefixPath = m_prefixDestPath;
prefixPath += BACKUP_SNAPSHOTS_PATH;
prefixPath.replace("//", "/");
backupWrapper.m_backupExcludePaths << prefixPath;
}
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
@ -822,10 +813,10 @@ void SystemBackup::on_checkEnv_end(int result)
}
/**
* @brief
* @brief
*/
#define MAX_LEN_BACKUPNAME 64
void SystemBackup::initForthWidget()
void SystemBackup::initNameBackupPage()
{
QWidget *nameBackupPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -1098,9 +1089,9 @@ bool SystemBackup::isExistsBackupName(const QString & backupName)
}
/**
* @brief
* @brief
*/
void SystemBackup::initFifthWidget()
void SystemBackup::initBackupingPage()
{
QWidget *backupingPage = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;
@ -1293,8 +1284,12 @@ void SystemBackup::on_backup_start()
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE){
QString prefixPath = m_prefixDestPath;
prefixPath += BACKUP_SNAPSHOTS_PATH;
prefixPath.replace("//", "/");
backupWrapper.m_backupExcludePaths << prefixPath;
}
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
@ -1433,7 +1428,7 @@ void SystemBackup::on_backup_end(bool result)
/**
* @brief
*/
void SystemBackup::initLastWidget()
void SystemBackup::initLastPage()
{
QWidget *last = new QWidget;
QVBoxLayout *vlayout = new QVBoxLayout;

View File

@ -35,12 +35,12 @@ public:
~SystemBackup();
private:
void initFirstWidget();
void initSecondWidget();
void initThirdWidget();
void initForthWidget();
void initFifthWidget();
void initLastWidget();
void initHomePage();
void initSetBackupPathsPage();
void initCheckPage();
void initNameBackupPage();
void initBackupingPage();
void initLastPage();
QList<ParseBackupList::BackupPoint> getBackupPointList();
bool isExistsBackupName(const QString & backupName);

View File

@ -42,10 +42,10 @@ SystemRestore::SystemRestore(QWidget *parent) :
m_iPosition = BackupPosition::LOCAL;
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initLastWidget();
initHomePage();
initCheckPage();
initRestoringPage();
initLastPage();
}
SystemRestore::~SystemRestore()
@ -57,7 +57,7 @@ SystemRestore::~SystemRestore()
/**
* @brief
*/
void SystemRestore::initFirstWidget()
void SystemRestore::initHomePage()
{
QWidget *homePage = new QWidget;
QVBoxLayout *vLayout = new QVBoxLayout;
@ -259,7 +259,7 @@ void SystemRestore::on_button_beginRestore_clicked(bool checked)
/**
* @brief --
*/
void SystemRestore::initSecondWidget()
void SystemRestore::initCheckPage()
{
QWidget *checkPage = new QWidget;
@ -637,7 +637,7 @@ void SystemRestore::on_checkEnv_end(int result)
/**
* @brief -
*/
void SystemRestore::initThirdWidget()
void SystemRestore::initRestoringPage()
{
QWidget *restoringPage = new QWidget;
@ -874,7 +874,7 @@ void SystemRestore::on_restore_end(bool result)
/**
* @brief
*/
void SystemRestore::initLastWidget()
void SystemRestore::initLastPage()
{
QWidget *last = new QWidget;

View File

@ -32,10 +32,10 @@ public:
virtual ~SystemRestore();
private:
void initFirstWidget();
void initSecondWidget();
void initThirdWidget();
void initLastWidget();
void initHomePage();
void initCheckPage();
void initRestoringPage();
void initLastPage();
signals:
void startCheckEnv();

File diff suppressed because it is too large Load Diff

2107
kybackup/qt_mn_MN.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2107
kybackup/qt_zh_HK.ts Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1 @@
<クd<>箆!ソ`。スン

View File

@ -1,13 +1,16 @@
[Desktop Entry]
Name=Backup and Restore
Name=Backup & Restore
Name[zh_CN]=备份还原
Name[zh_HK]=備份還原
Name[bo_CN]=རྗེས་གྲབས་དང་སླར་གསོ་བྱེད་དགོས།
Name[mn]=ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ
Comment=Provides system and data backup and restore functions
Comment[zh_CN]=提供系统备份还原和数据备份还原等功能
Comment[bo_CN]=རྒྱུད་ཁོངས་གྲབས་ཉར་དང་གཞི་གྲངས་གྲབས་ཉར་སོར་ལོག་མཁོ་འདོན་སོགས་ཀྱི་ནུས་པ་
Comment[mn]= ᠰᠢᠰᠲ᠋ᠧᠮ ᠤ᠋ᠨ ᠨᠦᠬᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ᠂ ᠳ᠋ᠠᠢᠲ᠋ᠠ ᠵᠢᠨ ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ ᠵᠡᠷᠭᠡ ᠴᠢᠳᠠᠪᠬᠢ ᠬᠠᠩᠭᠠᠠ
Keywords=backup
TryExec=kybackup
Exec=/usr/bin/kybackup %U
Exec=kybackup %U
StartupNotify=true
Terminal=false
Type=Application