File indexing completed on 2024-05-05 05:50:40
0001 /* 0002 SPDX-FileCopyrightText: 2016 Ragnar Thomsen <rthomsen6@gmail.com> 0003 0004 SPDX-License-Identifier: BSD-2-Clause 0005 */ 0006 0007 #include "cliproperties.h" 0008 #include "archiveformat.h" 0009 #include "ark_debug.h" 0010 #include "pluginmanager.h" 0011 #include <QRegularExpression> 0012 namespace Kerfuffle 0013 { 0014 CliProperties::CliProperties(QObject *parent, const KPluginMetaData &metaData, const QMimeType &archiveType) 0015 : QObject(parent) 0016 , m_mimeType(archiveType) 0017 , m_metaData(metaData) 0018 { 0019 } 0020 0021 QStringList CliProperties::addArgs(const QString &archive, 0022 const QStringList &files, 0023 const QString &password, 0024 bool headerEncryption, 0025 int compressionLevel, 0026 const QString &compressionMethod, 0027 const QString &encryptionMethod, 0028 ulong volumeSize) 0029 { 0030 if (!encryptionMethod.isEmpty()) { 0031 Q_ASSERT(!password.isEmpty()); 0032 } 0033 0034 QStringList args; 0035 for (const QString &s : std::as_const(m_addSwitch)) { 0036 args << s; 0037 } 0038 if (!password.isEmpty()) { 0039 args << substitutePasswordSwitch(password, headerEncryption); 0040 } 0041 if (compressionLevel > -1) { 0042 args << substituteCompressionLevelSwitch(compressionLevel); 0043 } 0044 if (!compressionMethod.isEmpty()) { 0045 args << substituteCompressionMethodSwitch(compressionMethod); 0046 } 0047 if (!encryptionMethod.isEmpty()) { 0048 args << substituteEncryptionMethodSwitch(encryptionMethod); 0049 } 0050 if (volumeSize > 0) { 0051 args << substituteMultiVolumeSwitch(volumeSize); 0052 } 0053 args << archive; 0054 args << files; 0055 0056 args.removeAll(QString()); 0057 return args; 0058 } 0059 0060 QStringList CliProperties::commentArgs(const QString &archive, const QString &commentfile) 0061 { 0062 QStringList args; 0063 const QStringList commentSwitches = substituteCommentSwitch(commentfile); 0064 for (const QString &s : commentSwitches) { 0065 args << s; 0066 } 0067 args << archive; 0068 0069 args.removeAll(QString()); 0070 return args; 0071 } 0072 0073 QStringList CliProperties::deleteArgs(const QString &archive, const QVector<Archive::Entry *> &files, const QString &password) 0074 { 0075 QStringList args; 0076 args << m_deleteSwitch; 0077 if (!password.isEmpty()) { 0078 args << substitutePasswordSwitch(password); 0079 } 0080 args << archive; 0081 for (const Archive::Entry *e : files) { 0082 args << e->fullPath(NoTrailingSlash); 0083 } 0084 0085 args.removeAll(QString()); 0086 return args; 0087 } 0088 0089 QStringList CliProperties::extractArgs(const QString &archive, const QStringList &files, bool preservePaths, const QString &password) 0090 { 0091 QStringList args; 0092 0093 if (preservePaths && !m_extractSwitch.isEmpty()) { 0094 args << m_extractSwitch; 0095 } else if (!preservePaths && !m_extractSwitchNoPreserve.isEmpty()) { 0096 args << m_extractSwitchNoPreserve; 0097 } 0098 0099 if (!password.isEmpty()) { 0100 args << substitutePasswordSwitch(password); 0101 } 0102 args << archive; 0103 args << files; 0104 0105 args.removeAll(QString()); 0106 return args; 0107 } 0108 0109 QStringList CliProperties::listArgs(const QString &archive, const QString &password) 0110 { 0111 QStringList args; 0112 for (const QString &s : std::as_const(m_listSwitch)) { 0113 args << s; 0114 } 0115 0116 const auto encryptionType = ArchiveFormat::fromMetadata(m_mimeType, m_metaData).encryptionType(); 0117 if (!password.isEmpty() && encryptionType == Archive::EncryptionType::HeaderEncrypted) { 0118 args << substitutePasswordSwitch(password); 0119 } 0120 args << archive; 0121 0122 args.removeAll(QString()); 0123 return args; 0124 } 0125 0126 QStringList CliProperties::moveArgs(const QString &archive, const QVector<Archive::Entry *> &entries, Archive::Entry *destination, const QString &password) 0127 { 0128 QStringList args; 0129 args << m_moveSwitch; 0130 if (!password.isEmpty()) { 0131 args << substitutePasswordSwitch(password); 0132 } 0133 args << archive; 0134 if (entries.count() > 1) { 0135 for (const Archive::Entry *file : entries) { 0136 args << file->fullPath(NoTrailingSlash); 0137 if (destination) { 0138 args << destination->fullPath() + file->name(); 0139 } 0140 } 0141 } else { 0142 args << entries.at(0)->fullPath(NoTrailingSlash); 0143 if (destination) { 0144 args << destination->fullPath(NoTrailingSlash); 0145 } 0146 } 0147 0148 args.removeAll(QString()); 0149 return args; 0150 } 0151 0152 QStringList CliProperties::testArgs(const QString &archive, const QString &password) 0153 { 0154 QStringList args; 0155 for (const QString &s : std::as_const(m_testSwitch)) { 0156 args << s; 0157 } 0158 if (!password.isEmpty()) { 0159 args << substitutePasswordSwitch(password); 0160 } 0161 args << archive; 0162 0163 args.removeAll(QString()); 0164 return args; 0165 } 0166 0167 QStringList CliProperties::substituteCommentSwitch(const QString &commentfile) const 0168 { 0169 Q_ASSERT(!commentfile.isEmpty()); 0170 0171 Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).supportsWriteComment()); 0172 0173 QStringList commentSwitches = m_commentSwitch; 0174 Q_ASSERT(!commentSwitches.isEmpty()); 0175 0176 QMutableListIterator<QString> i(commentSwitches); 0177 while (i.hasNext()) { 0178 i.next(); 0179 i.value().replace(QLatin1String("$CommentFile"), commentfile); 0180 } 0181 0182 return commentSwitches; 0183 } 0184 0185 QStringList CliProperties::substitutePasswordSwitch(const QString &password, bool headerEnc) const 0186 { 0187 if (password.isEmpty()) { 0188 return QStringList(); 0189 } 0190 0191 Archive::EncryptionType encryptionType = ArchiveFormat::fromMetadata(m_mimeType, m_metaData).encryptionType(); 0192 Q_ASSERT(encryptionType != Archive::EncryptionType::Unencrypted); 0193 0194 QStringList passwordSwitch; 0195 if (headerEnc) { 0196 passwordSwitch = m_passwordSwitchHeaderEnc; 0197 } else { 0198 passwordSwitch = m_passwordSwitch; 0199 } 0200 Q_ASSERT(!passwordSwitch.isEmpty()); 0201 0202 QMutableListIterator<QString> i(passwordSwitch); 0203 while (i.hasNext()) { 0204 i.next(); 0205 i.value().replace(QLatin1String("$Password"), password); 0206 } 0207 0208 return passwordSwitch; 0209 } 0210 0211 QString CliProperties::substituteCompressionLevelSwitch(int level) const 0212 { 0213 if (level < 0 || level > 9) { 0214 return QString(); 0215 } 0216 0217 Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).maxCompressionLevel() != -1); 0218 0219 QString compLevelSwitch = m_compressionLevelSwitch; 0220 Q_ASSERT(!compLevelSwitch.isEmpty()); 0221 0222 compLevelSwitch.replace(QLatin1String("$CompressionLevel"), QString::number(level)); 0223 0224 return compLevelSwitch; 0225 } 0226 0227 QString CliProperties::substituteCompressionMethodSwitch(const QString &method) const 0228 { 0229 if (method.isEmpty()) { 0230 return QString(); 0231 } 0232 0233 Q_ASSERT(!ArchiveFormat::fromMetadata(m_mimeType, m_metaData).compressionMethods().isEmpty()); 0234 0235 QString compMethodSwitch = m_compressionMethodSwitch[m_mimeType.name()].toString(); 0236 Q_ASSERT(!compMethodSwitch.isEmpty()); 0237 0238 QString cliMethod = ArchiveFormat::fromMetadata(m_mimeType, m_metaData).compressionMethods().value(method).toString(); 0239 0240 compMethodSwitch.replace(QLatin1String("$CompressionMethod"), cliMethod); 0241 0242 return compMethodSwitch; 0243 } 0244 0245 QString CliProperties::substituteEncryptionMethodSwitch(const QString &method) const 0246 { 0247 if (method.isEmpty()) { 0248 return QString(); 0249 } 0250 0251 const ArchiveFormat format = ArchiveFormat::fromMetadata(m_mimeType, m_metaData); 0252 0253 Q_ASSERT(!format.encryptionMethods().isEmpty()); 0254 0255 QString encMethodSwitch = m_encryptionMethodSwitch[m_mimeType.name()].toString(); 0256 if (encMethodSwitch.isEmpty()) { 0257 return QString(); 0258 } 0259 0260 Q_ASSERT(format.encryptionMethods().contains(method)); 0261 0262 encMethodSwitch.replace(QLatin1String("$EncryptionMethod"), method); 0263 0264 return encMethodSwitch; 0265 } 0266 0267 QString CliProperties::substituteMultiVolumeSwitch(ulong volumeSize) const 0268 { 0269 // The maximum value we allow in the QDoubleSpinBox is 1,000,000MB. Converted to 0270 // KB this is 1,024,000,000. 0271 if (volumeSize <= 0 || volumeSize > 1024000000) { 0272 return QString(); 0273 } 0274 0275 Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).supportsMultiVolume()); 0276 0277 QString multiVolumeSwitch = m_multiVolumeSwitch; 0278 Q_ASSERT(!multiVolumeSwitch.isEmpty()); 0279 0280 multiVolumeSwitch.replace(QLatin1String("$VolumeSize"), QString::number(volumeSize)); 0281 0282 return multiVolumeSwitch; 0283 } 0284 0285 bool CliProperties::isTestPassedMsg(const QString &line) 0286 { 0287 for (const QString &rx : std::as_const(m_testPassedPatterns)) { 0288 if (QRegularExpression(rx).match(line).hasMatch()) { 0289 return true; 0290 } 0291 } 0292 return false; 0293 } 0294 0295 } 0296 0297 #include "moc_cliproperties.cpp"