/* * AboutOss is an utility library to retrieve and display * opensource licenses in Android applications. * * Copyright (C) 2023-2025 by Frederic-Charles Barthelery. * * This file is part of AboutOss. * * AboutOss is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * AboutOss is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with AboutOss. If not, see . */ package com.geekorum.aboutoss.core.gms import okio.ByteString import okio.Source import okio.buffer import okio.use /** * Parse licences data generated by the "com.google.android.gms.oss-licenses-plugin" gradle plugin. */ class OssLicenseParser( thirdPartyLicensesSource: Source, thirdPartyLicensesMetadataSource: Source ): AutoCloseable { private val thirdPartyLicensesInput = thirdPartyLicensesSource.buffer() private val thirdPartyLicensesMetadataInput = thirdPartyLicensesMetadataSource.buffer() /** * Parse licenses * @param [thirdPartyLicensesInput] is usually res/raw/third_party_licenses file * @param [thirdPartyLicensesMetadataInput] is usually res/raw/third_party_license_metadata file */ fun parseLicenses(): Map { val licenses = readLicensesFile(thirdPartyLicensesInput) return buildLicenseInfo(licenses, thirdPartyLicensesMetadataInput) } private fun readLicensesFile(thirdPartyLicensesInput: Source): ByteString { return thirdPartyLicensesInput.buffer().use { it.readByteString() } } private fun buildLicenseInfo(license: ByteString, thirdPartyLicensesMetadataInput: Source): Map { return thirdPartyLicensesMetadataInput.buffer().use { buildMap { while (true) { val line = it.readUtf8Line() ?: break if (line.isNotBlank()) { with(line.toLineParser()) { val start = readStartIdx() val length = readLength() val dependency = readName() val licenseTxt = license.substring( beginIndex = start, endIndex = start + length + 1 ).utf8() put(dependency, licenseTxt) } } } } } } override fun close() { thirdPartyLicensesInput.close() thirdPartyLicensesMetadataInput.close() } companion object } private class LicenseMetadataLineParser( private val line: String ) { private var idx = 0 fun readStartIdx(): Int { val end = line.indexOf(':', startIndex = idx) val result = line.substring(idx, end).toInt() idx = end + 1 return result } fun readLength(): Int { val end = line.indexOf(' ', startIndex = idx) val result = line.substring(idx, end).toInt() idx = end + 1 return result } fun readName(): String { val result = line.substring(idx) idx = line.length + 1 return result } } private fun String.toLineParser() = LicenseMetadataLineParser(this)