MCPcopy Create free account
hub / github.com/FreesmTeam/FreesmLauncher / extractSubDir

Function extractSubDir

launcher/MMCZip.cpp:271–363  ·  view source on GitHub ↗

ours

Source from the content-addressed store, hash-verified

269
270// ours
271std::optional<QStringList> extractSubDir(QuaZip* zip, const QString& subdir, const QString& target)
272{
273 auto target_top_dir = QUrl::fromLocalFile(target);
274
275 QStringList extracted;
276
277 qDebug() << "Extracting subdir" << subdir << "from" << zip->getZipName() << "to" << target;
278 auto numEntries = zip->getEntriesCount();
279 if (numEntries < 0) {
280 qWarning() << "Failed to enumerate files in archive";
281 return std::nullopt;
282 } else if (numEntries == 0) {
283 qDebug() << "Extracting empty archives seems odd...";
284 return extracted;
285 } else if (!zip->goToFirstFile()) {
286 qWarning() << "Failed to seek to first file in zip";
287 return std::nullopt;
288 }
289
290 do {
291 QString file_name = zip->getCurrentFileName();
292 file_name = FS::RemoveInvalidPathChars(file_name);
293 if (!file_name.startsWith(subdir))
294 continue;
295
296 auto relative_file_name = QDir::fromNativeSeparators(file_name.mid(subdir.size()));
297 auto original_name = relative_file_name;
298
299 // Fix subdirs/files ending with a / getting transformed into absolute paths
300 if (relative_file_name.startsWith('/'))
301 relative_file_name = relative_file_name.mid(1);
302
303 // Fix weird "folders with a single file get squashed" thing
304 QString sub_path;
305 if (relative_file_name.contains('/') && !relative_file_name.endsWith('/')) {
306 sub_path = relative_file_name.section('/', 0, -2) + '/';
307 FS::ensureFolderPathExists(FS::PathCombine(target, sub_path));
308
309 relative_file_name = relative_file_name.split('/').last();
310 }
311
312 QString target_file_path;
313 if (relative_file_name.isEmpty()) {
314 target_file_path = target + '/';
315 } else {
316 target_file_path = FS::PathCombine(target_top_dir.toLocalFile(), sub_path, relative_file_name);
317 if (relative_file_name.endsWith('/') && !target_file_path.endsWith('/'))
318 target_file_path += '/';
319 }
320
321 if (!target_top_dir.isParentOf(QUrl::fromLocalFile(target_file_path))) {
322 qWarning() << "Extracting" << relative_file_name << "was cancelled, because it was effectively outside of the target path"
323 << target;
324 return std::nullopt;
325 }
326
327 if (!JlCompress::extractFile(zip, "", target_file_path)) {
328 qWarning() << "Failed to extract file" << original_name << "to" << target_file_path;

Callers 2

extractDirFunction · 0.85
installMethod · 0.85

Calls 9

RemoveInvalidPathCharsFunction · 0.85
ensureFolderPathExistsFunction · 0.85
PathCombineFunction · 0.85
extractFileFunction · 0.85
QFileInfoClass · 0.85
appendMethod · 0.80
sizeMethod · 0.45
containsMethod · 0.45
isEmptyMethod · 0.45

Tested by

no test coverage detected