github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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 "crypto/x509" 18 "fmt" 19 "io/ioutil" 20 "os" 21 "os/exec" 22 "strings" 23 ) 24 25 func main() { 26 udids := getLines(exec.Command("idevice_id", "-l")) 27 if len(udids) == 0 { 28 fail("no udid found; is a device connected?") 29 } 30 31 mps := detectMobileProvisionFiles(udids) 32 if len(mps) == 0 { 33 fail("did not find mobile provision matching device udids %q", udids) 34 } 35 36 fmt.Println("# Available provisioning profiles below.") 37 fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID") 38 fmt.Println("# will be overwritten when running Go programs.") 39 for _, mp := range mps { 40 fmt.Println() 41 f, err := ioutil.TempFile("", "go_ios_detect_") 42 check(err) 43 fname := f.Name() 44 defer os.Remove(fname) 45 46 out := output(parseMobileProvision(mp)) 47 _, err = f.Write(out) 48 check(err) 49 check(f.Close()) 50 51 cert, err := plistExtract(fname, "DeveloperCertificates:0") 52 check(err) 53 pcert, err := x509.ParseCertificate(cert) 54 check(err) 55 fmt.Printf("export GOIOS_DEV_ID=\"%s\"\n", pcert.Subject.CommonName) 56 57 appID, err := plistExtract(fname, "Entitlements:application-identifier") 58 check(err) 59 fmt.Printf("export GOIOS_APP_ID=%s\n", appID) 60 61 teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier") 62 check(err) 63 fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID) 64 } 65 } 66 67 func detectMobileProvisionFiles(udids [][]byte) []string { 68 cmd := exec.Command("mdfind", "-name", ".mobileprovision") 69 lines := getLines(cmd) 70 71 var files []string 72 for _, line := range lines { 73 if len(line) == 0 { 74 continue 75 } 76 xmlLines := getLines(parseMobileProvision(string(line))) 77 matches := 0 78 for _, udid := range udids { 79 for _, xmlLine := range xmlLines { 80 if bytes.Contains(xmlLine, udid) { 81 matches++ 82 } 83 } 84 } 85 if matches == len(udids) { 86 files = append(files, string(line)) 87 } 88 } 89 return files 90 } 91 92 func parseMobileProvision(fname string) *exec.Cmd { 93 return exec.Command("security", "cms", "-D", "-i", string(fname)) 94 } 95 96 func plistExtract(fname string, path string) ([]byte, error) { 97 out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput() 98 if err != nil { 99 return nil, err 100 } 101 return bytes.TrimSpace(out), nil 102 } 103 104 func getLines(cmd *exec.Cmd) [][]byte { 105 out := output(cmd) 106 lines := bytes.Split(out, []byte("\n")) 107 // Skip the empty line at the end. 108 if len(lines[len(lines)-1]) == 0 { 109 lines = lines[:len(lines)-1] 110 } 111 return lines 112 } 113 114 func output(cmd *exec.Cmd) []byte { 115 out, err := cmd.Output() 116 if err != nil { 117 fmt.Println(strings.Join(cmd.Args, "\n")) 118 fmt.Fprintln(os.Stderr, err) 119 os.Exit(1) 120 } 121 return out 122 } 123 124 func check(err error) { 125 if err != nil { 126 fail(err.Error()) 127 } 128 } 129 130 func fail(msg string, v ...interface{}) { 131 fmt.Fprintf(os.Stderr, msg, v...) 132 fmt.Fprintln(os.Stderr) 133 os.Exit(1) 134 }