diff --git a/README.md b/README.md index 3f2eede..a99cfc3 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ How to use Pretty simple: -``` +```php require_once('snaphax/snaphax.php'); $opts = array(); @@ -64,7 +64,7 @@ in the HTTP calls). This involved me paging through Fiddler, trying to generate SHA-256 hashes seemingly at random, tearing my heart out, and weeping openly. -Their system is a bit unusual: it AES-256 hashes two input values separately, +Their system is a bit unusual: it SHA-256 hashes two input values separately, using a secret key contained in the binary, and then uses a fixed pattern string to pull bytes from one or the other. The final composition of the two is used in HTTP requests. Why not just append the values pre-hash? The security @@ -88,10 +88,6 @@ The TODO list is almost endless at this point: - DOCS!!! - Figure out the /device call - what's this do? also device_id in /login resp - Syncing (to mark snaps as seen) -- Image/video uploading -- Friend list maintenance -- Port to Javascript (probably via Node + NPM since their API doesn't seem to - support JSONP) - Add support for PHP composer - Test framework diff --git a/snaphax.php b/snaphax.php index e3f8933..608e2cb 100644 --- a/snaphax.php +++ b/snaphax.php @@ -74,8 +74,40 @@ function login() { !empty($out['auth_token'])) { $this->auth_token = $out['auth_token']; } + if ( is_array($out) && !empty($out['username']) ) { + $this->options['username'] = $out['username']; + } return $out; } + function friend($action, $friend, $display=NULL) { + // Action can be "add", "delete", or "display" + // "add" adds the friend + // "delete" removes the friend + // "display" changes the display name of the friend to the value specifed by $display + + if (!$this->auth_token) { + throw new Exception('no auth token'); + } + $ts = $this->api->time(); + $url = "/ph/friend"; + $request = array( + 'timestamp' => $ts, + 'action' => $action, + 'username' => $this->options['username'], + 'friend' => $friend + ); + if($action == 'display') { + if(is_null($display)) { + throw new Exception('Please specify the displayname'); + } + $request['display'] = $display; + } + + $result = $this->api->postCall($url, $request, $this->auth_token, $ts); + $this->api->debug('modified user', $result); + + return $result; + } function fetch($id) { if (!$this->auth_token) { throw new Exception('no auth token'); @@ -120,7 +152,8 @@ function upload($file_data, $type, $recipients, $time=8) { $this->api->debug('upload snap data', $file_data); $file_data_encrypted = $this->api->encrypt($file_data); $this->api->debug('upload snap data encrypted', $file_data_encrypted); - file_put_contents('/tmp/blah.jpg', $file_data_encrypted); + $tempname = tempnam('/tmp/', 'jpg'); + file_put_contents($tempname, $file_data_encrypted); $result = $this->api->postCall( '/ph/upload', array( @@ -128,7 +161,7 @@ function upload($file_data, $type, $recipients, $time=8) { 'timestamp' => $ts, 'type' => $type, // 'data' => urlencode($file_data_encrypted).'; filename="file"', - 'data' => '@/tmp/blah.jpg;filename=file', + 'data' => "@$tempname;filename=data", 'media_id' => $media_id ), $this->auth_token, @@ -136,6 +169,7 @@ function upload($file_data, $type, $recipients, $time=8) { 0, array("Content-type: multipart/form-data") ); + unlink($tempname); $this->api->debug('upload result', $result); foreach ($recipients as $recipient) { @@ -192,13 +226,22 @@ function isValidBlobHeader($header) { else return false; } + + function pkcs5pad($data) { + // Block size is 16 bytes + $needed_padding = 16 - strlen($data) % 16; + if ($needed_padding == 0) { + $needed_padding = 16; + } + return $data . str_repeat(chr($needed_padding), $needed_padding); + } function decrypt($data) { - return mcrypt_decrypt('rijndael-128', $this->options['blob_enc_key'], $data, 'ecb'); + return mcrypt_decrypt('rijndael-128', $this->options['blob_enc_key'], SnaphaxApi::pkcs5pad($data), 'ecb'); } function encrypt($data) { - return mcrypt_encrypt('rijndael-128', $this->options['blob_enc_key'], $data, 'ecb'); + return mcrypt_encrypt('rijndael-128', $this->options['blob_enc_key'], SnaphaxApi::pkcs5pad($data), 'ecb'); } public function postCall($endpoint, $post_data, $param1, $param2, $json=1, $headers=false) {