-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0f6a537
Showing
16 changed files
with
1,197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/vendor/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# agora-token-php | ||
Agora token generation library for PHP | ||
|
||
As Agora support declined my feature request to do that, had to make Agora Tools for PHP repository folder available as a package, installable with Composer. | ||
|
||
https://github.com/AgoraIO/Tools/tree/master/DynamicKey/AgoraDynamicKey/php/src | ||
|
||
ISC license is not confirmed, but inherited from agora-chat npm package: | ||
|
||
https://www.npmjs.com/package/agora-chat | ||
|
||
Update files script: | ||
``` | ||
rm -rf ./src | ||
svn export https://github.com/AgoraIO/Tools/trunk/DynamicKey/AgoraDynamicKey/php/src | ||
cd ./src | ||
sed -i 's/<?php/<?php\n\nnamespace BoogieFromZk\\AgoraToken;/' * | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"name": "boogiefromzk/agora-token", | ||
"description": "Intended to make Agora Tools for PHP repository folder as a package installable with Composer.", | ||
"autoload": { | ||
"psr-4": { | ||
"BoogieFromZk\\AgoraToken\\": "src/" | ||
} | ||
}, | ||
"require": {}, | ||
"license": "ISC" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
<?php | ||
|
||
namespace BoogieFromZk\AgoraToken; | ||
|
||
class Message | ||
{ | ||
public $salt; | ||
public $ts; | ||
public $privileges; | ||
public function __construct() | ||
{ | ||
$this->salt = rand(0, 100000); | ||
|
||
$date = new DateTime("now", new DateTimeZone('UTC')); | ||
$this->ts = $date->getTimestamp() + 24 * 3600; | ||
|
||
$this->privileges = array(); | ||
} | ||
|
||
public function packContent() | ||
{ | ||
$buffer = unpack("C*", pack("V", $this->salt)); | ||
$buffer = array_merge($buffer, unpack("C*", pack("V", $this->ts))); | ||
$buffer = array_merge($buffer, unpack("C*", pack("v", sizeof($this->privileges)))); | ||
foreach ($this->privileges as $key => $value) { | ||
$buffer = array_merge($buffer, unpack("C*", pack("v", $key))); | ||
$buffer = array_merge($buffer, unpack("C*", pack("V", $value))); | ||
} | ||
return $buffer; | ||
} | ||
|
||
public function unpackContent($msg) | ||
{ | ||
$pos = 0; | ||
$salt = unpack("V", substr($msg, $pos, 4))[1]; | ||
$pos += 4; | ||
$ts = unpack("V", substr($msg, $pos, 4))[1]; | ||
$pos += 4; | ||
$size = unpack("v", substr($msg, $pos, 2))[1]; | ||
$pos += 2; | ||
|
||
$privileges = array(); | ||
for ($i = 0; $i < $size; $i++) { | ||
$key = unpack("v", substr($msg, $pos, 2)); | ||
$pos += 2; | ||
$value = unpack("V", substr($msg, $pos, 4)); | ||
$pos += 4; | ||
$privileges[$key[1]] = $value[1]; | ||
} | ||
$this->salt = $salt; | ||
$this->ts = $ts; | ||
$this->privileges = $privileges; | ||
} | ||
} | ||
|
||
class AccessToken | ||
{ | ||
const Privileges = array( | ||
"kJoinChannel" => 1, | ||
"kPublishAudioStream" => 2, | ||
"kPublishVideoStream" => 3, | ||
"kPublishDataStream" => 4, | ||
"kRtmLogin" => 1000, | ||
); | ||
|
||
public $appID, $appCertificate, $channelName, $uid; | ||
public $message; | ||
|
||
function __construct() | ||
{ | ||
$this->message = new Message(); | ||
} | ||
|
||
function setUid($uid) | ||
{ | ||
if ($uid === 0) { | ||
$this->uid = ""; | ||
} else { | ||
$this->uid = $uid . ''; | ||
} | ||
} | ||
|
||
function is_nonempty_string($name, $str) | ||
{ | ||
if (is_string($str) && $str !== "") { | ||
return true; | ||
} | ||
echo $name . " check failed, should be a non-empty string"; | ||
return false; | ||
} | ||
|
||
static function init($appID, $appCertificate, $channelName, $uid) | ||
{ | ||
$accessToken = new AccessToken(); | ||
|
||
if (!$accessToken->is_nonempty_string("appID", $appID) || | ||
!$accessToken->is_nonempty_string("appCertificate", $appCertificate) || | ||
!$accessToken->is_nonempty_string("channelName", $channelName)) { | ||
return null; | ||
} | ||
|
||
$accessToken->appID = $appID; | ||
$accessToken->appCertificate = $appCertificate; | ||
$accessToken->channelName = $channelName; | ||
|
||
$accessToken->setUid($uid); | ||
$accessToken->message = new Message(); | ||
return $accessToken; | ||
} | ||
|
||
static function initWithToken($token, $appCertificate, $channel, $uid) | ||
{ | ||
$accessToken = new AccessToken(); | ||
if (!$accessToken->extract($token, $appCertificate, $channel, $uid)) { | ||
return null; | ||
} | ||
return $accessToken; | ||
} | ||
|
||
function addPrivilege($key, $expireTimestamp) | ||
{ | ||
$this->message->privileges[$key] = $expireTimestamp; | ||
return $this; | ||
} | ||
|
||
function extract($token, $appCertificate, $channelName, $uid) | ||
{ | ||
$ver_len = 3; | ||
$appid_len = 32; | ||
$version = substr($token, 0, $ver_len); | ||
if ($version !== "006") { | ||
echo 'invalid version ' . $version; | ||
return false; | ||
} | ||
|
||
if (!$this->is_nonempty_string("token", $token) || | ||
!$this->is_nonempty_string("appCertificate", $appCertificate) || | ||
!$this->is_nonempty_string("channelName", $channelName)) { | ||
return false; | ||
} | ||
|
||
$appid = substr($token, $ver_len, $appid_len); | ||
$content = (base64_decode(substr($token, $ver_len + $appid_len, strlen($token) - ($ver_len + $appid_len)))); | ||
|
||
$pos = 0; | ||
$len = unpack("v", $content . substr($pos, 2))[1]; | ||
$pos += 2; | ||
$sig = substr($content, $pos, $len); | ||
$pos += $len; | ||
$crc_channel = unpack("V", substr($content, $pos, 4))[1]; | ||
$pos += 4; | ||
$crc_uid = unpack("V", substr($content, $pos, 4))[1]; | ||
$pos += 4; | ||
$msgLen = unpack("v", substr($content, $pos, 2))[1]; | ||
$pos += 2; | ||
$msg = substr($content, $pos, $msgLen); | ||
|
||
$this->appID = $appid; | ||
$message = new Message(); | ||
$message->unpackContent($msg); | ||
$this->message = $message; | ||
|
||
//non reversable values | ||
$this->appCertificate = $appCertificate; | ||
$this->channelName = $channelName; | ||
$this->setUid($uid); | ||
return true; | ||
} | ||
|
||
function build() | ||
{ | ||
$msg = $this->message->packContent(); | ||
$val = array_merge(unpack("C*", $this->appID), unpack("C*", $this->channelName), unpack("C*", $this->uid), $msg); | ||
|
||
$sig = hash_hmac('sha256', implode(array_map("chr", $val)), $this->appCertificate, true); | ||
|
||
$crc_channel_name = crc32($this->channelName) & 0xffffffff; | ||
$crc_uid = crc32($this->uid) & 0xffffffff; | ||
|
||
$content = array_merge(unpack("C*", packString($sig)), unpack("C*", pack("V", $crc_channel_name)), unpack("C*", pack("V", $crc_uid)), unpack("C*", pack("v", count($msg))), $msg); | ||
$version = "006"; | ||
$ret = $version . $this->appID . base64_encode(implode(array_map("chr", $content))); | ||
return $ret; | ||
} | ||
} | ||
|
||
function packString($value) | ||
{ | ||
return pack("v", strlen($value)) . $value; | ||
} |
Oops, something went wrong.