예제 #1
0
 /// <summary>
 /// Try to load a bitmap from file.
 /// Returns null when that was not possible.
 /// </summary>
 private static Image LoadBitmap(ApkFile apk, string fileName)
 {
     var data = apk.Load(fileName);
     if (data == null)
         return null;
     return Image.FromStream(new MemoryStream(data));
 }
예제 #2
0
 /// <summary>
 /// Load a resources table from the given apk.
 /// </summary>
 private static Table CreateResourcesArsc(ApkFile apkFile)
 {
     var data = (apkFile != null) ? apkFile.Load("resources.arsc") : null;
     if (data == null)
         return null;
     return new Table(new MemoryStream(data));
 }
예제 #3
0
        /// <summary>
        /// Default ctor
        /// </summary>
        public ApkRunner(IIde ide, string apkPath, string packageName, string activity, bool debuggable, int launchFlags)
        {
            this.ide = ide;
            this.apkPath = apkPath;
            this.packageName = packageName;
            this.activity = activity;
            this.debuggable = debuggable;
            this.launchFlags = launchFlags;
            cancellationTokenSource = new CancellationTokenSource();
            outputPane = ide.CreateDot42OutputPane();
            DeployApk = true;

            // Load package
            try
            {
                var apk = new ApkFile(apkPath);
                if (!apk.Manifest.TryGetMinSdkVersion(out minSdkVersion))
                    minSdkVersion = -1;
            }
            catch (Exception ex)
            {
                minSdkVersion = -1;
                ErrorLog.DumpError(ex);
            }
        }
예제 #4
0
 /// <summary>
 /// Create an layout.xml parser for the data in the given framework folder.
 /// </summary>
 private static LayoutXmlParser CreateLayoutXmlParser(ApkFile apkFile)
 {
     var data = (apkFile != null) ? apkFile.Load("layout.xml") : null;
     if (data == null)
         return new LayoutXmlParser(null);
     return new LayoutXmlParser(new MemoryStream(data));
 }
예제 #5
0
 /// <summary>
 /// Create an attrs.xml parser for the data in the given framework folder.
 /// </summary>
 private static AttrsXmlParser CreateAttrXmlParser(ApkFile apkFile)
 {
     var data = (apkFile != null) ? apkFile.Load("attrs.xml") : null;
     if (data == null)
         return new AttrsXmlParser(null);
     return new AttrsXmlParser(new MemoryStream(data));
 }
예제 #6
0
파일: SourceFile.cs 프로젝트: rfcclub/dot42
        private SourceFile(ApkFile apk, JarFile jar, ISpySettings settings, MapFile mapFile, string singleFilePath = null)
        {
            this.apk = apk;
            this.jar = jar;
            this.settings = settings;
            this.mapFile = mapFile;
            this.singleFilePath = singleFilePath;

#if DEBUG
            classLoader = new AssemblyClassLoader(module.OnClassLoaded);
            var modParams = new ModuleParameters
            {
                AssemblyResolver = new AssemblyResolver(new[] { Frameworks.Instance.FirstOrDefault().Folder }, classLoader, module.OnAssemblyLoaded),
                Kind = ModuleKind.Dll
            };
            assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("spy", Version.Parse("1.0.0.0")), "main", modParams);
            classLoader.LoadAssembly(assembly);

            var dot42Assembly = modParams.AssemblyResolver.Resolve("dot42");

            // Force loading of classes
            if (jar != null)
            {
                foreach (var fileName in jar.ClassFileNames)
                {
                    OpenClass(fileName);
                }
            }
#endif
        }
예제 #7
0
        internal static byte[] GetIcon(string resourceId, ApkFile apk)
        {
            // Look for the files
            var iconFileNames = apk.FileNames.Where(x => MatchesWith(x, resourceId)).ToList();

            // Load all variations
            var icons = iconFileNames.Select(x => LoadBitmap(apk, x)).Where(x => x != null).OrderByDescending(x => Math.Max(x.Width, x.Height)).ToList();

            var icon = icons.FirstOrDefault(x => (x.Height <= MaxWidthHeight) && (x.Width <= MaxWidthHeight));
            if (icon == null)
                return null; // Try scaling

            // Return icon
            var stream = new MemoryStream();
            icon.Save(stream, ImageFormat.Png);
            return stream.ToArray();
        }
