github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/misc/ios/detect.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build ignore 6 7 // detect attempts to autodetect the correct 8 // values of the environment variables 9 // used by go_darwin_arm_exec. 10 // detect shells out to ideviceinfo, a third party program that can 11 // be obtained by following the instructions at 12 // https://github.com/libimobiledevice/libimobiledevice. 13 package main 14 15 import ( 16 "bytes" 17 "fmt" 18 "io/ioutil" 19 "os" 20 "os/exec" 21 "strings" 22 ) 23 24 func main() { 25 devID := detectDevID() 26 27 udid := detectUDID() 28 mps := detectMobileProvisionFiles(udid) 29 if len(mps) == 0 { 30 fail("did not find mobile provision matching device udid %s", udid) 31 } 32 33 fmt.Println("Available provisioning profiles below.") 34 fmt.Println("NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID") 35 fmt.Println("will be overwritten when running Go programs.") 36 for _, mp := range mps { 37 fmt.Println() 38 fmt.Printf("export GOIOS_DEV_ID=%s\n", devID) 39 f, err := ioutil.TempFile("", "go_ios_detect_") 40 check(err) 41 fname := f.Name() 42 defer os.Remove(fname) 43 44 out := output(parseMobileProvision(mp)) 45 _, err = f.Write(out) 46 check(err) 47 check(f.Close()) 48 49 appID, err := plistExtract(fname, "Entitlements:application-identifier") 50 check(err) 51 fmt.Printf("export GOIOS_APP_ID=%s\n", appID) 52 53 teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier") 54 check(err) 55 fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID) 56 } 57 } 58 59 func detectDevID() string { 60 cmd := exec.Command("security", "find-identity", "-p", "codesigning", "-v") 61 lines := getLines(cmd) 62 63 for _, line := range lines { 64 if !bytes.Contains(line, []byte("iPhone Developer")) { 65 continue 66 } 67 if bytes.Contains(line, []byte("REVOKED")) { 68 continue 69 } 70 fields := bytes.Fields(line) 71 return string(fields[1]) 72 } 73 fail("no code signing identity found") 74 panic("unreachable") 75 } 76 77 var udidPrefix = []byte("UniqueDeviceID: ") 78 79 func detectUDID() []byte { 80 cmd := exec.Command("ideviceinfo") 81 lines := getLines(cmd) 82 for _, line := range lines { 83 if bytes.HasPrefix(line, udidPrefix) { 84 return bytes.TrimPrefix(line, udidPrefix) 85 } 86 } 87 fail("udid not found; is the device connected?") 88 panic("unreachable") 89 } 90 91 func detectMobileProvisionFiles(udid []byte) []string { 92 cmd := exec.Command("mdfind", "-name", ".mobileprovision") 93 lines := getLines(cmd) 94 95 var files []string 96 for _, line := range lines { 97 if len(line) == 0 { 98 continue 99 } 100 xmlLines := getLines(parseMobileProvision(string(line))) 101 for _, xmlLine := range xmlLines { 102 if bytes.Contains(xmlLine, udid) { 103 files = append(files, string(line)) 104 } 105 } 106 } 107 return files 108 } 109 110 func parseMobileProvision(fname string) *exec.Cmd { 111 return exec.Command("security", "cms", "-D", "-i", string(fname)) 112 } 113 114 func plistExtract(fname string, path string) ([]byte, error) { 115 out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput() 116 if err != nil { 117 return nil, err 118 } 119 return bytes.TrimSpace(out), nil 120 } 121 122 func getLines(cmd *exec.Cmd) [][]byte { 123 out := output(cmd) 124 return bytes.Split(out, []byte("\n")) 125 } 126 127 func output(cmd *exec.Cmd) []byte { 128 out, err := cmd.Output() 129 if err != nil { 130 fmt.Println(strings.Join(cmd.Args, "\n")) 131 fmt.Fprintln(os.Stderr, err) 132 os.Exit(1) 133 } 134 return out 135 } 136 137 func check(err error) { 138 if err != nil { 139 fail(err.Error()) 140 } 141 } 142 143 func fail(msg string, v ...interface{}) { 144 fmt.Fprintf(os.Stderr, msg, v...) 145 fmt.Fprintln(os.Stderr) 146 os.Exit(1) 147 }