Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/ThreemaFramework/Core/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 7 kB image not shown  

Quelle  Old_BlobUploader.swift   Sprache: JAVA

 

import CocoaLumberjackSwift
import Foundation
import PromiseKit
import ThreemaEssentials

final class Old_BlobUploader: NSObject {
    
    private let blobURL: BlobURL
    private let delegate: Old_BlobUploadDelegate
    
    final class BlobUploadItem {
        let description: String
        var totalBytesSent: Int64 = 0
        var totalBytesExpectedToSend: Int64 = 0
        var isCanceled = false
        var blobID: Data?

        init(_ taskDescription: String) {
            self.description = taskDescription
        }
    }
    
    private var blobUploadItems: [BlobUploadItem]
    
    private var blobItemIndex = 0
    
    @objc init(blobURL: BlobURL, delegate: Old_BlobUploadDelegate) {
        self.blobURL = blobURL
        self.delegate = delegate
        
        self.blobUploadItems = [BlobUploadItem]()
    }
    
    @objc func upload(blobs: [Data], origin: BlobOrigin, setPersistParam: Bool) {
        guard !blobs.isEmpty else {
            return
        }
        
        // Start all upload tasks
        for blob in blobs {
            blobUploadItems.append(startUpload(blob, setPersistParam: setPersistParam, origin: origin))
        }
    }

    /// Cancel all upload tasks.
    @objc func cancel() {
        HTTPClient.invalidateAndCancelSession(for: self)
    }
    
    private func startUpload(_ blob: Data, setPersistParam: Bool, origin: BlobOrigin) -> BlobUploadItem {
        let boundary = "---------------------------Boundary_Line"
        let contentType = String(format: "multipart/form-data; boundary=%@", boundary)

        var data = Data()
        data.append(contentsOf: String(format: "--%@\r\n", boundary).utf8)
        data.append(contentsOf: "Content-Disposition: form-data; name=\"blob\"; filename=\"blob.bin\"\r\n".utf8)
        data.append(contentsOf: "Content-Type: application/octet-stream\r\n\r\n".utf8)
        data.append(blob)
        data.append(contentsOf: String(format: "\r\n--%@--\r\n", boundary).utf8)
        
        blobItemIndex += 1
        let blobUploadItem = BlobUploadItem(String(blobItemIndex))
        
        blobURL.upload(origin: origin, setPersistParam: setPersistParam) { uploadURL, authorization, error in
            if uploadURL == nil {
                DDLogError("\(String(format: "Upload failed with error: %@", error!.localizedDescription))")
                self.delegate.uploadFailed()
                return
            }
            
            let client = HTTPClient(authorization: authorization)
            client.uploadDataMultipart(
                taskDescription: blobUploadItem.description,
                url: uploadURL!,
                contentType: contentType,
                data: data,
                delegate: self
            ) { task, data, response, error in
                if let error {
                    DDLogError("\(String(format: "Upload failed with error: %@", error.localizedDescription))")
                    self.delegate.uploadFailed()
                    return
                }
                guard let httpResponse = response as? HTTPURLResponse,
                      (200...299).contains(httpResponse.statusCode) else {
                    
                    var logMessage = "Upload not succeeded"
                    if let response = response as? HTTPURLResponse {
                        logMessage += " \(response.statusCode)"
                    }
                    DDLogWarn("\(logMessage).")
                    
                    if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 401 {
                        AuthTokenManager.shared().clearCache()
                    }
                    
                    self.delegate.uploadFailed()
                    return
                }
                            
                if let item = self.blobUploadItems.first(where: { $0.description == task?.taskDescription }),
                   let receivedData = data {
                    
                    if let blobIDHex = String(bytes: receivedData, encoding: .ascii),
                       let blobID = BytesUtility.toBytes(hexString: blobIDHex),
                       blobID.count == ThreemaProtocol.blobIDLength {
                        
                        item.blobID = Data(blobID)
                        
                        if self.blobUploadItems.filter({ $0.blobID == nil }).isEmpty {
                            self.delegate.uploadSucceeded(with: self.blobUploadItems.map { $0.blobID! })
                        }
                    }
                    else {
                        DDLogError("Could not evaluate received blob ID.")
                        self.delegate.uploadFailed()
                    }
                }
                else {
                    DDLogError("No data received for this upload task.")
                    self.delegate.uploadFailed()
                }
            }
        }
                
        return blobUploadItem
    }

    /// Progress of all upload tasks.
    /// - Returns: Progress, represented by a floating-point value between 0.0 and 1.0
    var progressPrecent: Double {
        guard !blobUploadItems.isEmpty else {
            return 0
        }
            
        var sumTotalBytesSent: Double = 0
        var sumTotalBytesExpectedToSend: Double = 0
            
        for item in blobUploadItems {
            sumTotalBytesSent += Double(item.totalBytesSent)
            sumTotalBytesExpectedToSend += Double(item.totalBytesExpectedToSend)
        }
            
        return sumTotalBytesSent / sumTotalBytesExpectedToSend
    }
}

// MARK: - URLSessionTaskDelegate

extension Old_BlobUploader: URLSessionTaskDelegate {

    func urlSession(
        _ session: URLSession,
        task: URLSessionTask,
        didSendBodyData bytesSent: Int64,
        totalBytesSent: Int64,
        totalBytesExpectedToSend: Int64
    ) {
        if let item = blobUploadItems.first(where: { $0.description == task.taskDescription }) {
            if !delegate.uploadShouldCancel() {
                item.totalBytesSent = totalBytesSent
                item.totalBytesExpectedToSend = totalBytesExpectedToSend
                
                delegate.uploadProgress(NSNumber(value: progressPrecent))
            }
            else {
                task.cancel()
                
                item.isCanceled = true
                if blobUploadItems.filter({ !$0.isCanceled }).isEmpty {
                    delegate.uploadDidCancel()
                }
            }
        }
        else {
            DDLogWarn("No internal data found for this upload task.")
        }
    }
    
    func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
        if let error {
            DDLogError("\(String(format: "Upload session invalid with error: %@", error.localizedDescription))")
        }

        if !delegate.uploadShouldCancel() {
            delegate.uploadFailed()
        }
        else {
            session.getAllTasks { tasks in
                for task in tasks {
                    if let item = self.blobUploadItems.first(where: { $0.description == task.taskDescription }) {
                        item.isCanceled = true
                    }
                }
                self.delegate.uploadDidCancel()
            }
        }
    }
    
    func urlSession(
        _ session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
    ) {
        Task {
            do {
                let result = try await SSLCAHelper().handle(challenge: challenge)
                completionHandler(result.disposition, result.credential)
            }
            catch {
                DDLogError("SSL cert pinning, handle authentication challenge failed \(error)")
            }
        }
    }
}

Messung
CHZG
869310092

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.