| // 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 | |
| // 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) | |
| } |