diff options
Diffstat (limited to 'misc/ios/detect.go')
-rw-r--r-- | misc/ios/detect.go | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/misc/ios/detect.go b/misc/ios/detect.go new file mode 100644 index 0000000..1cb8ae5 --- /dev/null +++ b/misc/ios/detect.go @@ -0,0 +1,134 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// detect attempts to autodetect the correct +// values of the environment variables +// used by go_ios_exec. +// detect shells out to ideviceinfo, a third party program that can +// be obtained by following the instructions at +// https://github.com/libimobiledevice/libimobiledevice. +package main + +import ( + "bytes" + "crypto/x509" + "fmt" + "os" + "os/exec" + "strings" +) + +func main() { + udids := getLines(exec.Command("idevice_id", "-l")) + if len(udids) == 0 { + fail("no udid found; is a device connected?") + } + + mps := detectMobileProvisionFiles(udids) + if len(mps) == 0 { + fail("did not find mobile provision matching device udids %q", udids) + } + + fmt.Println("# Available provisioning profiles below.") + fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID") + fmt.Println("# will be overwritten when running Go programs.") + for _, mp := range mps { + fmt.Println() + f, err := os.CreateTemp("", "go_ios_detect_") + check(err) + fname := f.Name() + defer os.Remove(fname) + + out := output(parseMobileProvision(mp)) + _, err = f.Write(out) + check(err) + check(f.Close()) + + cert, err := plistExtract(fname, "DeveloperCertificates:0") + check(err) + pcert, err := x509.ParseCertificate(cert) + check(err) + fmt.Printf("export GOIOS_DEV_ID=\"%s\"\n", pcert.Subject.CommonName) + + appID, err := plistExtract(fname, "Entitlements:application-identifier") + check(err) + fmt.Printf("export GOIOS_APP_ID=%s\n", appID) + + teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier") + check(err) + fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID) + } +} + +func detectMobileProvisionFiles(udids [][]byte) []string { + cmd := exec.Command("mdfind", "-name", ".mobileprovision") + lines := getLines(cmd) + + var files []string + for _, line := range lines { + if len(line) == 0 { + continue + } + xmlLines := getLines(parseMobileProvision(string(line))) + matches := 0 + for _, udid := range udids { + for _, xmlLine := range xmlLines { + if bytes.Contains(xmlLine, udid) { + matches++ + } + } + } + if matches == len(udids) { + files = append(files, string(line)) + } + } + return files +} + +func parseMobileProvision(fname string) *exec.Cmd { + return exec.Command("security", "cms", "-D", "-i", string(fname)) +} + +func plistExtract(fname string, path string) ([]byte, error) { + out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput() + if err != nil { + return nil, err + } + return bytes.TrimSpace(out), nil +} + +func getLines(cmd *exec.Cmd) [][]byte { + out := output(cmd) + lines := bytes.Split(out, []byte("\n")) + // Skip the empty line at the end. + if len(lines[len(lines)-1]) == 0 { + lines = lines[:len(lines)-1] + } + return lines +} + +func output(cmd *exec.Cmd) []byte { + out, err := cmd.Output() + if err != nil { + fmt.Println(strings.Join(cmd.Args, "\n")) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + return out +} + +func check(err error) { + if err != nil { + fail(err.Error()) + } +} + +func fail(msg string, v ...interface{}) { + fmt.Fprintf(os.Stderr, msg, v...) + fmt.Fprintln(os.Stderr) + os.Exit(1) +} |