core/src/iosMain/kotlin/licenseplist/LicensePlistParser.kt
author Da Risk <da_risk@geekorum.com>
Wed, 12 Mar 2025 20:17:28 -0400
changeset 25 a645b4ebb054
child 34 ce299aacc068
permissions -rw-r--r--
core: add ios LicensePlistParser
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     1
/*
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     2
 * AboutOss is an utility library to retrieve and display
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     3
 * opensource licenses in Android applications.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     4
 *
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     5
 * Copyright (C) 2023 by Frederic-Charles Barthelery.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     6
 *
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     7
 * This file is part of AboutOss.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     8
 *
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
     9
 * AboutOss is free software: you can redistribute it and/or modify
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    10
 * it under the terms of the GNU General Public License as published by
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    11
 * the Free Software Foundation, either version 3 of the License, or
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    12
 * (at your option) any later version.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    13
 *
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    14
 * AboutOss is distributed in the hope that it will be useful,
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    17
 * GNU General Public License for more details.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    18
 *
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    19
 * You should have received a copy of the GNU General Public License
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    20
 * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    21
 */
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    22
package com.geekorum.aboutoss.core.licenseplist
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    23
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    24
import kotlinx.cinterop.BetaInteropApi
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    25
import kotlinx.cinterop.ExperimentalForeignApi
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    26
import kotlinx.cinterop.ObjCObjectVar
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    27
import kotlinx.cinterop.alloc
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    28
import kotlinx.cinterop.memScoped
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    29
import kotlinx.cinterop.ptr
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    30
import kotlinx.cinterop.value
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    31
import platform.Foundation.NSBundle
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    32
import platform.Foundation.NSData
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    33
import platform.Foundation.NSError
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    34
import platform.Foundation.NSPropertyListMutableContainers
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    35
import platform.Foundation.NSPropertyListSerialization
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    36
import platform.Foundation.NSURL
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    37
import platform.Foundation.dataWithContentsOfURL
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    38
import kotlin.coroutines.resume
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    39
import kotlin.coroutines.resumeWithException
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    40
import kotlin.coroutines.suspendCoroutine
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    41
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    42
class LicensePlistParser {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    43
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    44
    @Suppress("UNCHECKED_CAST")
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    45
    suspend fun parseLicenses(
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    46
        licensePlistInput: NSURL
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    47
    ): Map<String, String> {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    48
        val fileContent = getContent(licensePlistInput)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    49
        val plist = fileContent.toPropertyList() as Map<String, List<Map<String, String>>>
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    50
        val paneLists = plist["PreferenceSpecifiers"]!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    51
            .filter {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    52
                it["Type"] == "PSChildPaneSpecifier"
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    53
            }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    54
        val directoryUrl = licensePlistInput.URLByDeletingLastPathComponent()!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    55
        return paneLists.associate { pane ->
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    56
            val paneFile = pane["File"]!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    57
            val libraryName = pane["Title"]!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    58
            val paneUrl = buildPaneUrl(directoryUrl, paneFile)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    59
            val paneFileContent =  getContent(paneUrl)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    60
            val paneFilePlist = paneFileContent.toPropertyList() as Map<String, List<Map<String, String>>>
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    61
            val license = getLicenseFromPaneFilePlist(paneFilePlist)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    62
            libraryName to license
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    63
        }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    64
    }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    65
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    66
    private fun buildPaneUrl(directoryUrl: NSURL, paneName: String) = directoryUrl.URLByAppendingPathComponent(paneName)!!.URLByAppendingPathExtension("plist")!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    67
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    68
    private fun getLicenseFromPaneFilePlist(paneFilePList: Map<String, List<Map<String, String>>>): String {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    69
        val specifiers = paneFilePList["PreferenceSpecifiers"]!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    70
        val licenses = specifiers.map {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    71
            it["FooterText"]!!
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    72
        }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    73
        return licenses.joinToString("\n\n")
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    74
    }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    75
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    76
    private fun getContent(url: NSURL): NSData {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    77
        return checkNotNull(NSData.dataWithContentsOfURL(url))
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    78
    }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    79
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    80
    @OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    81
    private suspend fun NSData.toPropertyList(): Any? = suspendCoroutine { cont ->
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    82
        val parsed = memScoped {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    83
            val error: ObjCObjectVar<NSError?> = alloc()
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    84
            val result = NSPropertyListSerialization.propertyListWithData(this@toPropertyList,
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    85
                options = NSPropertyListMutableContainers,
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    86
                format = null,
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    87
                error.ptr
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    88
            )
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    89
            if (error.value != null) {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    90
                cont.resumeWithException(Exception(error.value!!.description))
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    91
            }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    92
            result
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    93
        }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    94
        cont.resume(parsed!!)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    95
    }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    96
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    97
    companion object {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    98
        fun getDefaultLicensePlistUrl(): NSURL {
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
    99
            val path = NSBundle.mainBundle.pathForResource(
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   100
                "com.mono0926.LicensePlist",
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   101
                ofType = "plist",
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   102
                inDirectory = "licenseplist"
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   103
            )
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   104
            return NSURL.fileURLWithPath(path!!)
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   105
        }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   106
    }
a645b4ebb054 core: add ios LicensePlistParser
Da Risk <da_risk@geekorum.com>
parents:
diff changeset
   107
}