-
-
Notifications
You must be signed in to change notification settings - Fork 162
/
house_arrest.go
88 lines (76 loc) · 2.2 KB
/
house_arrest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package afc
import (
"bytes"
"errors"
"fmt"
"github.com/danielpaulus/go-ios/ios"
"howett.net/plist"
)
const serviceName = "com.apple.mobile.house_arrest"
type Connection struct {
deviceConn ios.DeviceConnectionInterface
packageNumber uint64
}
//NewFromConn allows to use AFC on a DeviceConnectionInterface, see crashreport for an example
func NewFromConn(deviceConn ios.DeviceConnectionInterface) *Connection {
return &Connection{deviceConn: deviceConn}
}
//NewWithHouseArrest gives an AFC connection to an app container using the house arrest service
func NewWithHouseArrest(device ios.DeviceEntry, bundleID string) (*Connection, error) {
deviceConn, err := ios.ConnectToService(device, serviceName)
if err != nil {
return &Connection{}, err
}
err = vendContainer(deviceConn, bundleID)
if err != nil {
return &Connection{}, err
}
return &Connection{deviceConn: deviceConn}, nil
}
func vendContainer(deviceConn ios.DeviceConnectionInterface, bundleID string) error {
plistCodec := ios.NewPlistCodec()
vendContainer := map[string]interface{}{"Command": "VendContainer", "Identifier": bundleID}
msg, err := plistCodec.Encode(vendContainer)
if err != nil {
return fmt.Errorf("VendContainer Encoding cannot fail unless the encoder is broken: %v", err)
}
err = deviceConn.Send(msg)
if err != nil {
return err
}
reader := deviceConn.Reader()
response, err := plistCodec.Decode(reader)
if err != nil {
return err
}
return checkResponse(response)
}
func checkResponse(vendContainerResponseBytes []byte) error {
response, err := plistFromBytes(vendContainerResponseBytes)
if err != nil {
return err
}
if "Complete" == response.Status {
return nil
}
if response.Error != "" {
return errors.New(response.Error)
}
return errors.New("unknown error during vendcontainer")
}
func plistFromBytes(plistBytes []byte) (vendContainerResponse, error) {
var vendResponse vendContainerResponse
decoder := plist.NewDecoder(bytes.NewReader(plistBytes))
err := decoder.Decode(&vendResponse)
if err != nil {
return vendResponse, err
}
return vendResponse, nil
}
type vendContainerResponse struct {
Status string
Error string
}
func (conn Connection) Close() error {
return conn.deviceConn.Close()
}