예제 #8
0
파일: Program.cs 프로젝트: rfcclub/dot42
        private static void UninstallAPK(string path)
        {
            var pathSet = new HashSet<string>();
            if (File.Exists(path))
            {
                pathSet.Add(path);
            }
            else if (Directory.Exists(path))
            {
                foreach (var file in Directory.EnumerateFiles(path, "*.apk", SearchOption.AllDirectories))
                {
                    pathSet.Add(file);
                }
            }


            try
            {
                var names = new HashSet<string>();
                foreach (var iterator in pathSet)
                {
                    var apk = new ApkFile(iterator);
                    var name = apk.Manifest.PackageName;
                    names.Add(name);
                }

                foreach (var name in names)
                {
                    UninstallAPKByPackageName(name);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to uninstall {0} because {1}", path, ex.Message);
            }
        }
예제 #9
0
        /// <summary>
        /// Default ctor
        /// </summary>
        public MetaInfManifestBuilder(ApkFile apk, string author, string debugTokenPath, Dictionary<string, string> apkPath2barPath)
        {
            // Prepare
            var developmentMode = !string.IsNullOrEmpty(debugTokenPath);            
            var debugToken = developmentMode ? new BarFile(debugTokenPath) : null;
            if (debugToken != null)
            {
                // Verify debug token
                if (!string.Equals(debugToken.Manifest.PackageType, "debug-token", StringComparison.OrdinalIgnoreCase))
                    throw new ArgumentException(string.Format("Debug token {0} has invalid package type", debugTokenPath));
                if (string.IsNullOrEmpty(debugToken.Manifest.PackageAuthor))
                    throw new ArgumentException(string.Format("Debug token {0} has no package author", debugTokenPath));
                if (string.IsNullOrEmpty(debugToken.Manifest.PackageAuthorId))
                    throw new ArgumentException(string.Format("Debug token {0} has no package author id", debugTokenPath));
            }

            // Create manifest
            AppendLine("Archive-Manifest-Version: 1.1");
            AppendLine("Created-By: dot42");
            AppendLine();

            var androidManifest = apk.Manifest;
            if (developmentMode)
            {
                AppendLine("Package-Author: " + debugToken.Manifest.PackageAuthor);
                AppendLine("Package-Author-Id: " + debugToken.Manifest.PackageAuthorId);
            }
            else
            {
                AppendLine("Package-Author: " + author);
                AppendLine("Package-Author-Id: " + FormatID(author));
            }
            AppendLine("Package-Name: " + androidManifest.PackageName);
            AppendLine("Package-Id: " + FormatID(androidManifest.PackageName));
            AppendLine("Package-Version: " + androidManifest.VersionName);
            AppendLine("Package-Version-Id: " + FormatID(androidManifest.VersionName));
            AppendLine("Package-Type: application");
            AppendLine();

            AppendLine("Application-Name: " + androidManifest.ApplicationLabel);
            AppendLine("Application-Id: " + FormatID(androidManifest.ApplicationLabel));
            AppendLine("Application-Version: " + androidManifest.VersionName);
            AppendLine("Application-Version-Id: " + FormatID(androidManifest.VersionName));
            if (developmentMode)
            {
                AppendLine("Application-Development-Mode: true");
            }
            AppendLine();

            // Collect permissions
            var permissions = new HashSet<string> { "access_shared", "play_audio" };
            foreach (var permission in androidManifest.UsesPermissions)
            {
                string bbPerm;
                var key = (permission.Name ?? string.Empty).ToUpperInvariant();
                if (permissionMap.TryGetValue(key, out bbPerm))
                    permissions.Add(bbPerm);
            }
            var userActions = string.Join(",", permissions);

            var entryPoint = GetEntryPoint(androidManifest);
            if (entryPoint != null)
            {
                AppendLine("Entry-Point-Name: " + androidManifest.ApplicationLabel);
                AppendLine("Entry-Point-Type: Qnx/Android");
                AppendLine("Entry-Point: " + string.Format("android://{0}?activity-name={1}", androidManifest.PackageName, entryPoint.Name));
                if (!string.IsNullOrEmpty(userActions))
                {
                    AppendLine("Entry-Point-User-Actions: " + userActions);                    
                }
                var icon = entryPoint.Icon;
                if (string.IsNullOrEmpty(icon)) icon = androidManifest.ApplicationIcon;
                if (!string.IsNullOrEmpty(icon))
                {
                    string iconBarPath;
                    if (apkPath2barPath.TryGetValue(icon, out iconBarPath))
                    {
                        AppendLine("Entry-Point-Icon: " + iconBarPath);
                    }
                }
                AppendLine();
            }
        }
예제 #10
0
        /// <summary>
        /// Compile the given XML file to a binary XML file in the given output folder.
        /// </summary>
        public void Build()
        {
#if DEBUG
            //Debugger.Launch();
#endif

            // Prepare folder
            var outputFolder = Path.GetDirectoryName(path);
            if (!Directory.Exists(outputFolder))
                Directory.CreateDirectory(outputFolder);

            // Sign bar?
            const bool sign = true;

            // Load APK
            var apk = new ApkFile(ApkPath);

            // Collect entries
            var entries = new List<BarEntry>();
            var apkName = Path.GetFileNameWithoutExtension(path) + ".apk";
            entries.Add(new BarEntry(string.Format(@"android\{0}", apkName), ApkPath));

            // Collect icon's
            var apkPath2barPath = new Dictionary<string, string>();
            CollectIcons(apk, entries, apkPath2barPath);

            // Build ZIP
            var manifest = new MetaInfManifestBuilder(apk, Author, DebugTokenPath, apkPath2barPath);

            // Build signatures
            if (sign)
            {
                foreach (var entry in entries)
                {
                    manifest.AddArchiveAsset(entry.Name, entry.Data);
                    //signature.AddSha1Digest(entry.Name, entry.Data);
                }
            }

            // Create zip
            ////string md5FingerPrint = null;
            ////string sha1FingerPrint = null;
            using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                using (var zipStream = new ZipOutputStream(fileStream) {UseZip64 = UseZip64.Off})
                {
                    zipStream.SetLevel(9);

                    zipStream.PutNextEntry(new ZipEntry("META-INF/MANIFEST.MF") { CompressionMethod = CompressionMethod.Deflated });
                    manifest.WriteTo(zipStream);
                    zipStream.CloseEntry();

                    ////if (sign)
                    ////{
                    ////    zipStream.PutNextEntry(new ZipEntry("META-INF/LE-C0FC2.SF")
                    ////    {CompressionMethod = CompressionMethod.Deflated});
                    ////    signature.WriteTo(zipStream);
                    ////    zipStream.CloseEntry();

                    ////    zipStream.PutNextEntry(new ZipEntry("META-INF/LE-C0FC2.RSA")
                    ////    {CompressionMethod = CompressionMethod.Deflated});
                    ////    rsa.WriteTo(zipStream, out md5FingerPrint, out sha1FingerPrint);
                    ////    zipStream.CloseEntry();
                    ////}

                    foreach (var entry in entries)
                    {
                        var entryName = entry.Name.Replace('\\', '/');
                        zipStream.PutNextEntry(new ZipEntry(entryName) { CompressionMethod = GetCompressionMethod(entryName) });
                        entry.WriteTo(zipStream);
                        zipStream.CloseEntry();
                    }
                }
            }

#if NO_FINGERPRINT_YET
            // Save MD5 fingerprint
            var md5FingerPrintPath = Path.ChangeExtension(path, ".md5");
            File.WriteAllText(md5FingerPrintPath, md5FingerPrint ?? string.Empty);

            // Save SHA1 fingerprint
            var sha1FingerPrintPath = Path.ChangeExtension(path, ".sha1");
            File.WriteAllText(sha1FingerPrintPath, sha1FingerPrint ?? string.Empty);
#endif

#if DEBUG && NO_RSA_YET
            // Create RSA
            using (var fileStream = new FileStream(Path.Combine(outputFolder, "CERT.RSA"), FileMode.Create,
                                                FileAccess.Write))
            {
                rsa.WriteTo(fileStream, out md5FingerPrint, out sha1FingerPrint);
            }
#endif
        }
