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