Skip to content

Instantly share code, notes, and snippets.

@albeebe albeebe/Working Sosumi PHP
Last active Apr 14, 2019

Embed
What would you like to do?
<?PHP
// https://twitter.com/#!/marcoarment/status/59089853433921537
date_default_timezone_set('America/Los_Angeles');
// Sosumi - a PHP client for Apple's Find My iPhone web service
//
// June 20, 2010
// Tyler Hall <tylerhall@gmail.com>
// http://github.com/tylerhall/sosumi/tree/master
//
// Usage:
// $ssm = new Sosumi('username', 'password');
// $location_info = $ssm->locate(<device id>);
// $ssm->sendMessage('Your Message', true, <device id>, 'Important Message');
class Sosumi
{
public $devices;
public $debug;
private $username;
private $password;
private $partition;
private $scope;
private $prsId;
public function __construct($mobile_me_username, $mobile_me_password, $debug = false)
{
$this->devices = array();
$this->debug = $debug;
$this->username = $mobile_me_username;
$this->password = $mobile_me_password;
$this->getPartition();
$this->initClient();
$this->refreshClient();
}
private function getPartition()
{
$this->iflog('Getting partition...');
//$post = '{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":2147483647,"osVersion":"4.2.1","personID":0,"productType":"iPad1,1"}}';
$response = $this->curlPost("/fmipservice/device/{$this->username}/initClient", $post, array(), true);
preg_match('/MMe-Host:(.*?)$/msi', $response, $matches);
if(isset($matches[1])) $this->partition = trim($matches[1]);
preg_match('/MMe-Scope:(.*?)$/msi', $response, $matches);
if(isset($matches[1])) $this->scope = trim($matches[1]);
}
public function refreshClient()
{
$this->iflog('refreshClient ' . $this->prsId);
$post = '{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":2147483647,"osVersion":"4.2.1","personID":0,"productType":"iPad1,1"}}';
$response = $this->curlPost("/fmipservice/device/{$this->prsId}/refreshClient", $post, array(), true);
}
public function locate($device_id, $max_wait = 300)
{
$start = time();
// Loop until the device has been located...
while(!$this->devices[$device_id]->latitude || !$this->devices[$device_id]->longitude)
{
$this->iflog('Waiting for location...');
if((time() - $start) > $max_wait)
{
throw new Exception("Unable to find location within '$max_wait' seconds\n");
}
sleep(5);
$this->initClient();
}
$loc = array(
"latitude" => $this->devices[$device_id]->latitude,
"longitude" => $this->devices[$device_id]->longitude,
"accuracy" => $this->devices[$device_id]->horizontalAccuracy,
"timestamp" => $this->devices[$device_id]->locationTimestamp,
);
return $loc;
}
public function sendMessage($device_id, $msg, $alarm = false, $subject = 'Important Message')
{
$post = sprintf('{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":5911,"osVersion":"3.2","productType":"iPad1,1","selectedDevice":"%s","shouldLocate":false},"device":"%s","serverContext":{"callbackIntervalInMS":3000,"clientId":"0000000000000000000000000000000000000000","deviceLoadStatus":"203","hasDevices":true,"lastSessionExtensionTime":null,"maxDeviceLoadTime":60000,"maxLocatingTime":90000,"preferredLanguage":"en","prefsUpdateTime":1276872996660,"sessionLifespan":900000,"timezone":{"currentOffset":-25200000,"previousOffset":-28800000,"previousTransition":1268560799999,"tzCurrentName":"Pacific Daylight Time","tzName":"America/Los_Angeles"},"validRegion":true},"sound":%s,"subject":"%s","text":"%s","userText":true}',
$device_id, $device_id,
$alarm ? 'true' : 'false', $subject, $msg);
$this->iflog('Sending message...');
$this->curlPost("/fmipservice/device/{$this->username}/sendMessage", $post);
$this->iflog('Message sent');
}
public function remoteLock($device_id, $passcode)
{
$post = sprintf('{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":5911,"osVersion":"3.2","productType":"iPad1,1","selectedDevice":"%s","shouldLocate":false},"device":"%s","oldPasscode":"","passcode":"%s","serverContext":{"callbackIntervalInMS":3000,"clientId":"0000000000000000000000000000000000000000","deviceLoadStatus":"203","hasDevices":true,"lastSessionExtensionTime":null,"maxDeviceLoadTime":60000,"maxLocatingTime":90000,"preferredLanguage":"en","prefsUpdateTime":1276872996660,"sessionLifespan":900000,"timezone":{"currentOffset":-25200000,"previousOffset":-28800000,"previousTransition":1268560799999,"tzCurrentName":"Pacific Daylight Time","tzName":"America/Los_Angeles"},"validRegion":true}}',
$device_id, $device_id, $passcode);
$this->iflog('Sending remote lock...');
$this->curlPost("/fmipservice/device/{$this->username}/remoteLock", $post);
$this->iflog('Remote lock sent');
}
// This hasn't been tested (for obvious reasons). Please let me know if it does/doesn't work...
public function remoteWipe($device_id, $passcode)
{
$post = sprintf('{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":5911,"osVersion":"3.2","productType":"iPad1,1","selectedDevice":"%s","shouldLocate":false},"device":"%s","oldPasscode":"","passcode":"%s","serverContext":{"callbackIntervalInMS":3000,"clientId":"0000000000000000000000000000000000000000","deviceLoadStatus":"203","hasDevices":true,"lastSessionExtensionTime":null,"maxDeviceLoadTime":60000,"maxLocatingTime":90000,"preferredLanguage":"en","prefsUpdateTime":1276872996660,"sessionLifespan":900000,"timezone":{"currentOffset":-25200000,"previousOffset":-28800000,"previousTransition":1268560799999,"tzCurrentName":"Pacific Daylight Time","tzName":"America/Los_Angeles"},"validRegion":true}}',
$device_id, $device_id, $passcode);
$this->iflog('Sending remote wipe...');
$this->curlPost("/fmipservice/device/{$this->username}/remoteWipe", $post);
$this->iflog('Remote wipe sent');
}
private function initClient()
{
$this->iflog('initClient...');
$post = '{}';//'{"clientContext":{"appName":"FindMyiPhone","appVersion":"1.4","buildVersion":"145","deviceUDID":"0000000000000000000000000000000000000000","inactiveTime":2147483647,"osVersion":"4.2.1","personID":0,"productType":"iPad1,1"}}';
$json_str = $this->curlPost("/fmipservice/device/{$this->scope}/initClient", $post);
$this->iflog('initClient Returned: ' . $json_str);
$json = json_decode($json_str);
if(is_null($json))
throw new Exception("Error parsing json string");
if(isset($json->error))
throw new Exception("Error from web service: '$json->error'");
$this->devices = array();
if(isset($json) && isset($json->content) && (is_array($json->content) || is_object($json->content))){
$this->prsId = $json->serverContext->prsId;
$this->iflog('Parsing ' . count($json->content) . ' devices...');
foreach($json->content as $json_device)
{
$device = new SosumiDevice();
if(isset($json_device->location) && is_object($json_device->location))
{
$device->locationTimestamp = date('Y-m-d H:i:s', $json_device->location->timeStamp / 1000);
$device->locationType = $json_device->location->positionType;
$device->horizontalAccuracy = $json_device->location->horizontalAccuracy;
$device->locationFinished = $json_device->location->locationFinished;
$device->longitude = $json_device->location->longitude;
$device->latitude = $json_device->location->latitude;
}
$device->isLocating = $json_device->isLocating;
$device->deviceModel = $json_device->deviceModel;
$device->deviceStatus = $json_device->deviceStatus;
$device->id = $json_device->id;
$device->name = $json_device->name;
$device->deviceClass = $json_device->deviceClass;
$device->chargingStatus = $json_device->batteryStatus;
$device->batteryLevel = $json_device->batteryLevel;
$this->devices[$device->id] = $device;
}
}
}
private function curlPost($url, $post_vars = '', $headers = array(), $return_headers = false)
{
if(isset($this->partition))
$url = 'https://' . $this->partition . $url;
else
$url = 'https://fmipmobile.icloud.com' . $url;
$this->iflog("URL: $url");
$this->iflog("POST DATA: $post_vars");
$headers[] = 'Content-Type: application/json; charset=utf-8';
$headers[] = 'X-Apple-Find-Api-Ver: 3.0';
$headers[] = 'X-Apple-Authscheme: UserIdGuest';
$headers[] = 'X-Apple-Realm-Support: 1.0';
$headers[] = 'User-agent: FindMyiPhone/472.1 CFNetwork/711.1.12 Darwin/14.0.0';
$headers[] = 'X-Client-Name: iPad';
$headers[] = 'X-Client-UUID: 0cf3dc501ff812adb0b202baed4f37274b210853';
$headers[] = 'Accept-Language: en-us';
$headers[] = "Connection: keep-alive";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERPWD, $this->username . ':' . $this->password);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_vars);
if(!is_null($headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// curl_setopt($ch, CURLOPT_VERBOSE, true);
if($return_headers)
curl_setopt($ch, CURLOPT_HEADER, true);
return curl_exec($ch);
}
private function iflog($str)
{
if($this->debug === true)
echo $str . "\n";
}
}
class SosumiDevice
{
public $isLocating;
public $locationTimestamp;
public $locationType;
public $horizontalAccuracy;
public $locationFinished;
public $longitude;
public $latitude;
public $deviceModel;
public $deviceStatus;
public $id;
public $name;
public $deviceClass;
// These values only recently appeared in Apple's JSON response.
// Their final names will probably change to something other than
// 'a' and 'b'.
public $chargingStatus; // location->a
public $batteryLevel; // location->b
}
@gvanrijn

This comment has been minimized.

Copy link

commented Dec 18, 2014

Nice! Works as before. Thx!! What was the issue?

@jhonmicheal

This comment has been minimized.

Copy link

commented Nov 13, 2015

where is the login page

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.