-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrosumi.rb
132 lines (96 loc) · 3.62 KB
/
rosumi.rb
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require "uri"
require 'json'
require 'net/http'
require 'net/https'
require 'base64'
class Rosumi
URL="fmipmobile.icloud.com"
PORT=443
attr_accessor :devices
def initialize(user, pass, verbose = false)
@user = user
@pass = pass
@verbose = verbose
@devices = []
@partition = nil
@http = Net::HTTP.new(URL, PORT)
@http.use_ssl=true
self.updateDevices()
end
def updateDevices
post = {'clientContext' => {'appName' => 'FindMyiPhone',
'appVersion' => '1.4',
'buildVersion' => '145',
'deviceUDID' => '0000000000000000000000000000000000000000',
'inactiveTime' => 2147483647,
'osVersion' => '4.2.1',
'personID' => 0,
'productType' => 'iPad1,1'
}};
json_devices = self.post("/fmipservice/device/#{@user}/initClient", post)
puts 'posted' if @verbose
puts json_devices if @verbose
@devices = [];
json_devices['content'].each { |json_device| @devices << json_device }
@devices
end
def post(path, data)
auth = Base64.encode64(@user+':'+@pass)
puts auth if @verbose
headers = {
'Content-Type' => 'application/json; charset=utf-8',
'X-Apple-Find-Api-Ver' => '2.0',
'X-Apple-Authscheme' => 'UserIdGuest',
'X-Apple-Realm-Support' => '1.2',
'User-Agent' => 'Find iPhone/1.1 MeKit (iPad: iPhone OS/4.2.1)',
'X-Client-Name' => 'iPad',
'X-Client-Uuid' => '0cf3dc501ff812adb0b202baed4f37274b210853',
'Accept-Language' => 'en-us',
'Authorization' => "Basic #{auth}"
}
puts "Path = #{path}" if @verbose
unless @partition
@partition = fetchPartition(path, JSON.generate(data), headers)
@http = Net::HTTP.new(@partition, PORT)
@http.use_ssl=true
end
resp = fetch(path, JSON.generate(data), headers)
return JSON.parse(resp.body);
end
def locate(device_num = 0, max_wait = 300)
start = Time.now
begin
raise "Unable to find location within '#{max_wait}' seconds" if ((Time.now - start) > max_wait)
sleep(5)
self.updateDevices()
raise "Invalid device number!" if @devices[device_num].nil?
raise "There is no location data for this device (#{@devices[device_num]['name']})" if @devices[device_num]['location'].nil?
end while (@devices[device_num]['location']['locationFinished'] == 'false')
loc = {
:name => @devices[device_num]['name'],
:latitude => @devices[device_num]['location']['latitude'],
:longitude => @devices[device_num]['location']['longitude'],
:accuracy => @devices[device_num]['location']['horizontalAccuracy'],
:timestamp => @devices[device_num]['location']['timeStamp'],
:position_type => @devices[device_num]['location']['positionType']
};
return loc;
end
private
def fetch(path, data, headers, limit = 10)
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
response = @http.post(path, data, headers)
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then fetch(response['location'], data, headers, limit - 1)
else
response.error!
end
end
def fetchPartition(path, data, headers)
puts 'fetching partition' if @verbose
response = @http.post(path, data, headers)
puts "got partition #{response['X-Apple-MMe-Host']}" if @verbose
response['X-Apple-MMe-Host']
end
end