Skip to content

Commit c0f2caf

Browse files
authored
Add uninstall command (danielpaulus#77)
* add uninstall command
1 parent 4e75bcf commit c0f2caf

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

ios/installationproxy/installationproxy.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package installationproxy
22

33
import (
44
"bytes"
5+
"fmt"
6+
log "github.com/sirupsen/logrus"
57

68
ios "github.com/danielpaulus/go-ios/ios"
79
"howett.net/plist"
@@ -61,6 +63,56 @@ func (conn *Connection) browseApps(request interface{}) ([]AppInfo, error) {
6163
}
6264
return appinfos, nil
6365
}
66+
67+
func (c *Connection) Uninstall(bundleId string) error {
68+
options := map[string]interface{}{}
69+
uninstallCommand := map[string]interface{}{
70+
"Command": "Uninstall",
71+
"ApplicationIdentifier": bundleId,
72+
"ClientOptions": options,
73+
}
74+
b, err := c.plistCodec.Encode(uninstallCommand)
75+
if err != nil {
76+
return err
77+
}
78+
err = c.deviceConn.Send(b)
79+
if err != nil {
80+
return err
81+
}
82+
for {
83+
response, err := c.plistCodec.Decode(c.deviceConn.Reader())
84+
if err != nil {
85+
return err
86+
}
87+
dict, err := ios.ParsePlist(response)
88+
if err != nil {
89+
return err
90+
}
91+
done, err := checkFinished(dict)
92+
if err != nil {
93+
return err
94+
}
95+
if done {
96+
return nil
97+
}
98+
}
99+
}
100+
101+
func checkFinished(dict map[string]interface{}) (bool, error) {
102+
if val, ok := dict["Error"]; ok {
103+
return true, fmt.Errorf("received uninstall error: %v", val)
104+
}
105+
if val, ok := dict["Status"]; ok {
106+
if "Complete" == val {
107+
log.Info("done uninstalling")
108+
return true, nil
109+
}
110+
log.Infof("uninstall status: %s", val)
111+
return false, nil
112+
}
113+
return true, fmt.Errorf("unknown status update: %+v", dict)
114+
}
115+
64116
func plistFromBytes(plistBytes []byte) (BrowseResponse, error) {
65117
var browseResponse BrowseResponse
66118
decoder := plist.NewDecoder(bytes.NewReader(plistBytes))

main.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Usage:
7070
ios readpair [options]
7171
ios pcap [options] [--pid=<processID>] [--process=<processName>]
7272
ios install --path=<ipaOrAppFolder> [options]
73+
ios uninstall <bundleID> [options]
7374
ios apps [--system] [options]
7475
ios launch <bundleID> [options]
7576
ios kill <bundleID> [options]
@@ -241,6 +242,13 @@ The commands work as following:
241242
return
242243
}
243244

245+
b, _ = arguments.Bool("uninstall")
246+
if b {
247+
bundleID, _ := arguments.String("<bundleID>")
248+
uninstallApp(device, bundleID)
249+
return
250+
}
251+
244252
b, _ = arguments.Bool("image")
245253
if b {
246254
list, _ := arguments.Bool("list")
@@ -582,6 +590,15 @@ func installApp(device ios.DeviceEntry, path string) {
582590
exitIfError("failed writing", err)
583591
}
584592

593+
func uninstallApp(device ios.DeviceEntry, bundleId string) {
594+
log.WithFields(
595+
log.Fields{"appPath": bundleId, "device": device.Properties.SerialNumber}).Info("uninstalling")
596+
svc, err := installationproxy.New(device)
597+
exitIfError("failed connecting to installationproxy", err)
598+
err = svc.Uninstall(bundleId)
599+
exitIfError("failed uninstalling", err)
600+
}
601+
585602
func language(device ios.DeviceEntry, locale string, language string) {
586603
lang, err := ios.GetLanguage(device)
587604
exitIfError("failed getting language", err)

0 commit comments

Comments
 (0)