using System; using System.IO; using System.IO.Compression; using System.Text.RegularExpressions; namespace CompanyManagment.Application.Helpers { public class ApkInfo { public string VersionName { get; set; } = string.Empty; public string VersionCode { get; set; } = string.Empty; public string PackageName { get; set; } = string.Empty; public string ApplicationLabel { get; set; } = string.Empty; } public static class ApkHelper { public static ApkInfo ReadApkInfo(Stream apkStream) { var apkInfo = new ApkInfo(); try { using var archive = new ZipArchive(apkStream, ZipArchiveMode.Read, true); var manifestEntry = archive.GetEntry("AndroidManifest.xml"); if (manifestEntry == null) { throw new InvalidOperationException("AndroidManifest.xml not found in APK file"); } using var manifestStream = manifestEntry.Open(); using var memoryStream = new MemoryStream(); manifestStream.CopyTo(memoryStream); var manifestBytes = memoryStream.ToArray(); // Parse the binary AndroidManifest.xml apkInfo = ParseBinaryManifest(manifestBytes); // Validate that we found at least version information if (string.IsNullOrEmpty(apkInfo.VersionCode) && string.IsNullOrEmpty(apkInfo.VersionName)) { throw new InvalidOperationException("Could not extract version information from APK"); } return apkInfo; } catch (Exception ex) { throw new InvalidOperationException($"Error reading APK file: {ex.Message}", ex); } } private static ApkInfo ParseBinaryManifest(byte[] manifestBytes) { var apkInfo = new ApkInfo(); try { // Convert bytes to string for regex parsing var text = System.Text.Encoding.UTF8.GetString(manifestBytes); // Extract package name var packageMatch = Regex.Match(text, @"package[^a-zA-Z]+([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+)", RegexOptions.IgnoreCase); if (packageMatch.Success) { apkInfo.PackageName = packageMatch.Groups[1].Value; } // Extract version code - look for numeric values that could be version codes var versionCodeMatch = Regex.Match(text, @"versionCode[^\d]*(\d+)", RegexOptions.IgnoreCase); if (versionCodeMatch.Success) { apkInfo.VersionCode = versionCodeMatch.Groups[1].Value; } else { // Fallback: try to find reasonable numeric values var numbers = Regex.Matches(text, @"\b(\d{1,8})\b"); foreach (Match numMatch in numbers) { if (int.TryParse(numMatch.Groups[1].Value, out int num) && num > 0 && num < 99999999) { apkInfo.VersionCode = num.ToString(); break; } } } // Extract version name var versionNameMatch = Regex.Match(text, @"versionName[^\d]*(\d+(?:\.\d+)*(?:\.\d+)*)", RegexOptions.IgnoreCase); if (versionNameMatch.Success) { apkInfo.VersionName = versionNameMatch.Groups[1].Value; } else { // Fallback: look for version-like patterns var versionMatch = Regex.Match(text, @"\b(\d+\.\d+(?:\.\d+)*)\b"); if (versionMatch.Success) { apkInfo.VersionName = versionMatch.Groups[1].Value; } } // Set defaults if nothing found if (string.IsNullOrEmpty(apkInfo.VersionCode)) apkInfo.VersionCode = "1"; if (string.IsNullOrEmpty(apkInfo.VersionName)) apkInfo.VersionName = "1.0"; if (string.IsNullOrEmpty(apkInfo.PackageName)) apkInfo.PackageName = "unknown.package"; return apkInfo; } catch (Exception) { // Return default values if parsing fails return new ApkInfo { VersionCode = "1", VersionName = "1.0", PackageName = "unknown.package" }; } } } }