import { AnalysisType, AnalyzedPackageWithVersion, ImagePackagesAnalysis, } from "../types"; export function analyze( targetImage: string, apkDbFileContent: string, ): Promise { return Promise.resolve({ Image: targetImage, AnalyzeType: AnalysisType.Apk, Analysis: parseFile(apkDbFileContent), }); } export function parseFile(text: string): AnalyzedPackageWithVersion[] { const pkgs: AnalyzedPackageWithVersion[] = []; let curPkg: AnalyzedPackageWithVersion | null = null; // Absolute path of the most recent F: record; "" until one is seen. let currentDir = ""; for (const line of text.split("\n")) { if (line.length < 2) { continue; } const key = line.charAt(0); const value = line.substr(2).trim(); switch (key) { case "P": { // Package curPkg = { Name: value, Version: "", Source: undefined, Provides: [], Deps: {}, AutoInstalled: undefined, Files: [], Directories: [], }; pkgs.push(curPkg); currentDir = ""; break; } case "V": // Version if (curPkg) { curPkg.Version = value; } break; case "p": // Provides if (curPkg) { for (let name of value.split(" ")) { name = name.split("=")[0]; curPkg.Provides.push(name); } } break; case "r": // Depends case "D": // Depends if (curPkg) { for (let name of value.split(" ")) { if (name.charAt(0) !== "!") { name = name.split("=")[0]; curPkg.Deps[name] = true; } } } break; case "o": // Origin if (curPkg) { curPkg.Source = value; } break; case "F": { // Directory for subsequent R: file-list records, root-relative // like "usr/lib" if (!curPkg) { break; } currentDir = value ? "/" + value : ""; if (currentDir && !curPkg.Directories!.includes(currentDir)) { curPkg.Directories!.push(currentDir); } break; } case "R": { // File name relative to the current F: directory if (!curPkg || !currentDir) { break; } curPkg.Files!.push(`${currentDir}/${value}`); break; } } } return pkgs; }