예제 #11
0
        /// <summary>
        /// Collect all icons
        /// </summary>
        private static void CollectIcons(ApkFile apk, List<BarEntry> entries, Dictionary<string, string> apkPath2barPath)
        {
#if DEBUG
            Debugger.Launch();
#endif

            var iconNames = apk.Manifest.Activities.Select(x => x.Icon).Where(x => !string.IsNullOrEmpty(x)).ToList();
            var appIcon = apk.Manifest.ApplicationIcon;
            if (!string.IsNullOrEmpty(appIcon))
                iconNames.Add(appIcon);

            foreach (var name in iconNames)
            {
                if (apkPath2barPath.ContainsKey(name))
                    continue;
                int nameAsInt;
                if (!int.TryParse(name, out nameAsInt))
                    continue;
                var resId = apk.Resources.GetResourceIdentifier(nameAsInt);
                var iconData = IconBuilder.GetIcon(resId, apk);
                if (iconData != null)
                {
                    var barPath = "android/res/drawable/" + resId + ".png";
                    var entry = new BarEntry(barPath, new MemoryStream(iconData));
                    entries.Add(entry);
                    apkPath2barPath[name] = barPath;
                }
            }
        }
예제 #12
0
 private DexLookup LoadDex()
 {
     var apk = new ApkFile(_apkPath);
     var dex = apk.Load("classes.dex");
     return new DexLookup(Dex.Read(new MemoryStream(dex)));
 }
