Существует ли препроцессор Swift для обнаружения включенных мостовых заголовков? - PullRequest
0 голосов
/ 11 апреля 2019

Единственный ответ, который я нашел, был в этом , и я не удовлетворен им.

Я добавляю стандартный конвертер MD5 в качестве расширения строки:

/* ###################################################################################################################################### */
/**
 From here: https://stackoverflow.com/q/24123518/879365
 I am not making this public, because it requires the common crypto in the bridging header.
 */
fileprivate extension String {
    /* ################################################################## */
    /**
     - returns: the String, as an MD5 hash.
     */
    var md5: String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)

        let hash = NSMutableString()

        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }

        result.deallocate()
        return hash as String
    }
}

Требуется добавить в заголовок моста следующее:

#import <CommonCrypto/CommonCrypto.h>

Поскольку я хотел бы добавить это к набору инструментов многократного использования, я хотел бы посмотреть, есть ли способ во время компиляции определить, использовалась ли общая криптографическая библиотека.

Есть ли способ для меня, чтобы установить это как условную компиляцию?

Это не имеет большого значения, если нет; просто означает, что мне нужно настроить это как отдельный исходный файл.

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

Возможно, стоит отметить, что вы можете позвонить CC_MD5 без соединительного заголовка, если для доступа к нему используете dlsym.

import Foundation

typealias CC_MD5_Type = @convention(c) (UnsafeRawPointer, UInt32, UnsafeMutableRawPointer) -> UnsafeMutableRawPointer

let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
let CC_MD5 = unsafeBitCast(dlsym(RTLD_DEFAULT, "CC_MD5")!, to: CC_MD5_Type.self)

var md5 = Data(count: 16)
md5.withUnsafeMutableBytes {
    _ = CC_MD5("abc", 3, $0)
}

assert(md5 == Data(bytes: [0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72]))
0 голосов
/ 12 апреля 2019

Вот решение, которое я ударил. Это была смесь моего первоначального варианта и отличный ответ Роба. Это работает шарм (я использую его для построения ответов на RFC2617 Дайджест аутентификации ). Из-за использования встроенных хуков мне больше не нужен мостовой заголовок, и я могу добавить его в мой набор расширений String.

довольно классический случай правильного ответа, пришедшего из совершенно другого места, откуда я искал. Мне нравится, когда это происходит.

Вот, пожалуйста,

public extension String {
    /* ################################################################## */
    /**
     From here: https://stackoverflow.com/q/24123518/879365, but modified from here: https://stackoverflow.com/a/55639723/879365
     - returns: an MD5 hash of the String
     */
    var md5: String {
        var hash = ""

        // Start by getting a C-style string of our string as UTF-8.
        if let str = self.cString(using: .utf8) {
            // This is a cast for the MD5 function. The convention attribute just says that it's a "raw" C function.
            typealias CC_MD5_Type = @convention(c) (UnsafeRawPointer, UInt32, UnsafeMutableRawPointer) -> UnsafeMutableRawPointer

            // This is a flag, telling the name lookup to happen in the global scope. No dlopen required.
            let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)

            // This loads a function pointer with the CommonCrypto MD5 function.
            let CC_MD5 = unsafeBitCast(dlsym(RTLD_DEFAULT, "CC_MD5")!, to: CC_MD5_Type.self)

            // This is the length of the hash
            let CC_MD5_DIGEST_LENGTH = 16

            // This is where our MD5 hash goes. It's a simple 16-byte buffer.
            let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: CC_MD5_DIGEST_LENGTH)

            // Execute the MD5 hash. Save the result in our buffer.
            _ = CC_MD5(str, CUnsignedInt(str.count), result)

            // Turn it into a normal Swift String of hex digits.
            for i in 0..<CC_MD5_DIGEST_LENGTH {
                hash.append(String(format: "%02x", result[i]))
            }

            // Don't need this anymore.
            result.deallocate()
        }

        return hash
    }
}
...