aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard/ZipArchive/ZipImporter.swift
blob: 6c1e3de2eceeeac28d02e13377cb9197a085d4b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All Rights Reserved.

import UIKit

enum ZipImporterError: WireGuardAppError {
    case noTunnelsInZipArchive

    func alertText() -> (String, String)? {
        switch (self) {
        case .noTunnelsInZipArchive:
            return ("No tunnels in zip archive", "No .conf tunnel files were found inside the zip archive.")
        }
    }
}

class ZipImporter {
    static func importConfigFiles(from url: URL, completion: @escaping (WireGuardResult<[TunnelConfiguration?]>) -> Void) {
        DispatchQueue.global(qos: .userInitiated).async {
            var unarchivedFiles: [(fileBaseName: String, contents: Data)]
            do {
                unarchivedFiles = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"])
                for (i, unarchivedFile) in unarchivedFiles.enumerated().reversed() {
                    let fileBaseName = unarchivedFile.fileBaseName
                    let trimmedName = fileBaseName.trimmingCharacters(in: .whitespacesAndNewlines)
                    if (!trimmedName.isEmpty) {
                        unarchivedFiles[i].fileBaseName = trimmedName
                    } else {
                        unarchivedFiles.remove(at: i)
                    }
                }

                if (unarchivedFiles.isEmpty) {
                    throw ZipImporterError.noTunnelsInZipArchive
                }
            } catch (let error as WireGuardAppError) {
                DispatchQueue.main.async { completion(.failure(error)) }
                return
            } catch {
                fatalError()
            }

            unarchivedFiles.sort { $0.fileBaseName < $1.fileBaseName }
            var configs = Array<TunnelConfiguration?>(repeating: nil, count: unarchivedFiles.count)
            for (i, file) in unarchivedFiles.enumerated() {
                if (i > 0 && file == unarchivedFiles[i - 1]) {
                    continue
                }
                guard let fileContents = String(data: file.contents, encoding: .utf8) else {
                    continue
                }
                guard let tunnelConfig = try? WgQuickConfigFileParser.parse(fileContents, name: file.fileBaseName) else {
                    continue
                }
                configs[i] = tunnelConfig
            }
            DispatchQueue.main.async { completion(.success(configs)) }
        }
    }
}