예제 #13
0
        /// <summary>
        /// Starts the debugger.
        /// </summary>
        internal void DebugLaunch(uint grfLaunch)
        {
            // Open the package
            PackageFile packageFile;
            var         packagePath = PackagePath;

            try
            {
                packageFile = new PackageFile(packagePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Failed to open package because: {0}", ex.Message));
                return;
            }

            // Show device selection
            var debuggable = (grfLaunch != (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_NoDebug);
            var ide        = Package.Ide;

#if ANDROID
            int minSdkVersion;
            if (!packageFile.Manifest.TryGetMinSdkVersion(out minSdkVersion))
            {
                minSdkVersion = -1;
            }
            var targetFramework = (minSdkVersion > 0) ? Frameworks.Instance.GetBySdkVersion(minSdkVersion) : null;
            var targetVersion   = (targetFramework != null) ? targetFramework.Name : null;
            var runner          = new ApkRunner(ide, packagePath, packageFile.Manifest.PackageName, packageFile.Manifest.Activities.Select(x => x.Name).FirstOrDefault(), debuggable, (int)grfLaunch);
#elif BB
            var targetFramework = Frameworks.Instance.FirstOrDefault();
            var targetVersion   = (targetFramework != null) ? targetFramework.Name : null;
            var runner          = new BarRunner(ide, packagePath, packageFile.Manifest.PackageName, "--default--", debuggable, (int)grfLaunch);
#endif

            using (var dialog = new DeviceSelectionDialog(ide, runner.DeviceIsCompatible, targetVersion))
            {
                var rc = dialog.ShowDialog();
                switch (rc)
                {
                case DialogResult.OK:
                    var device = dialog.SelectedDevice;
                    Package.Ide.LastUsedUniqueId = device.UniqueId;

                    using (var xDialog = new LauncherDialog(packagePath, debuggable))
                    {
                        var stateDialog = xDialog;
                        stateDialog.Cancel += (s, x) => runner.Cancel();
                        stateDialog.Load   += (s, x) => runner.Run(device, stateDialog.SetState);
                        stateDialog.ShowDialog();
                    }
                    break;

                case DialogResult.Retry:
                    // Change project target version
                    try
                    {
                        ChangeAndroidTargetVersion(dialog.NewProjectTargetVersion);
                        MessageBox.Show(string.Format("Changed target framework version to {0}, to match the Android version of your device.", dialog.NewProjectTargetVersion));
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(string.Format("Failed to change target framework version because: {0}", ex.Message));
                    }
                    break;
                }
            }
        }
예제 #14
0
        /// <summary>
        /// Compile the given resources into a suitable output folder.
        /// </summary>
        internal bool Compile(List<Tuple<string, ResourceType>> resources, List<string> appWidgetProviderCodeFiles, List<string> references, List<string> referenceFolders, string baseApkPath)
        {
            // Remove temp folder
            if (Directory.Exists(tempFolder))
            {
                Directory.Delete(tempFolder, true);
            }

            // Ensure temp\res folder exists
            var resFolder = Path.Combine(tempFolder, "res");
            Directory.CreateDirectory(resFolder);
            var tempApkPath = Path.Combine(tempFolder, "temp.apk");

            // Compile each resource
            foreach (var resource in resources.Where(x => x.Item2 != ResourceType.Manifest))
            {
                CopyResourceToFolder(tempFolder, resource.Item1, resource.Item2);
            }

            // Extract resources out of library project references
            var resolver = new AssemblyResolver(referenceFolders, null, null);
            foreach (var path in references)
            {
                ExtractLibraryProjectResources(resFolder, path, resolver);
            }

            // Select manifest path
            var manifestPath = resources.Where(x => x.Item2 == ResourceType.Manifest).Select(x => x.Item1).FirstOrDefault();

            // Ensure files exists for the appwidgetproviders
            CreateAppWidgetProviderFiles(tempFolder, manifestPath, appWidgetProviderCodeFiles);

            // Create system ID's resource
            CreateSystemIdsResource(tempFolder);

            // Run aapt
            var args = new[] {
                                 "p",
                                 "-f",
                                 "-S",
                                 resFolder,
                                 "-M",
                                 GetManifestPath(tempFolder, manifestPath, packageName),
                                 "-I",
                                 baseApkPath,
                                 "-F",
                                 tempApkPath
                             };
            var runner = new ProcessRunner(Locations.Aapt, args);
            var exitCode = runner.Run();
            if (exitCode != 0)
            {
                ProcessAaptErrors(runner.Output, tempFolder, resources);
                return false;
            }

            // Unpack compiled resources to base folder.
            Table resourceTable = null;
            using (var apk = new ApkFile(tempApkPath))
            {
                foreach (var name in apk.FileNames)
                {
                    // Extract
                    var data = apk.Load(name);

                    // Save
                    var path = Path.Combine(baseFolder, name);
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                    File.WriteAllBytes(path, data);

                    // Is resource table? yes -> load it
                    if (name == "resources.arsc")
                    {
                        resourceTable = new Table(new MemoryStream(data));
                    }
                }
            }

            // Create R.cs
            if (!string.IsNullOrEmpty(generatedCodeFolder))
            {
                var codeBuilder = new CreateResourceIdsCode(resourceTable, resources, valuesResourceProcessor.StyleableDeclarations);
                codeBuilder.Generate(generatedCodeFolder, packageName, generatedCodeNamespace, generatedCodeLanguage, lastModified);
            }

            // Create resource type usage info file
            if (!string.IsNullOrEmpty(resourceTypeUsageInformationPath))
            {
                // Ensure folder exists
                var folder = Path.GetDirectoryName(resourceTypeUsageInformationPath);
                if (!Directory.Exists(folder))
                    Directory.CreateDirectory(folder);

                // Create file
                File.WriteAllLines(resourceTypeUsageInformationPath, layoutProcessor.CustomClassNames);                
            }

            return true;
        }
예제 #15
0
        public override void Start(bool withDebugging)
        {
            // Open the package
            ApkFile apkFile;
            var apkPath = ApkPath;
            try
            {
                apkFile = new ApkFile(apkPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Failed to open package because: {0}", ex.Message));
                return;
            }

            // Show device selection
            var ide = Dot42Addin.Ide;
            int minSdkVersion;
            if (!apkFile.Manifest.TryGetMinSdkVersion(out minSdkVersion))
                minSdkVersion = -1;
            var targetFramework = (minSdkVersion > 0) ? Frameworks.Instance.GetBySdkVersion(minSdkVersion) : null;
            var targetVersion = (targetFramework != null) ? targetFramework.Name : null;
            var runner = new ApkRunner(ide, ApkPath, apkFile.Manifest.PackageName, apkFile.Manifest.Activities.Select(x => x.Name).FirstOrDefault(), withDebugging, 0);
            using (var dialog = new DeviceSelectionDialog(ide, IsCompatible, targetVersion)) {
                if (dialog.ShowDialog() == DialogResult.OK) {
                    // Run on the device now
                    var device = dialog.SelectedDevice;
                    ide.LastUsedUniqueId = device.UniqueId;

                    using (var xDialog = new LauncherDialog(apkPath, withDebugging))
                    {
                        var stateDialog = xDialog;
                        stateDialog.Cancel += (s, x) => runner.Cancel();
                        stateDialog.Load += (s, x) => runner.Run(device, stateDialog.SetState);
                        stateDialog.ShowDialog();
                    }
                }
            }
        }
예제 #16
0
        /// <summary>
        /// Starts the debugger.
        /// </summary>
        internal void DebugLaunch(uint grfLaunch)
        {
            // Open the package
            PackageFile packageFile;
            var packagePath = PackagePath;
            try
            {
                packageFile = new PackageFile(packagePath);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Failed to open package because: {0}", ex.Message));
                return;
            }

            // Show device selection
            var debuggable = (grfLaunch != (uint)__VSDBGLAUNCHFLAGS.DBGLAUNCH_NoDebug);
            var ide = Package.Ide;

#if ANDROID
            int minSdkVersion;
            if (!packageFile.Manifest.TryGetMinSdkVersion(out minSdkVersion))
                minSdkVersion = -1;
            var targetFramework = (minSdkVersion > 0) ? Frameworks.Instance.GetBySdkVersion(minSdkVersion) : null;
            var targetVersion = (targetFramework != null) ? targetFramework.Name : null;
            var runner = new ApkRunner(ide, packagePath, packageFile.Manifest.PackageName, packageFile.Manifest.Activities.Select(x => x.Name).FirstOrDefault(), debuggable, (int) grfLaunch);
#elif BB
            var targetFramework = Frameworks.Instance.FirstOrDefault();
            var targetVersion = (targetFramework != null) ? targetFramework.Name : null;
            var runner = new BarRunner(ide, packagePath, packageFile.Manifest.PackageName, "--default--", debuggable, (int)grfLaunch);
#endif
            
            using (var dialog = new DeviceSelectionDialog(ide, runner.DeviceIsCompatible, targetVersion))
            {
                var rc= dialog.ShowDialog();
                switch (rc)
                {
                    case DialogResult.OK:
                        var device = dialog.SelectedDevice;
                        Package.Ide.LastUsedUniqueId = device.UniqueId;

                        using (var xDialog = new LauncherDialog(packagePath, debuggable))
                        {
                            var stateDialog = xDialog;
                            stateDialog.Cancel += (s, x) => runner.Cancel();
                            stateDialog.Load += (s, x) => runner.Run(device, stateDialog.SetState);
                            stateDialog.ShowDialog();
                        }
                        break;
                    case DialogResult.Retry:
                        // Change project target version
                        try
                        {
                            ChangeAndroidTargetVersion(dialog.NewProjectTargetVersion);
                            MessageBox.Show(string.Format("Changed target framework version to {0}, to match the Android version of your device.", dialog.NewProjectTargetVersion));
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(string.Format("Failed to change target framework version because: {0}", ex.Message));
                        }
                        break;
                }
            }
        }
예제 #17
0
 /// <summary>
 /// Gets the name of the APK package.
 /// </summary>
 private string GetApkName()
 {
     var apk = new ApkFile(Package.ItemSpec);
     return apk.Manifest.PackageName;
 }