Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #include "zipreader.h"
23 :
24 : #include "global/io/file.h"
25 : #include "global/io/dir.h"
26 : #include "internal/zipcontainer.h"
27 :
28 : using namespace muse;
29 : using namespace muse::io;
30 :
31 : struct ZipReader::Impl
32 : {
33 : ZipContainer* zip = nullptr;
34 : IODevice* device = nullptr;
35 : bool isSelfDevice = false;
36 : };
37 :
38 208 : bool ZipReader::startsWithEntry(const ByteArray& data, std::span<const uint8_t> name)
39 : {
40 208 : return ZipContainer::startsWithEntry(data.constData(), data.size(), name);
41 : }
42 :
43 23 : ZipReader::ZipReader(const io::path_t& filePath)
44 23 : : m_filePath(filePath)
45 : {
46 23 : m_impl = new Impl();
47 23 : m_impl->device = new File(filePath);
48 23 : m_impl->isSelfDevice = true;
49 23 : if (m_impl->device->open(IODevice::ReadOnly)) {
50 : }
51 23 : m_impl->zip = new ZipContainer(m_impl->device);
52 23 : }
53 :
54 166 : ZipReader::ZipReader(IODevice* device)
55 : {
56 166 : m_impl = new Impl();
57 166 : m_impl->device = device;
58 166 : m_impl->zip = new ZipContainer(m_impl->device);
59 166 : }
60 :
61 189 : ZipReader::~ZipReader()
62 : {
63 189 : close();
64 189 : delete m_impl->zip;
65 189 : if (m_impl->isSelfDevice) {
66 23 : delete m_impl->device;
67 : }
68 189 : delete m_impl;
69 189 : }
70 :
71 18 : bool ZipReader::exists() const
72 : {
73 18 : if (!m_filePath.empty()) {
74 18 : return File::exists(m_filePath);
75 : }
76 :
77 0 : return true;
78 : }
79 :
80 352 : void ZipReader::close()
81 : {
82 352 : m_impl->zip->close();
83 352 : }
84 :
85 103 : bool ZipReader::hasError() const
86 : {
87 103 : return m_impl->zip->status() != ZipContainer::NoError;
88 : }
89 :
90 30 : std::vector<ZipReader::FileInfo> ZipReader::fileInfoList() const
91 : {
92 30 : std::vector<FileInfo> ret;
93 30 : std::vector<ZipContainer::FileInfo> fis = m_impl->zip->fileInfoList();
94 30 : ret.reserve(fis.size());
95 293 : for (const ZipContainer::FileInfo& qfi : fis) {
96 263 : FileInfo fi;
97 263 : fi.filePath = qfi.filePath;
98 263 : fi.isDir = qfi.isDir;
99 263 : fi.isFile = qfi.isFile;
100 263 : fi.isSymLink = qfi.isSymLink;
101 263 : fi.size = qfi.size;
102 :
103 263 : ret.push_back(std::move(fi));
104 263 : }
105 :
106 30 : return ret;
107 30 : }
108 :
109 39 : bool ZipReader::fileExists(const std::string& fileName) const
110 : {
111 39 : return m_impl->zip->fileExists(fileName);
112 : }
113 :
114 518 : ByteArray ZipReader::fileData(const std::string& fileName) const
115 : {
116 518 : return m_impl->zip->fileData(fileName);
117 : }
118 :
119 : // ===========================
120 : // ZipUnpack
121 : // ===========================
122 :
123 0 : Ret ZipUnpack::unpack(const io::path_t& zipPath, const io::path_t& dirPath)
124 : {
125 0 : Ret ret = io::Dir::mkpath(dirPath);
126 0 : if (!ret) {
127 0 : return ret;
128 : }
129 :
130 0 : ZipReader zip(zipPath);
131 0 : for (const ZipReader::FileInfo& fi : zip.fileInfoList()) {
132 0 : const io::path_t filePath = dirPath + "/" + fi.filePath;
133 :
134 0 : if (fi.isDir) {
135 0 : ret = io::Dir::mkpath(filePath);
136 0 : } else if (fi.isFile) {
137 0 : ret = io::Dir::mkpath(io::dirpath(filePath));
138 :
139 0 : if (ret) {
140 0 : const ByteArray data = zip.fileData(fi.filePath.toStdString());
141 0 : ret = io::File::writeFile(filePath, data);
142 0 : }
143 : }
144 :
145 0 : if (!ret) {
146 0 : break;
147 : }
148 0 : }
149 :
150 0 : return ret;
151 0 : }
|