Merge pull request #1 from danog/analysis-zdjEEJ

Applied fixes from StyleCI
This commit is contained in:
Daniil Gentili 2016-07-14 15:18:13 +02:00 committed by GitHub
commit 42e8d105d9
19 changed files with 1966 additions and 1516 deletions

View File

@ -18,7 +18,8 @@
* Comments, Questions? Contact the author at cody [at] wshost [dot] net * Comments, Questions? Contact the author at cody [at] wshost [dot] net
*/ */
class AES { class AES
{
// The number of 32-bit words comprising the plaintext and columns comrising the state matrix of an AES cipher. // The number of 32-bit words comprising the plaintext and columns comrising the state matrix of an AES cipher.
private static $Nb = 4; private static $Nb = 4;
// The number of 32-bit words comprising the cipher key in this AES cipher. // The number of 32-bit words comprising the cipher key in this AES cipher.
@ -27,7 +28,7 @@ class AES {
private $Nr; private $Nr;
// The S-Box substitution table. // The S-Box substitution table.
private static $sBox = array( private static $sBox = [
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
@ -59,11 +60,11 @@ class AES {
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
); ];
// The inverse S-Box substitution table. // The inverse S-Box substitution table.
private static $invSBox = array( private static $invSBox = [
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
@ -95,11 +96,11 @@ class AES {
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
); ];
// Log table based on 0xe5 // Log table based on 0xe5
private static $ltable = array( private static $ltable = [
0x00, 0xff, 0xc8, 0x08, 0x91, 0x10, 0xd0, 0x36, 0x00, 0xff, 0xc8, 0x08, 0x91, 0x10, 0xd0, 0x36,
0x5a, 0x3e, 0xd8, 0x43, 0x99, 0x77, 0xfe, 0x18, 0x5a, 0x3e, 0xd8, 0x43, 0x99, 0x77, 0xfe, 0x18,
0x23, 0x20, 0x07, 0x70, 0xa1, 0x6c, 0x0c, 0x7f, 0x23, 0x20, 0x07, 0x70, 0xa1, 0x6c, 0x0c, 0x7f,
@ -131,11 +132,11 @@ class AES {
0x22, 0x88, 0x94, 0xce, 0x19, 0x01, 0x71, 0x4c, 0x22, 0x88, 0x94, 0xce, 0x19, 0x01, 0x71, 0x4c,
0xa5, 0xe3, 0xc5, 0x31, 0xbb, 0xcc, 0x1f, 0x2d, 0xa5, 0xe3, 0xc5, 0x31, 0xbb, 0xcc, 0x1f, 0x2d,
0x3b, 0x52, 0x6f, 0xf6, 0x2e, 0x89, 0xf7, 0xc0, 0x3b, 0x52, 0x6f, 0xf6, 0x2e, 0x89, 0xf7, 0xc0,
0x68, 0x1b, 0x64, 0x04, 0x06, 0xbf, 0x83, 0x38 0x68, 0x1b, 0x64, 0x04, 0x06, 0xbf, 0x83, 0x38,
); ];
// Inverse log table // Inverse log table
private static $atable = array( private static $atable = [
0x01, 0xe5, 0x4c, 0xb5, 0xfb, 0x9f, 0xfc, 0x12, 0x01, 0xe5, 0x4c, 0xb5, 0xfb, 0x9f, 0xfc, 0x12,
0x03, 0x34, 0xd4, 0xc4, 0x16, 0xba, 0x1f, 0x36, 0x03, 0x34, 0xd4, 0xc4, 0x16, 0xba, 0x1f, 0x36,
0x05, 0x5c, 0x67, 0x57, 0x3a, 0xd5, 0x21, 0x5a, 0x05, 0x5c, 0x67, 0x57, 0x3a, 0xd5, 0x21, 0x5a,
@ -167,8 +168,8 @@ class AES {
0x1e, 0xd3, 0x49, 0xe9, 0x9c, 0xc8, 0xc6, 0xc7, 0x1e, 0xd3, 0x49, 0xe9, 0x9c, 0xc8, 0xc6, 0xc7,
0x22, 0x6e, 0xdb, 0x20, 0xbf, 0x43, 0x51, 0x52, 0x22, 0x6e, 0xdb, 0x20, 0xbf, 0x43, 0x51, 0x52,
0x66, 0xb2, 0x76, 0x60, 0xda, 0xc5, 0xf3, 0xf6, 0x66, 0xb2, 0x76, 0x60, 0xda, 0xc5, 0xf3, 0xf6,
0xaa, 0xcd, 0x9a, 0xa0, 0x75, 0x54, 0x0e, 0x01 0xaa, 0xcd, 0x9a, 0xa0, 0x75, 0x54, 0x0e, 0x01,
); ];
// The key schedule in this AES cipher. // The key schedule in this AES cipher.
private $w; private $w;
@ -180,16 +181,18 @@ class AES {
/** constructs an AES cipher using a specific key. /** constructs an AES cipher using a specific key.
*/ */
public function __construct($z) { public function __construct($z)
$this->Nk = strlen($z)/4; {
$this->Nk = strlen($z) / 4;
$this->Nr = $this->Nk + self::$Nb + 2; $this->Nr = $this->Nk + self::$Nb + 2;
if ($this->Nk != 4 && $this->Nk != 6 && $this->Nk != 8) if ($this->Nk != 4 && $this->Nk != 6 && $this->Nk != 8) {
die("Key is " . ($this->Nk*32) . " bits long. *not* 128, 192, or 256."); die('Key is '.($this->Nk * 32).' bits long. *not* 128, 192, or 256.');
}
$this->Nr = $this->Nk+self::$Nb+2; $this->Nr = $this->Nk + self::$Nb + 2;
$this->w = array(); // Nb*(Nr+1) 32-bit words $this->w = []; // Nb*(Nr+1) 32-bit words
$this->s = array(array()); // 2-D array of Nb colums and 4 rows $this->s = [[]]; // 2-D array of Nb colums and 4 rows
$this->KeyExpansion($z); // places expanded key in w $this->KeyExpansion($z); // places expanded key in w
} }
@ -201,23 +204,25 @@ class AES {
* encryptBlock() function directly, as the amount of time required * encryptBlock() function directly, as the amount of time required
* to encrypt is linear to the size of the ciphertext. * to encrypt is linear to the size of the ciphertext.
**/ **/
public function encrypt($x) { public function encrypt($x)
$t = ""; // 16-byte block {
$y = ""; // returned cipher text; $t = ''; // 16-byte block
$y = ''; // returned cipher text;
// put a 16-byte block into t // put a 16-byte block into t
$xsize = strlen($x); $xsize = strlen($x);
for ($i=0; $i<$xsize; $i+=16) { for ($i = 0; $i < $xsize; $i += 16) {
for ($j=0; $j<16; $j++) { for ($j = 0; $j < 16; $j++) {
if (($i+$j)<$xsize) { if (($i + $j) < $xsize) {
$t[$j] = $x[$i+$j]; $t[$j] = $x[$i + $j];
} } else {
else
$t[$j] = chr(0); $t[$j] = chr(0);
} }
}
$y .= $this->encryptBlock($t); $y .= $this->encryptBlock($t);
} }
return $y; return $y;
} }
@ -228,21 +233,24 @@ class AES {
* decryptBlock() function directly, as the amount of time required * decryptBlock() function directly, as the amount of time required
* to decrypt is linear to the size of the ciphertext. * to decrypt is linear to the size of the ciphertext.
**/ **/
public function decrypt($y) { public function decrypt($y)
$t = ""; // 16-byte block {
$x = ""; // returned plain text; $t = ''; // 16-byte block
$x = ''; // returned plain text;
// put a 16-byte block into t // put a 16-byte block into t
$ysize = strlen($y); $ysize = strlen($y);
for ($i=0; $i<$ysize; $i+=16) { for ($i = 0; $i < $ysize; $i += 16) {
for ($j=0; $j<16; $j++) { for ($j = 0; $j < 16; $j++) {
if (($i+$j)<$ysize) if (($i + $j) < $ysize) {
$t[$j] = $y[$i+$j]; $t[$j] = $y[$i + $j];
else } else {
$t[$j] = chr(0); $t[$j] = chr(0);
} }
}
$x .= $this->decryptBlock($t); $x .= $this->decryptBlock($t);
} }
return $x; return $x;
} }
@ -250,19 +258,20 @@ class AES {
* @params 16-byte plaintext string * @params 16-byte plaintext string
* @returns 16-byte ciphertext string * @returns 16-byte ciphertext string
**/ **/
public function encryptBlock($x) { public function encryptBlock($x)
$y = ""; // 16-byte string {
$y = ''; // 16-byte string
// place input x into the initial state matrix in column order // place input x into the initial state matrix in column order
for ($i=0; $i<4*self::$Nb; $i++) { for ($i = 0; $i < 4 * self::$Nb; $i++) {
// we want integerger division for the second index // we want integerger division for the second index
$this->s[$i%4][($i-$i%self::$Nb)/self::$Nb] = ord($x[$i]); $this->s[$i % 4][($i - $i % self::$Nb) / self::$Nb] = ord($x[$i]);
} }
// add round key // add round key
$this->addRoundKey(0); $this->addRoundKey(0);
for ($i=1; $i<$this->Nr; $i++) { for ($i = 1; $i < $this->Nr; $i++) {
// substitute bytes // substitute bytes
$this->subBytes(); $this->subBytes();
@ -286,8 +295,10 @@ class AES {
$this->addRoundKey($i); $this->addRoundKey($i);
// place state matrix s into y in column order // place state matrix s into y in column order
for ($i=0; $i<4*self::$Nb; $i++) for ($i = 0; $i < 4 * self::$Nb; $i++) {
$y .= chr($this->s[$i%4][($i-$i%self::$Nb)/self::$Nb]); $y .= chr($this->s[$i % 4][($i - $i % self::$Nb) / self::$Nb]);
}
return $y; return $y;
} }
@ -295,17 +306,19 @@ class AES {
* @params 16-byte ciphertext string * @params 16-byte ciphertext string
* @returns 16-byte plaintext string * @returns 16-byte plaintext string
**/ **/
public function decryptBlock($y) { public function decryptBlock($y)
$x = ""; // 16-byte string {
$x = ''; // 16-byte string
// place input y into the initial state matrix in column order // place input y into the initial state matrix in column order
for ($i=0; $i<4*self::$Nb; $i++) for ($i = 0; $i < 4 * self::$Nb; $i++) {
$this->s[$i%4][($i-$i%self::$Nb)/self::$Nb] = ord($y[$i]); $this->s[$i % 4][($i - $i % self::$Nb) / self::$Nb] = ord($y[$i]);
}
// add round key // add round key
$this->addRoundKey($this->Nr); $this->addRoundKey($this->Nr);
for ($i=$this->Nr-1; $i>0; $i--) { for ($i = $this->Nr - 1; $i > 0; $i--) {
// inverse shift rows // inverse shift rows
$this->invShiftRows(); $this->invShiftRows();
@ -329,15 +342,16 @@ class AES {
$this->addRoundKey($i); $this->addRoundKey($i);
// place state matrix s into x in column order // place state matrix s into x in column order
for ($i=0; $i<4*self::$Nb; $i++) { for ($i = 0; $i < 4 * self::$Nb; $i++) {
// Used to remove filled null characters. // Used to remove filled null characters.
$x .= ($this->s[$i%4][($i-$i%self::$Nb)/self::$Nb] == chr(0) ? "" : chr($this->s[$i%4][($i-$i%self::$Nb)/self::$Nb])); $x .= ($this->s[$i % 4][($i - $i % self::$Nb) / self::$Nb] == chr(0) ? '' : chr($this->s[$i % 4][($i - $i % self::$Nb) / self::$Nb]));
} }
return $x; return $x;
} }
public function __destruct() { public function __destruct()
{
unset($this->w); unset($this->w);
unset($this->s); unset($this->s);
} }
@ -345,9 +359,10 @@ class AES {
/** makes a big key out of a small one /** makes a big key out of a small one
* @returns void * @returns void
**/ **/
private function KeyExpansion($z) { private function KeyExpansion($z)
{
// Rcon is the round constant // Rcon is the round constant
static $Rcon = array( static $Rcon = [
0x00000000, 0x00000000,
0x01000000, 0x01000000,
0x02000000, 0x02000000,
@ -364,35 +379,36 @@ class AES {
0xab000000, 0xab000000,
0x4d000000, 0x4d000000,
0x9a000000, 0x9a000000,
0x2f000000 0x2f000000,
); ];
$temp = 0; // temporary 32-bit word $temp = 0; // temporary 32-bit word
// the first Nk words of w are the cipher key z // the first Nk words of w are the cipher key z
for ($i=0; $i<$this->Nk; $i++) { for ($i = 0; $i < $this->Nk; $i++) {
$this->w[$i] = 0; $this->w[$i] = 0;
// fill an entire word of expanded key w // fill an entire word of expanded key w
// by pushing 4 bytes into the w[i] word // by pushing 4 bytes into the w[i] word
$this->w[$i] = ord($z[4*$i]); // add a byte in $this->w[$i] = ord($z[4 * $i]); // add a byte in
$this->w[$i] <<= 8; // make room for the next byte $this->w[$i] <<= 8; // make room for the next byte
$this->w[$i] += ord($z[4*$i+1]); $this->w[$i] += ord($z[4 * $i + 1]);
$this->w[$i] <<= 8; $this->w[$i] <<= 8;
$this->w[$i] += ord($z[4*$i+2]); $this->w[$i] += ord($z[4 * $i + 2]);
$this->w[$i] <<= 8; $this->w[$i] <<= 8;
$this->w[$i] += ord($z[4*$i+3]); $this->w[$i] += ord($z[4 * $i + 3]);
} }
for (; $i<self::$Nb*($this->Nr+1); $i++) { for (; $i < self::$Nb * ($this->Nr + 1); $i++) {
$temp = $this->w[$i-1]; $temp = $this->w[$i - 1];
if ($i%$this->Nk == 0) if ($i % $this->Nk == 0) {
$temp = $this->subWord($this->rotWord($temp)) ^ $Rcon[$i/$this->Nk]; $temp = $this->subWord($this->rotWord($temp)) ^ $Rcon[$i / $this->Nk];
else if ($this->Nk > 6 && $i%$this->Nk == 4) } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
$temp = $this->subWord($temp); $temp = $this->subWord($temp);
}
$this->w[$i] = $this->w[$i-$this->Nk] ^ $temp; $this->w[$i] = $this->w[$i - $this->Nk] ^ $temp;
self::make32BitWord($this->w[$i]); self::make32BitWord($this->w[$i]);
} }
@ -401,13 +417,14 @@ class AES {
/** adds the key schedule for a round to a state matrix. /** adds the key schedule for a round to a state matrix.
* @returns void * @returns void
**/ **/
private function addRoundKey($round) { private function addRoundKey($round)
$temp = ""; {
$temp = '';
for ($i=0; $i<4; $i++) { for ($i = 0; $i < 4; $i++) {
for ($j=0; $j<self::$Nb; $j++) { for ($j = 0; $j < self::$Nb; $j++) {
// place the i-th byte of the j-th word from expanded key w into temp // place the i-th byte of the j-th word from expanded key w into temp
$temp = $this->w[$round*self::$Nb+$j] >> (3-$i)*8; $temp = $this->w[$round * self::$Nb + $j] >> (3 - $i) * 8;
// Cast temp from a 32-bit word into an 8-bit byte. // Cast temp from a 32-bit word into an 8-bit byte.
$temp %= 256; $temp %= 256;
// Can't do unsigned shifts, so we need to make this temp positive // Can't do unsigned shifts, so we need to make this temp positive
@ -421,52 +438,65 @@ class AES {
/** unmixes each column of a state matrix. /** unmixes each column of a state matrix.
* @returns void * @returns void
**/ **/
private function invMixColumns() { private function invMixColumns()
$s0 = $s1 = $s2 = $s3= ''; {
$s0 = $s1 = $s2 = $s3 = '';
// There are Nb columns // There are Nb columns
for ($i=0; $i<self::$Nb; $i++) { for ($i = 0; $i < self::$Nb; $i++) {
$s0 = $this->s[0][$i]; $s1 = $this->s[1][$i]; $s2 = $this->s[2][$i]; $s3 = $this->s[3][$i]; $s0 = $this->s[0][$i];
$s1 = $this->s[1][$i];
$s2 = $this->s[2][$i];
$s3 = $this->s[3][$i];
$this->s[0][$i] = $this->mult(0x0e, $s0) ^ $this->mult(0x0b, $s1) ^ $this->mult(0x0d, $s2) ^ $this->mult(0x09, $s3); $this->s[0][$i] = $this->mult(0x0e, $s0) ^ $this->mult(0x0b, $s1) ^ $this->mult(0x0d, $s2) ^ $this->mult(0x09, $s3);
$this->s[1][$i] = $this->mult(0x09, $s0) ^ $this->mult(0x0e, $s1) ^ $this->mult(0x0b, $s2) ^ $this->mult(0x0d, $s3); $this->s[1][$i] = $this->mult(0x09, $s0) ^ $this->mult(0x0e, $s1) ^ $this->mult(0x0b, $s2) ^ $this->mult(0x0d, $s3);
$this->s[2][$i] = $this->mult(0x0d, $s0) ^ $this->mult(0x09, $s1) ^ $this->mult(0x0e, $s2) ^ $this->mult(0x0b, $s3); $this->s[2][$i] = $this->mult(0x0d, $s0) ^ $this->mult(0x09, $s1) ^ $this->mult(0x0e, $s2) ^ $this->mult(0x0b, $s3);
$this->s[3][$i] = $this->mult(0x0b, $s0) ^ $this->mult(0x0d, $s1) ^ $this->mult(0x09, $s2) ^ $this->mult(0x0e, $s3); $this->s[3][$i] = $this->mult(0x0b, $s0) ^ $this->mult(0x0d, $s1) ^ $this->mult(0x09, $s2) ^ $this->mult(0x0e, $s3);
} }
} }
/** applies an inverse cyclic shift to the last 3 rows of a state matrix. /** applies an inverse cyclic shift to the last 3 rows of a state matrix.
* @returns void * @returns void
**/ **/
private function invShiftRows() { private function invShiftRows()
$temp = ""; {
for ($i=1; $i<4; $i++) { $temp = '';
for ($j=0; $j<self::$Nb; $j++) for ($i = 1; $i < 4; $i++) {
$temp[($i+$j)%self::$Nb] = $this->s[$i][$j]; for ($j = 0; $j < self::$Nb; $j++) {
for ($j=0; $j<self::$Nb; $j++) $temp[($i + $j) % self::$Nb] = $this->s[$i][$j];
}
for ($j = 0; $j < self::$Nb; $j++) {
$this->s[$i][$j] = $temp[$j]; $this->s[$i][$j] = $temp[$j];
} }
} }
}
/** applies inverse S-Box substitution to each byte of a state matrix. /** applies inverse S-Box substitution to each byte of a state matrix.
* @returns void * @returns void
**/ **/
private function invSubBytes() { private function invSubBytes()
for ($i=0; $i<4; $i++) {
for ($j=0; $j<self::$Nb; $j++) for ($i = 0; $i < 4; $i++) {
for ($j = 0; $j < self::$Nb; $j++) {
$this->s[$i][$j] = self::$invSBox[$this->s[$i][$j]]; $this->s[$i][$j] = self::$invSBox[$this->s[$i][$j]];
} }
}
}
/** mixes each column of a state matrix. /** mixes each column of a state matrix.
* @returns void * @returns void
**/ **/
private function mixColumns() { private function mixColumns()
$s0 = $s1 = $s2 = $s3= ''; {
$s0 = $s1 = $s2 = $s3 = '';
// There are Nb columns // There are Nb columns
for ($i=0; $i<self::$Nb; $i++) { for ($i = 0; $i < self::$Nb; $i++) {
$s0 = $this->s[0][$i]; $s1 = $this->s[1][$i]; $s2 = $this->s[2][$i]; $s3 = $this->s[3][$i]; $s0 = $this->s[0][$i];
$s1 = $this->s[1][$i];
$s2 = $this->s[2][$i];
$s3 = $this->s[3][$i];
$this->s[0][$i] = $this->mult(0x02, $s0) ^ $this->mult(0x03, $s1) ^ $this->mult(0x01, $s2) ^ $this->mult(0x01, $s3); $this->s[0][$i] = $this->mult(0x02, $s0) ^ $this->mult(0x03, $s1) ^ $this->mult(0x01, $s2) ^ $this->mult(0x01, $s3);
$this->s[1][$i] = $this->mult(0x01, $s0) ^ $this->mult(0x02, $s1) ^ $this->mult(0x03, $s2) ^ $this->mult(0x01, $s3); $this->s[1][$i] = $this->mult(0x01, $s0) ^ $this->mult(0x02, $s1) ^ $this->mult(0x03, $s2) ^ $this->mult(0x01, $s3);
@ -478,41 +508,49 @@ class AES {
/** applies a cyclic shift to the last 3 rows of a state matrix. /** applies a cyclic shift to the last 3 rows of a state matrix.
* @returns void * @returns void
**/ **/
private function shiftRows() { private function shiftRows()
$temp = ""; {
for ($i=1; $i<4; $i++) { $temp = '';
for ($j=0; $j<self::$Nb; $j++) for ($i = 1; $i < 4; $i++) {
$temp[$j] = $this->s[$i][($j+$i)%self::$Nb]; for ($j = 0; $j < self::$Nb; $j++) {
for ($j=0; $j<self::$Nb; $j++) $temp[$j] = $this->s[$i][($j + $i) % self::$Nb];
}
for ($j = 0; $j < self::$Nb; $j++) {
$this->s[$i][$j] = $temp[$j]; $this->s[$i][$j] = $temp[$j];
} }
} }
}
/** applies S-Box substitution to each byte of a state matrix. /** applies S-Box substitution to each byte of a state matrix.
* @returns void * @returns void
**/ **/
private function subBytes() { private function subBytes()
{
for ($i=0; $i<4; $i++) { for ($i = 0; $i < 4; $i++) {
for ($j=0; $j<self::$Nb; $j++) for ($j = 0; $j < self::$Nb; $j++) {
$this->s[$i][$j] = self::$sBox[$this->s[$i][$j]]; $this->s[$i][$j] = self::$sBox[$this->s[$i][$j]];
} }
} }
}
/** multiplies two polynomials a(x), b(x) in GF(2^8) modulo the irreducible polynomial m(x) = x^8+x^4+x^3+x+1 /** multiplies two polynomials a(x), b(x) in GF(2^8) modulo the irreducible polynomial m(x) = x^8+x^4+x^3+x+1
* @returns 8-bit value * @returns 8-bit value
**/ **/
private static function mult($a, $b) { private static function mult($a, $b)
{
$sum = self::$ltable[$a] + self::$ltable[$b]; $sum = self::$ltable[$a] + self::$ltable[$b];
$sum %= 255; $sum %= 255;
// Get the antilog // Get the antilog
$sum = self::$atable[$sum]; $sum = self::$atable[$sum];
return ($a == 0 ? 0 : ($b == 0 ? 0 : $sum));
return $a == 0 ? 0 : ($b == 0 ? 0 : $sum);
} }
/** applies a cyclic permutation to a 4-byte word. /** applies a cyclic permutation to a 4-byte word.
* @returns 32-bit int * @returns 32-bit int
**/ **/
private static function rotWord($w) { private static function rotWord($w)
{
$temp = $w >> 24; // put the first 8-bits into temp $temp = $w >> 24; // put the first 8-bits into temp
$w <<= 8; // make room for temp to fill the lower end of the word $w <<= 8; // make room for temp to fill the lower end of the word
self::make32BitWord($w); self::make32BitWord($w);
@ -526,10 +564,11 @@ class AES {
/** applies S-box substitution to each byte of a 4-byte word. /** applies S-box substitution to each byte of a 4-byte word.
* @returns 32-bit int * @returns 32-bit int
**/ **/
private static function subWord($w) { private static function subWord($w)
{
$temp = 0; $temp = 0;
// loop through 4 bytes of a word // loop through 4 bytes of a word
for ($i=0; $i<4; $i++) { for ($i = 0; $i < 4; $i++) {
$temp = $w >> 24; // put the first 8-bits into temp $temp = $w >> 24; // put the first 8-bits into temp
// Can't do unsigned shifts, so we need to make this temp positive // Can't do unsigned shifts, so we need to make this temp positive
$temp = ($temp < 0 ? (256 + $temp) : $temp); $temp = ($temp < 0 ? (256 + $temp) : $temp);
@ -546,9 +585,9 @@ class AES {
/** reduces a 64-bit word to a 32-bit word /** reduces a 64-bit word to a 32-bit word
* @returns void * @returns void
**/ **/
private static function make32BitWord(&$w) { private static function make32BitWord(&$w)
{
// Reduce this 64-bit word to 32-bits on 64-bit machines // Reduce this 64-bit word to 32-bits on 64-bit machines
$w &= 0x00000000FFFFFFFF; $w &= 0x00000000FFFFFFFF;
} }
} }
?>

108
TL.php
View File

@ -1,11 +1,14 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once 'libpy2php.php';
$__author__ = 'agrigoryev'; $__author__ = 'agrigoryev';
require_once ('os.php'); require_once 'os.php';
class TlConstructor { class TlConstructor
function __construct($json_dict) { {
$this->id = (int)$json_dict['id']; public function __construct($json_dict)
{
$this->id = (int) $json_dict['id'];
$this->type = $json_dict['type']; $this->type = $json_dict['type'];
$this->predicate = $json_dict['predicate']; $this->predicate = $json_dict['predicate'];
$this->params = []; $this->params = [];
@ -13,10 +16,10 @@ class TlConstructor {
if (($param['type'] == 'Vector<long>')) { if (($param['type'] == 'Vector<long>')) {
$param['type'] = 'Vector t'; $param['type'] = 'Vector t';
$param['subtype'] = 'long'; $param['subtype'] = 'long';
} else if (($param['type'] == 'vector<%Message>')) { } elseif (($param['type'] == 'vector<%Message>')) {
$param['type'] = 'vector'; $param['type'] = 'vector';
$param['subtype'] = 'message'; $param['subtype'] = 'message';
} else if (($param['type'] == 'vector<future_salt>')) { } elseif (($param['type'] == 'vector<future_salt>')) {
$param['type'] = 'vector'; $param['type'] = 'vector';
$param['subtype'] = 'future_salt'; $param['subtype'] = 'future_salt';
} else { } else {
@ -26,22 +29,28 @@ class TlConstructor {
} }
} }
} }
class TlMethod { class TlMethod
function __construct($json_dict) { {
$this->id = (int)$json_dict['id']; public function __construct($json_dict)
{
$this->id = (int) $json_dict['id'];
$this->type = $json_dict['type']; $this->type = $json_dict['type'];
$this->method = $json_dict['method']; $this->method = $json_dict['method'];
$this->params = $json_dict['params']; $this->params = $json_dict['params'];
} }
} }
class TLObject extends ArrayObject { class TLObject extends ArrayObject
function __construct($tl_elem) { {
public function __construct($tl_elem)
{
parent::__construct(); parent::__construct();
$this->name = $tl_elem->predicate; $this->name = $tl_elem->predicate;
} }
} }
class TL { class TL
function __construct($filename) { {
public function __construct($filename)
{
$TL_dict = json_decode(file_get_contents($filename), true); $TL_dict = json_decode(file_get_contents($filename), true);
$this->constructors = $TL_dict['constructors']; $this->constructors = $TL_dict['constructors'];
$this->constructor_id = []; $this->constructor_id = [];
@ -61,83 +70,89 @@ class TL {
} }
$this->struct = new \danog\PHP\Struct(); $this->struct = new \danog\PHP\Struct();
} }
function serialize_obj($type_, $kwargs) {
$bytes_io = fopen("php://memory", "rw+b"); public function serialize_obj($type_, $kwargs)
if(isset($this->constructor_type[$type_])) {
$tl_constructor = $this->constructor_type[$type_];
}
else
{ {
$bytes_io = fopen('php://memory', 'rw+b');
if (isset($this->constructor_type[$type_])) {
$tl_constructor = $this->constructor_type[$type_];
} else {
throw new Exception(sprintf('Could not extract type: %s', $type_)); throw new Exception(sprintf('Could not extract type: %s', $type_));
} }
fwrite($bytes_io, $this->struct->pack('<i', $tl_constructor->id)); fwrite($bytes_io, $this->struct->pack('<i', $tl_constructor->id));
foreach ($tl_constructor->params as $arg) { foreach ($tl_constructor->params as $arg) {
$this->serialize_param($bytes_io, $arg['type'], $kwargs[$arg['name']]); $this->serialize_param($bytes_io, $arg['type'], $kwargs[$arg['name']]);
} }
return fread_all($bytes_io); return fread_all($bytes_io);
} }
function serialize_method($type_, $kwargs) {
$bytes_io = fopen("php://memory", "rw+b"); public function serialize_method($type_, $kwargs)
if(isset($this->method_name[$type_])) {
$tl_method = $this->method_name[$type_];
}
else
{ {
$bytes_io = fopen('php://memory', 'rw+b');
if (isset($this->method_name[$type_])) {
$tl_method = $this->method_name[$type_];
} else {
throw new Exception(sprintf('Could not extract type: %s', $type_)); throw new Exception(sprintf('Could not extract type: %s', $type_));
} }
fwrite($bytes_io, $this->struct->pack('<i', $tl_method->id)); fwrite($bytes_io, $this->struct->pack('<i', $tl_method->id));
foreach ($tl_method->params as $arg) { foreach ($tl_method->params as $arg) {
$this->serialize_param($bytes_io, $arg['type'], $kwargs[$arg['name']]); $this->serialize_param($bytes_io, $arg['type'], $kwargs[$arg['name']]);
} }
return fread_all($bytes_io); return fread_all($bytes_io);
} }
function serialize_param($bytes_io, $type_, $value) {
public function serialize_param($bytes_io, $type_, $value)
{
if (($type_ == 'int')) { if (($type_ == 'int')) {
assert(is_numeric($value)); assert(is_numeric($value));
assert(strlen(decbin($value)) <= 32); assert(strlen(decbin($value)) <= 32);
fwrite($bytes_io, $this->struct->pack('<i', $value)); fwrite($bytes_io, $this->struct->pack('<i', $value));
} else if (($type_ == 'long')) { } elseif (($type_ == 'long')) {
assert(is_numeric($value)); assert(is_numeric($value));
fwrite($bytes_io, $this->struct->pack('<q', $value)); fwrite($bytes_io, $this->struct->pack('<q', $value));
} else if (in_array($type_, ['int128', 'int256'])) { } elseif (in_array($type_, ['int128', 'int256'])) {
assert(is_string($value)); assert(is_string($value));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
} else if ($type_ == 'string' || $type_ == 'bytes') { } elseif ($type_ == 'string' || $type_ == 'bytes') {
$l = len($value); $l = len($value);
if (($l < 254)) { if (($l < 254)) {
fwrite($bytes_io, $this->struct->pack('<b', $l)); fwrite($bytes_io, $this->struct->pack('<b', $l));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
fwrite($bytes_io, pack("@".((-$l - 1) % 4))); fwrite($bytes_io, pack('@'.((-$l - 1) % 4)));
} else { } else {
fwrite($bytes_io, string2bin('\xfe')); fwrite($bytes_io, string2bin('\xfe'));
fwrite($bytes_io, substr($this->struct->pack('<i', $l), null, 3)); fwrite($bytes_io, substr($this->struct->pack('<i', $l), null, 3));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
fwrite($bytes_io, pack("@".(-$l % 4))); fwrite($bytes_io, pack('@'.(-$l % 4)));
} }
} }
} }
/** /**
* :type bytes_io: io.BytesIO object * :type bytes_io: io.BytesIO object.
*/ */
function deserialize(&$bytes_io, $type_ = null, $subtype = null) { public function deserialize(&$bytes_io, $type_ = null, $subtype = null)
{
assert(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream'); assert(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream');
if (($type_ == 'int')) { if (($type_ == 'int')) {
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0]; $x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
} else if (($type_ == '#')) { } elseif (($type_ == '#')) {
$x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0]; $x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0];
} else if (($type_ == 'long')) { } elseif (($type_ == 'long')) {
$x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0]; $x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0];
} else if (($type_ == 'double')) { } elseif (($type_ == 'double')) {
$x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0]; $x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0];
} else if (($type_ == 'int128')) { } elseif (($type_ == 'int128')) {
$x = fread($bytes_io, 16); $x = fread($bytes_io, 16);
} else if (($type_ == 'int256')) { } elseif (($type_ == 'int256')) {
$x = fread($bytes_io, 32); $x = fread($bytes_io, 32);
} else if (($type_ == 'string') || ($type_ == 'bytes')) { } elseif (($type_ == 'string') || ($type_ == 'bytes')) {
$l = $this->struct->unpack('<C', fread($bytes_io, 1)) [0]; $l = $this->struct->unpack('<C', fread($bytes_io, 1)) [0];
assert($l <= 254); assert($l <= 254);
if (($l == 254)) { if (($l == 254)) {
$long_len = $this->struct->unpack('<I', fread($bytes_io, 3) . string2bin('\x00')) [0]; $long_len = $this->struct->unpack('<I', fread($bytes_io, 3).string2bin('\x00')) [0];
$x = fread($bytes_io, $long_len); $x = fread($bytes_io, $long_len);
fread($bytes_io, (-$long_len % 4)); fread($bytes_io, (-$long_len % 4));
} else { } else {
@ -145,19 +160,19 @@ class TL {
fread($bytes_io, (($l + 1) % 4)); fread($bytes_io, (($l + 1) % 4));
} }
assert(is_string($x)); assert(is_string($x));
} else if (($type_ == 'vector')) { } elseif (($type_ == 'vector')) {
assert($subtype != null); assert($subtype != null);
$count = $this->struct->unpack('<l', substr($bytes_io, 4)) [0]; $count = $this->struct->unpack('<l', substr($bytes_io, 4)) [0];
$x = []; $x = [];
foreach( pyjslib_range($count) as $i ) { foreach (pyjslib_range($count) as $i) {
$x[] = deserialize($bytes_io, $subtype); $x[] = deserialize($bytes_io, $subtype);
} }
} else { } else {
if(isset($this->constructor_type[$type_])) { if (isset($this->constructor_type[$type_])) {
$tl_elem = $this->constructor_type[$type_]; $tl_elem = $this->constructor_type[$type_];
} else { } else {
$i = $this->struct->unpack('<i', fread($bytes_io, 4)) [0]; $i = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
if(isset($this->constructor_id[$i])) { if (isset($this->constructor_id[$i])) {
$tl_elem = $this->constructor_id[$i]; $tl_elem = $this->constructor_id[$i];
} else { } else {
throw new Exception(sprintf('Could not extract type: %s', $type_)); throw new Exception(sprintf('Could not extract type: %s', $type_));
@ -174,6 +189,7 @@ class TL {
} }
} }
} }
return $x; return $x;
} }
} }

View File

@ -1,4 +1,5 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once 'libpy2php.php';
$__all__ = ['Chat', 'User', 'Message', 'Contact']; $__all__ = ['Chat', 'User', 'Message', 'Contact'];

View File

@ -1,11 +1,16 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
class Chat { require_once 'libpy2php.php';
function __construct() { class chat
{
public function __construct()
{
$this->_users = []; $this->_users = [];
} }
function add_user($user) {
$this->_users+= $user; public function add_user($user)
{
$this->_users += $user;
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
class Contact { require_once 'libpy2php.php';
class contact
{
} }

View File

@ -1,43 +1,51 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('os.php'); require_once 'libpy2php.php';
class File { require_once 'os.php';
function __construct($path) { class file
{
public function __construct($path)
{
$this->_path = $path; $this->_path = $path;
} }
/** /**
* truncates the file and create new with :param bytes. * truncates the file and create new with :param bytes.
* :return number of bytes written * :return number of bytes written.
*/ */
function write_bytes($bytes) { public function write_bytes($bytes)
{
// py2php.fixme "with" unsupported. // py2php.fixme "with" unsupported.
} }
/** /**
* read the file as bytes. :return b'' on file not exist * read the file as bytes. :return b'' on file not exist.
*/ */
function read_bytes() { public function read_bytes()
{
if (!(new exists($this->_path))) { if (!(new exists($this->_path))) {
return ''; return '';
} }
// py2php.fixme "with" unsupported. // py2php.fixme "with" unsupported.
}
}
/** /**
* tries to open with os default viewer * tries to open with os default viewer.
*/ */
function open() { public function open()
new call((os::name == 'nt') ? 'cmd /c start "" "' . $this->_path . '"' : [platform::startswith('darwin') ? 'open' : 'xdg-open', $this->_path]); {
new call((os::name == 'nt') ? 'cmd /c start "" "'.$this->_path.'"' : [platform::startswith('darwin') ? 'open' : 'xdg-open', $this->_path]);
} }
/** /**
* try to remove the file * try to remove the file.
*/ */
function remove() { public function remove()
{
try { try {
os::remove($this->_path); os::remove($this->_path);
} } catch (FileNotFoundError $e) {
catch(FileNotFoundError $e) {
} }
} }
} }

View File

@ -1,6 +1,8 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('crypt.php'); require_once 'libpy2php.php';
class Message { require_once 'crypt.php';
class message
{
} }

View File

@ -1,280 +1,373 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('os.php'); require_once 'libpy2php.php';
class TelepyShell { require_once 'os.php';
class TelepyShell
{
public $intro = 'Welcome to telepy interactive shell. Type help or ? for help. public $intro = 'Welcome to telepy interactive shell. Type help or ? for help.
'; ';
public $prompt = '>'; public $prompt = '>';
function preloop() {
require_once ('classes/telepy.php'); public function preloop()
{
require_once 'classes/telepy.php';
$this->_telepy = new Telepy(); $this->_telepy = new Telepy();
} }
function precmd($line) {
public function precmd($line)
{
$line = $line->lstrip(); $line = $line->lstrip();
$blank_pos = $line->find(' '); $blank_pos = $line->find(' ');
if (($blank_pos < 0)) { if (($blank_pos < 0)) {
return $line->lower(); return $line->lower();
} }
return array_slice($line, null, $blank_pos)->lower() . ' ' . array_slice($line, ($blank_pos + 1), null);
return array_slice($line, null, $blank_pos)->lower().' '.array_slice($line, ($blank_pos + 1), null);
} }
function completedefault(...$ignored) {
public function completedefault(...$ignored)
{
pyjslib_printnl($ignored); pyjslib_printnl($ignored);
} }
function complete($text, $state) {
public function complete($text, $state)
{
$this->super()->complete($text, $state); $this->super()->complete($text, $state);
pyjslib_printnl('completing'); pyjslib_printnl('completing');
} }
/** /**
* shell <command-line> * shell <command-line>
* lets you use external shell. !<command-line> for short-hand. * lets you use external shell. !<command-line> for short-hand.
*/ */
function do_shell($line) { public function do_shell($line)
{
pyjslib_printnl(os::popen($line)->read()); pyjslib_printnl(os::popen($line)->read());
} }
/** /**
* msg <peer> * msg <peer>
* sends message to this peer * sends message to this peer.
*/ */
function do_msg($arg) { public function do_msg($arg)
{
} }
/** /**
* fwd <user> <msg-no> * fwd <user> <msg-no>
* forward message to user. You can see message numbers starting client with -N * forward message to user. You can see message numbers starting client with -N.
*/ */
function do_fwd($arg) { public function do_fwd($arg)
{
} }
/** /**
* chat_with_peer <peer> * chat_with_peer <peer>
* starts one on one chat session with this peer. /exit or /quit to end this mode. * starts one on one chat session with this peer. /exit or /quit to end this mode.
*/ */
function do_chat_with_peer($arg) { public function do_chat_with_peer($arg)
{
} }
/** /**
* add_contact <phone-number> <first-name> <last-name> * add_contact <phone-number> <first-name> <last-name>
* tries to add contact to contact-list by phone * tries to add contact to contact-list by phone.
*/ */
function do_add_contact($arg) { public function do_add_contact($arg)
{
} }
/** /**
* rename_contact <user> <first-name> <last-name> * rename_contact <user> <first-name> <last-name>
* tries to rename contact. If you have another device it will be a fight * tries to rename contact. If you have another device it will be a fight.
*/ */
function do_rename_contact($arg) { public function do_rename_contact($arg)
{
} }
/** /**
* mark_read <peer> * mark_read <peer>
* mark read all received messages with peer * mark read all received messages with peer.
*/ */
function do_mark_read($arg) { public function do_mark_read($arg)
{
} }
/** /**
* delete_msg <msg-no> * delete_msg <msg-no>
* deletes message (not completly, though) * deletes message (not completly, though).
*/ */
function do_delete_msg($arg) { public function do_delete_msg($arg)
{
} }
/** /**
* restore_msg <msg-no> * restore_msg <msg-no>
* restores delete message. Impossible for secret chats. Only possible short time (one hour, I think) after deletion * restores delete message. Impossible for secret chats. Only possible short time (one hour, I think) after deletion.
*/ */
function do_restore_msg($arg) { public function do_restore_msg($arg)
{
} }
/** /**
* send_photo <peer> <photo-file-name> * send_photo <peer> <photo-file-name>
* sends photo to peer * sends photo to peer.
*/ */
function do_send_photo($arg) { public function do_send_photo($arg)
{
} }
/** /**
* send_video <peer> <video-file-name> * send_video <peer> <video-file-name>
* sends video to peer * sends video to peer.
*/ */
function do_send_video($arg) { public function do_send_video($arg)
{
} }
/** /**
* send_text <peer> <text-file-name> * send_text <peer> <text-file-name>
* sends text file as plain messages * sends text file as plain messages.
*/ */
function do_send_text($arg) { public function do_send_text($arg)
{
} }
/** /**
* load_photo <msg-no> * load_photo <msg-no>
* loads photo to download dir * loads photo to download dir.
*/ */
function do_load_photo($arg) { public function do_load_photo($arg)
{
} }
/** /**
* load_video <msg-no> * load_video <msg-no>
* loads video to download dir * loads video to download dir.
*/ */
function do_load_video($arg) { public function do_load_video($arg)
{
} }
/** /**
* load_video_thumb <msg-no> * load_video_thumb <msg-no>
* loads video thumbnail to download dir * loads video thumbnail to download dir.
*/ */
function do_load_video_thumb($arg) { public function do_load_video_thumb($arg)
{
} }
/** /**
* load_audio <msg-no> * load_audio <msg-no>
* loads audio to download dir * loads audio to download dir.
*/ */
function do_load_audio($arg) { public function do_load_audio($arg)
{
} }
/** /**
* load_document <msg-no> * load_document <msg-no>
* loads document to download dir * loads document to download dir.
*/ */
function do_load_document($arg) { public function do_load_document($arg)
{
} }
/** /**
* load_document_thumb <msg-no> * load_document_thumb <msg-no>
* loads document thumbnail to download dir * loads document thumbnail to download dir.
*/ */
function do_load_document_thumb($arg) { public function do_load_document_thumb($arg)
{
} }
/** /**
* view_photo <msg-no> * view_photo <msg-no>
* loads photo/video to download dir and starts system default viewer * loads photo/video to download dir and starts system default viewer.
*/ */
function do_view_photo($arg) { public function do_view_photo($arg)
{
} }
/** /**
* view_video <msg-no> * view_video <msg-no>.
*/ */
function do_view_video($arg) { public function do_view_video($arg)
{
} }
/** /**
* view_video_thumb <msg-no> * view_video_thumb <msg-no>.
*/ */
function do_view_video_thumb($arg) { public function do_view_video_thumb($arg)
{
} }
/** /**
* view_audio <msg-no> * view_audio <msg-no>.
*/ */
function do_view_audio($arg) { public function do_view_audio($arg)
{
} }
/** /**
* view_document <msg-no> * view_document <msg-no>.
*/ */
function do_view_document($arg) { public function do_view_document($arg)
{
} }
/** /**
* view_document_thumb <msg-no> * view_document_thumb <msg-no>.
*/ */
function do_view_document_thumb($arg) { public function do_view_document_thumb($arg)
{
} }
/** /**
* fwd_media <msg-no> * fwd_media <msg-no>
* send media in your message. Use this to prevent sharing info about author of media (though, it is possible to determine user_id from media itself, it is not possible get access_hash of this user) * send media in your message. Use this to prevent sharing info about author of media (though, it is possible to determine user_id from media itself, it is not possible get access_hash of this user).
*/ */
function do_fwd_media($arg) { public function do_fwd_media($arg)
{
} }
/** /**
* set_profile_photo <photo-file-name> * set_profile_photo <photo-file-name>
* sets userpic. Photo should be square, or server will cut biggest central square part * sets userpic. Photo should be square, or server will cut biggest central square part.
*/ */
function do_set_profile_photo($arg) { public function do_set_profile_photo($arg)
{
} }
/** /**
* chat_info <chat> * chat_info <chat>
* prints info about chat * prints info about chat.
*/ */
function do_chat_info($arg) { public function do_chat_info($arg)
{
$arg = $arg->split(); $arg = $arg->split();
if ((count($arg) == 1)) { if ((count($arg) == 1)) {
pyjslib_printnl(['chat_info called with ', $arg[0]]); pyjslib_printnl(['chat_info called with ', $arg[0]]);
} }
} }
/** /**
* chat_add_user <chat> <user> * chat_add_user <chat> <user>
* add user to chat * add user to chat.
*/ */
function do_chat_add_user($arg) { public function do_chat_add_user($arg)
{
pyjslib_printnl($arg); pyjslib_printnl($arg);
} }
/** /**
* chat_del_user <chat> <user> * chat_del_user <chat> <user>
* remove user from chat * remove user from chat.
*/ */
function do_chat_del_user($arg) { public function do_chat_del_user($arg)
{
} }
/** /**
* chat_rename <chat> <new-name> * chat_rename <chat> <new-name>
* rename chat room * rename chat room.
*/ */
function do_chat_rename($arg) { public function do_chat_rename($arg)
{
$arg = $arg->split(); $arg = $arg->split();
} }
/** /**
* create_group_chat <chat topic> <user1> <user2> <user3> ... * create_group_chat <chat topic> <user1> <user2> <user3> ...
* creates a groupchat with users, use chat_add_user to add more users * creates a groupchat with users, use chat_add_user to add more users.
*/ */
function do_create_group_chat($chat_topic, $user1, $user2, $user3) { public function do_create_group_chat($chat_topic, $user1, $user2, $user3)
{
pyjslib_printnl($chat_topic); pyjslib_printnl($chat_topic);
pyjslib_printnl([$user1, $user2, $user3]); pyjslib_printnl([$user1, $user2, $user3]);
} }
/** /**
* chat_set_photo <chat> <photo-file-name> * chat_set_photo <chat> <photo-file-name>
* sets group chat photo. Same limits as for profile photos. * sets group chat photo. Same limits as for profile photos.
*/ */
function do_chat_set_photo($chat, $photo) { public function do_chat_set_photo($chat, $photo)
{
} }
/** /**
* search <peer> <pattern> * search <peer> <pattern>
* searches pattern in messages with peer * searches pattern in messages with peer.
*/ */
function do_search($pattern) { public function do_search($pattern)
{
} }
/** /**
* global_search <pattern> * global_search <pattern>
* searches pattern in all messages * searches pattern in all messages.
*/ */
function do_global_search($pattern) { public function do_global_search($pattern)
{
} }
/** /**
* create_secret_chat <user> * create_secret_chat <user>
* creates secret chat with this user * creates secret chat with this user.
*/ */
function do_create_secret_chat($user) { public function do_create_secret_chat($user)
{
} }
/** /**
* visualize_key <secret_chat> * visualize_key <secret_chat>
* prints visualization of encryption key. You should compare it to your partner's one * prints visualization of encryption key. You should compare it to your partner's one.
*/ */
function do_visualize_key($secret_chat) { public function do_visualize_key($secret_chat)
{
} }
/** /**
* set_ttl <secret_chat> <ttl> * set_ttl <secret_chat> <ttl>
* sets ttl to secret chat. Though client does ignore it, client on other end can make use of it * sets ttl to secret chat. Though client does ignore it, client on other end can make use of it.
*/ */
function do_set_ttl($secret_chat, $ttl) { public function do_set_ttl($secret_chat, $ttl)
{
} }
/** /**
* accept_secret_chat <secret_chat> * accept_secret_chat <secret_chat>
* manually accept secret chat (only useful when starting with -E key) * manually accept secret chat (only useful when starting with -E key).
*/ */
function do_accept_secret_chat($secret_chat) { public function do_accept_secret_chat($secret_chat)
{
} }
/** /**
* user_info <user> * user_info <user>
* prints info about user * prints info about user.
*/ */
function do_user_info($user) { public function do_user_info($user)
{
} }
/** /**
* history <peer> [limit] * history <peer> [limit]
* prints history (and marks it as read). Default limit = 40 * prints history (and marks it as read). Default limit = 40.
*/ */
function do_history($peer, $limit = 40) { public function do_history($peer, $limit = 40)
{
if (($peer == '')) { if (($peer == '')) {
pyjslib_printnl('no peer have specified'); pyjslib_printnl('no peer have specified');
return; return;
} }
$args = $peer->split(); $args = $peer->split();
if (!in_array(count($args), [1, 2])) { if (!in_array(count($args), [1, 2])) {
pyjslib_printnl(['not appropriate number of arguments : ', $peer]); pyjslib_printnl(['not appropriate number of arguments : ', $peer]);
return; return;
} }
if ((count($args) == 2)) { if ((count($args) == 2)) {
@ -286,54 +379,70 @@ class TelepyShell {
pyjslib_printnl($peer); pyjslib_printnl($peer);
pyjslib_printnl($limit); pyjslib_printnl($limit);
} }
/** /**
* dialog_list * dialog_list
* prints info about your dialogs * prints info about your dialogs.
*/ */
function do_dialog_list($ignored) { public function do_dialog_list($ignored)
{
} }
/** /**
* contact_list * contact_list
* prints info about users in your contact list * prints info about users in your contact list.
*/ */
function do_contact_list($ignored) { public function do_contact_list($ignored)
{
} }
/** /**
* suggested_contacts * suggested_contacts
* print info about contacts, you have max common friends * print info about contacts, you have max common friends.
*/ */
function do_suggested_contacts($ignored) { public function do_suggested_contacts($ignored)
{
} }
/** /**
* stats * stats
* just for debugging * just for debugging.
*/ */
function do_stats($ignored) { public function do_stats($ignored)
{
} }
/** /**
* export_card * export_card
* print your 'card' that anyone can later use to import your contact * print your 'card' that anyone can later use to import your contact.
*/ */
function do_export_card($card) { public function do_export_card($card)
{
} }
/** /**
* import_card <card> * import_card <card>
* gets user by card. You can write messages to him after that. * gets user by card. You can write messages to him after that.
*/ */
function do_import_card($card) { public function do_import_card($card)
{
} }
/** /**
* quit_force * quit_force
* quit without waiting for query ends * quit without waiting for query ends.
*/ */
function do_quit_force($ignored) { public function do_quit_force($ignored)
{
return true; return true;
} }
/** /**
* quit * quit
* wait for all queries to end then quit * wait for all queries to end then quit.
*/ */
function do_quit($ignored) { public function do_quit($ignored)
{
return true; return true;
} }
} }

View File

@ -1,15 +1,17 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
class Telepy { require_once 'libpy2php.php';
function __construct() { class telepy
{
public function __construct()
{
try { try {
require_once ('configparser.php'); require_once 'configparser.php';
} catch (ImportError $e) {
require_once 'ConfigParser.php';
} }
catch(ImportError $e) { require_once 'mtproto.php';
require_once ('ConfigParser.php');
}
require_once ('mtproto.php');
$this->_config = $configparser->ConfigParser(); $this->_config = $configparser->ConfigParser();
if (!($this->_config->read('credentials'))) { if (!($this->_config->read('credentials'))) {
pyjslib_printnl('File \'credentials\' seems to not exist.'); pyjslib_printnl('File \'credentials\' seems to not exist.');
@ -19,7 +21,7 @@ class Telepy {
$port = $this->_config->getint('App data', 'port'); $port = $this->_config->getint('App data', 'port');
$this->_session = $mtproto->Session($ip, $port); $this->_session = $mtproto->Session($ip, $port);
$this->_session->create_auth_key(); $this->_session->create_auth_key();
$__temp22 = py2php_kwargs_method_call($this->_session, 'method_call', ['get_future_salts'], ["num" => 3]); $__temp22 = py2php_kwargs_method_call($this->_session, 'method_call', ['get_future_salts'], ['num' => 3]);
$this->_salt = $__temp22; $this->_salt = $__temp22;
$future_salts = $__temp22; $future_salts = $__temp22;
} }

View File

@ -1,12 +1,16 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
class User { require_once 'libpy2php.php';
class user
{
public $me = null; public $me = null;
// current connected user // current connected user
public $friends = []; public $friends = [];
// current connected user's friends // current connected user's friends
function __construct($uid) { public function __construct($uid)
{
$this->uid = $uid; $this->uid = $uid;
} }
} }

View File

@ -1,14 +1,20 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('AES.class.php'); require_once 'libpy2php.php';
class crypt { require_once 'AES.class.php';
function ige_encrypt($message, $key, $iv) { class crypt
{
public function ige_encrypt($message, $key, $iv)
{
return _ige($message, $key, $iv, 'encrypt'); return _ige($message, $key, $iv, 'encrypt');
} }
function ige_decrypt($message, $key, $iv) {
public function ige_decrypt($message, $key, $iv)
{
return _ige($message, $key, $iv, 'decrypt'); return _ige($message, $key, $iv, 'decrypt');
} }
/** /**
* Given a key, given an iv, and message * Given a key, given an iv, and message
* do whatever operation asked in the operation field. * do whatever operation asked in the operation field.
@ -17,21 +23,22 @@ class crypt {
* message must be a multiple by 16 bytes (for division in 16 byte blocks) * message must be a multiple by 16 bytes (for division in 16 byte blocks)
* key must be 32 byte * key must be 32 byte
* iv must be 32 byte (it's not internally used in AES 256 ECB, but it's * iv must be 32 byte (it's not internally used in AES 256 ECB, but it's
* needed for IGE) * needed for IGE).
*/ */
function _ige($message, $key, $iv, $operation = 'decrypt') { public function _ige($message, $key, $iv, $operation = 'decrypt')
{
$message = str_split($message); $message = str_split($message);
if ((len($key) != 32)) { if ((len($key) != 32)) {
throw new Exception('key must be 32 bytes long (was ' . len($key) . ' bytes)'); throw new Exception('key must be 32 bytes long (was '.len($key).' bytes)');
} }
if ((len($iv) != 32)) { if ((len($iv) != 32)) {
throw new Exception('iv must be 32 bytes long (was ' . len($iv) . ' bytes)'); throw new Exception('iv must be 32 bytes long (was '.len($iv).' bytes)');
} }
$cipher = new AES($key); $cipher = new AES($key);
$cipher = $cipher->encrypt($iv); $cipher = $cipher->encrypt($iv);
$blocksize = $cipher->block_size; $blocksize = $cipher->block_size;
if ((len($message) % $blocksize) != 0) { if ((len($message) % $blocksize) != 0) {
throw new Exception('message must be a multiple of 16 bytes (try adding ' . (16 - (count($message) % 16)) . ' bytes of padding)'); throw new Exception('message must be a multiple of 16 bytes (try adding '.(16 - (count($message) % 16)).' bytes of padding)');
} }
$ivp = substr($iv, 0, $blocksize - 0); $ivp = substr($iv, 0, $blocksize - 0);
$ivp2 = substr($iv, $blocksize, null); $ivp2 = substr($iv, $blocksize, null);
@ -44,7 +51,7 @@ class crypt {
$outdata = strxor($decrypt_xored, $ivp); $outdata = strxor($decrypt_xored, $ivp);
$ivp = $indata; $ivp = $indata;
$ivp2 = $outdata; $ivp2 = $outdata;
} else if (($operation == 'encrypt')) { } elseif (($operation == 'encrypt')) {
$xored = strxor($indata, $ivp); $xored = strxor($indata, $ivp);
$encrypt_xored = $cipher->encrypt($xored); $encrypt_xored = $cipher->encrypt($xored);
$outdata = strxor($encrypt_xored, $ivp2); $outdata = strxor($encrypt_xored, $ivp2);
@ -55,6 +62,7 @@ class crypt {
} }
$ciphered .= $outdata; $ciphered .= $outdata;
} }
return $ciphered; return $ciphered;
} }
} }

View File

@ -1,21 +1,21 @@
<?php <?php
# Copyright 2006 James Tauber and contributors // Copyright 2006 James Tauber and contributors
# //
# Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
# You may obtain a copy of the License at // You may obtain a copy of the License at
# //
# http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
# //
# Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
# limitations under the License. // limitations under the License.
/** /**
* This call makes three things happen: * This call makes three things happen:.
* *
* 1) a global error handler for php errors that causes an exception to be * 1) a global error handler for php errors that causes an exception to be
* thrown instead of standard php error handling. * thrown instead of standard php error handling.
@ -26,175 +26,182 @@
* 3) error_reporting is set to E_STRICT, so that even notices cause an * 3) error_reporting is set to E_STRICT, so that even notices cause an
* exception to be thrown. This way we are forced to deal with even * exception to be thrown. This way we are forced to deal with even
* the minor issues during development, and hopefully fewer issues * the minor issues during development, and hopefully fewer issues
make it out into the world.
*/ */
require_once( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'strict_mode.php' ); require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'strict_mode.php';
init_strict_mode(); init_strict_mode();
# iteration from Bob Ippolito's Iteration in JavaScript // iteration from Bob Ippolito's Iteration in JavaScript
# pyjs_extend from Kevin Lindsey's Inteheritance Tutorial (http://www.kevlindev.com/tutorials/javascript/inheritance/) // pyjs_extend from Kevin Lindsey's Inteheritance Tutorial (http://www.kevlindev.com/tutorials/javascript/inheritance/)
# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
function pyjslib_isObject($a) {
// type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
function pyjslib_isObject($a)
{
return is_object($a); return is_object($a);
} }
function pyjslib_isFunction($a) { function pyjslib_isFunction($a)
{
return is_function($a); return is_function($a);
} }
function pyjslib_isString($a) { function pyjslib_isString($a)
{
return is_string($a); return is_string($a);
} }
function pyjslib_isNull($a) { function pyjslib_isNull($a)
{
return is_null($a); return is_null($a);
} }
function pyjslib_isArray($a) { function pyjslib_isArray($a)
{
return is_array($a); return is_array($a);
} }
function pyjslib_isUndefined($a) { function pyjslib_isUndefined($a)
{
return !isset($a); return !isset($a);
} }
function pyjslib_isIteratable($a) { function pyjslib_isIteratable($a)
{
return $a instanceof Traversable; return $a instanceof Traversable;
} }
function pyjslib_isNumber($a) { function pyjslib_isNumber($a)
{
return is_numeric($a); return is_numeric($a);
} }
function pyjslib_int($a) { function pyjslib_int($a)
return (int)$a; {
return (int) $a;
} }
function pyjslib_str($val) { function pyjslib_str($val)
return (string)$val; {
return (string) $val;
} }
function pyjslib_del_slice(&$list, $from, $to, $step=1) { function pyjslib_del_slice(&$list, $from, $to, $step = 1)
if( $from <= 0 ) { {
if ($from <= 0) {
$from = 0; $from = 0;
} }
if( $to === null ) { if ($to === null) {
$to = count($list); $to = count($list);
} }
if( $step <= 0 ) { if ($step <= 0) {
$step = 1; $step = 1;
} }
for( $i = $from; $i < $to; $i += $step ) { for ($i = $from; $i < $to; $i += $step) {
unset( $list[$i]); unset($list[$i]);
} }
} }
function pyjslib_array_slice($list, $from, $to, $step=1) { function pyjslib_array_slice($list, $from, $to, $step = 1)
{
$newlist = []; $newlist = [];
if( $from <= 0 ) { if ($from <= 0) {
$from = 0; $from = 0;
} }
if( $to === null ) { if ($to === null) {
$to = count($list); $to = count($list);
} }
if( $step <= 0 ) { if ($step <= 0) {
$step = 1; $step = 1;
} }
for( $i = $from; $i < $to; $i += $step ) { for ($i = $from; $i < $to; $i += $step) {
$newlist[] = $list[$i]; $newlist[] = $list[$i];
} }
return $newlist; return $newlist;
} }
# taken from mochikit: range( [start,] stop[, step] ) // taken from mochikit: range( [start,] stop[, step] )
function pyjslib_range($start, $stop = null, $step = 1) { function pyjslib_range($start, $stop = null, $step = 1)
if( $stop === null ) { {
if ($stop === null) {
$stop = $start; $stop = $start;
$start = 0; $start = 0;
} }
if( $stop <= $start && $step < 0 ) { if ($stop <= $start && $step < 0) {
$arr = range( $stop, $start, -$step ); $arr = range($stop, $start, -$step);
array_pop( $arr ); array_pop($arr);
return array_reverse( $arr, false );
return array_reverse($arr, false);
} }
$arr = range( $start, $stop, $step ); $arr = range($start, $stop, $step);
array_pop( $arr ); array_pop($arr);
return $arr; return $arr;
} }
function pyjslib_filter($callback, $iterable) { function pyjslib_filter($callback, $iterable)
{
$a = []; $a = [];
foreach( $iterable as $item ) { foreach ($iterable as $item) {
if( call_user_func( $callback, $item ) ) { if (call_user_func($callback, $item)) {
$a[] = $item; $a[] = $item;
} }
} }
return $a; return $a;
} }
function pyjslib_globals() { function pyjslib_globals()
{
return $GLOBALS; return $GLOBALS;
} }
function pyjslib_map($callable) { function pyjslib_map($callable)
{
$done = false; $done = false;
$call_cnt = 0; $call_cnt = 0;
$results = []; $results = [];
$params = func_get_args(); $params = func_get_args();
array_shift( $params ); array_shift($params);
while( !$done ) { while (!$done) {
$func_args = []; $func_args = [];
$found = false; $found = false;
for( $i = 0; $i < count($params); $i ++ ) { for ($i = 0; $i < count($params); $i++) {
$func_args[] = @$params[$i][$call_cnt]; $func_args[] = @$params[$i][$call_cnt];
if( count($params[$i]) > $call_cnt + 1 ) { if (count($params[$i]) > $call_cnt + 1) {
$found = true; $found = true;
} }
} }
if( !$found ) { if (!$found) {
$done = true; $done = true;
} }
$results[] = call_user_func_array($callable, $func_args); $results[] = call_user_func_array($callable, $func_args);
$call_cnt ++; $call_cnt++;
} }
return $results; return $results;
} }
function pyjslib_zip() { function pyjslib_zip()
{
$params = func_get_args(); $params = func_get_args();
if (count($params) === 1){ // this case could be probably cleaner if (count($params) === 1) { // this case could be probably cleaner
// single iterable passed // single iterable passed
$result = array(); $result = [];
foreach ($params[0] as $item){ foreach ($params[0] as $item) {
$result[] = array($item); $result[] = [$item];
}; }
return $result; return $result;
}; }
$result = call_user_func_array('array_map',array_merge(array(null),$params)); $result = call_user_func_array('array_map', array_merge([null], $params));
$length = min(array_map('count', $params)); $length = min(array_map('count', $params));
return array_slice($result, 0, $length); return array_slice($result, 0, $length);
} }
@ -203,82 +210,83 @@ function pyjslib_is_assoc($arr)
return array_keys($arr) !== range(0, count($arr) - 1); return array_keys($arr) !== range(0, count($arr) - 1);
} }
function pyjslib_dict($arg=null) { function pyjslib_dict($arg = null)
if( $arg === null ) { {
if ($arg === null) {
return []; return [];
} }
if( pyjslib_is_assoc( $arg )) { if (pyjslib_is_assoc($arg)) {
return $arg; return $arg;
} }
$dict = []; $dict = [];
foreach( $arg as $a ) { foreach ($arg as $a) {
if( count($a) == 2 ) { if (count($a) == 2) {
$dict[$a[0]] = $a[1]; $dict[$a[0]] = $a[1];
} }
} }
return $dict; return $dict;
} }
function pyjslib_printWorker($objs, $nl, $multi_arg, $depth=1) { function pyjslib_printWorker($objs, $nl, $multi_arg, $depth = 1)
{
$buf = ''; $buf = '';
if( is_array( $objs ) && $multi_arg && $depth == 1) { if (is_array($objs) && $multi_arg && $depth == 1) {
$cnt = 0; $cnt = 0;
foreach( $objs as $obj ) { foreach ($objs as $obj) {
if( $cnt ++ > 0 ) { if ($cnt++ > 0) {
$buf .= " "; $buf .= ' ';
} }
$buf .= pyjslib_printWorker( $obj, $nl, $multi_arg, $depth + 1 ); $buf .= pyjslib_printWorker($obj, $nl, $multi_arg, $depth + 1);
} }
} } elseif (is_bool($objs)) {
else if( is_bool( $objs )) { $buf = $objs ? 'True' : 'False';
$buf = $objs ? "True" : "False"; } elseif (is_null($objs)) {
}
else if( is_null( $objs )) {
$buf = 'None'; $buf = 'None';
} } elseif (is_float($objs)) {
else if( is_float( $objs )) { $buf = (int) $objs;
$buf = (int)$objs; } elseif (is_string($objs) && ($multi_arg && $depth > 2 || (!$multi_arg && $depth > 1))) {
}
else if( is_string( $objs ) && ($multi_arg && $depth > 2 || (!$multi_arg && $depth > 1) ) ) {
$buf = "'$objs'"; $buf = "'$objs'";
} } elseif (is_array($objs)) {
elseif( is_array( $objs )) {
$buf = '['; $buf = '[';
$cnt = 0; $cnt = 0;
foreach( $objs as $obj ) { foreach ($objs as $obj) {
$val = pyjslib_printWorker($obj, $nl, false, $depth + 1); $val = pyjslib_printWorker($obj, $nl, false, $depth + 1);
if( $cnt ++ > 0 ) { if ($cnt++ > 0) {
$buf .= ', '; $buf .= ', ';
} }
$buf .= $val; $buf .= $val;
} }
$buf .= "]"; $buf .= ']';
// $buf = '[' . implode( ", ", $objs ) . ']'; // $buf = '[' . implode( ", ", $objs ) . ']';
} } else {
else {
$buf = $objs; $buf = $objs;
} }
if( $depth == 1 && (!strlen($buf) || $buf[strlen($buf)-1] != "\n") ) { if ($depth == 1 && (!strlen($buf) || $buf[strlen($buf) - 1] != "\n")) {
$buf .= $nl ? "\n" : " "; $buf .= $nl ? "\n" : ' ';
} }
return $buf; return $buf;
} }
function pyjslib_repr($obj) { function pyjslib_repr($obj)
{
return pyjslib_printWorker($obj, false, false); return pyjslib_printWorker($obj, false, false);
} }
function pyjslib_print($objs, $multi_arg=false) { function pyjslib_print($objs, $multi_arg = false)
{
echo pyjslib_printWorker($objs, false, $multi_arg); echo pyjslib_printWorker($objs, false, $multi_arg);
} }
function pyjslib_printnl($objs, $multi_arg=false) { function pyjslib_printnl($objs, $multi_arg = false)
{
echo pyjslib_printWorker($objs, true, $multi_arg); echo pyjslib_printWorker($objs, true, $multi_arg);
} }
function py2php_kwargs_function_call($funcname, $ordered, $named) { function py2php_kwargs_function_call($funcname, $ordered, $named)
{
if( $funcname == 'array' || $funcname == 'pyjslib_dict' ) { if ($funcname == 'array' || $funcname == 'pyjslib_dict') {
return $named; return $named;
} }
@ -286,58 +294,62 @@ function py2php_kwargs_function_call($funcname, $ordered, $named) {
$count = 1; $count = 1;
$refFunc = new ReflectionFunction($funcname); $refFunc = new ReflectionFunction($funcname);
foreach( $refFunc->getParameters() as $param ){ foreach ($refFunc->getParameters() as $param) {
if( $param->isVariadic() ) { if ($param->isVariadic()) {
$ordered[$count-1] = $named; $ordered[$count - 1] = $named;
break; break;
} }
//invokes ReflectionParameter::__toString //invokes ReflectionParameter::__toString
if( $count > $num_ordered ) { if ($count > $num_ordered) {
$name = $param->name; $name = $param->name;
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null; $default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
$ordered[] = @$named[$name] ?: $default; $ordered[] = @$named[$name] ?: $default;
} }
$count ++; $count++;
} }
//var_dump($ordered); //var_dump($ordered);
return call_user_func_array($funcname, $ordered); return call_user_func_array($funcname, $ordered);
} }
function py2php_kwargs_method_call( $obj, $method, $ordered, $named ) { function py2php_kwargs_method_call($obj, $method, $ordered, $named)
{
$num_ordered = count($ordered); $num_ordered = count($ordered);
$count = 1; $count = 1;
$refFunc = new ReflectionMethod($obj, $method); $refFunc = new ReflectionMethod($obj, $method);
foreach( $refFunc->getParameters() as $param ){ foreach ($refFunc->getParameters() as $param) {
//invokes ReflectionParameter::__toString //invokes ReflectionParameter::__toString
if( $count > $num_ordered ) { if ($count > $num_ordered) {
$name = $param->name; $name = $param->name;
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null; $default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
$ordered[] = @$named[$name] ?: $default; $ordered[] = @$named[$name] ?: $default;
} }
$count ++; $count++;
} }
$callable = [$obj, $method]; $callable = [$obj, $method];
return call_user_func_array($callable, $ordered); return call_user_func_array($callable, $ordered);
} }
class IOError extends Exception{ class IOError extends Exception
{
} }
class ValueError extends Exception{ class ValueError extends Exception
{
} }
function pyjslib_open( $name, $mode="r", $buffering=null ) { function pyjslib_open($name, $mode = 'r', $buffering = null)
return new pyjslib_file( $name, $mode, $buffering ); {
return new pyjslib_file($name, $mode, $buffering);
} }
class pyjslib_file implements Iterator { class pyjslib_file implements Iterator
{
private $fh = false; private $fh = false;
private $current_line = null; private $current_line = null;
@ -349,138 +361,160 @@ class pyjslib_file implements Iterator {
public $newlines = null; public $newlines = null;
public $softspace = false; public $softspace = false;
function __construct($name_or_fd, $mode="r", $buffering=null) { public function __construct($name_or_fd, $mode = 'r', $buffering = null)
if( is_resource($name_or_fd) ) { {
if (is_resource($name_or_fd)) {
$this->fh = $name_or_fd; $this->fh = $name_or_fd;
$this->closed = false; $this->closed = false;
$meta = stream_get_meta_data( $name_or_df ); $meta = stream_get_meta_data($name_or_df);
$this->mode = $meta['mode']; $this->mode = $meta['mode'];
return; return;
} }
$name = $name_or_fd; $name = $name_or_fd;
try { try {
$this->fh = fopen($name, $mode); $this->fh = fopen($name, $mode);
if( !$this->fh ) { if (!$this->fh) {
throw new Exception("Could not open $name"); throw new Exception("Could not open $name");
} }
$this->closed = false; $this->closed = false;
$this->mode = $mode; $this->mode = $mode;
} } catch (Exception $e) {
catch( Exception $e ) { throw new IOError($e->getMessage(), $e->getCode());
throw new IOError( $e->getMessage(), $e->getCode() );
} }
} }
public function close()
{
function close() { if ($this->fh) {
if( $this->fh ) { fclose($this->fh);
fclose( $this->fh );
$this->fh = null; $this->fh = null;
$this->closed = true; $this->closed = true;
} }
} }
function flush() { public function flush()
if( !$this->fh ) { {
throw new ValueError("File is closed."); if (!$this->fh) {
throw new ValueError('File is closed.');
} }
fflush( $this->fh ); fflush($this->fh);
} }
function fileno() { public function fileno()
if( !$this->fh ) { {
throw new ValueError("File is closed."); if (!$this->fh) {
throw new ValueError('File is closed.');
} }
return $this->fh; return $this->fh;
} }
function isatty() { public function isatty()
if( !$this->fh ) { {
throw new ValueError("File is closed."); if (!$this->fh) {
throw new ValueError('File is closed.');
} }
return posix_isatty( $this->fh );
return posix_isatty($this->fh);
} }
/* --- /* ---
* Begin PHP Iterator implementation * Begin PHP Iterator implementation
* --- * ---
*/ */
function rewind() { public function rewind()
fseek( $this->fh, 0 ); {
fseek($this->fh, 0);
$this->line = 0; $this->line = 0;
} }
function current() { public function current()
if( !$this->current_line ) { {
$this->current_line = fgets( $this->fh ); if (!$this->current_line) {
$this->current_line = fgets($this->fh);
} }
return $this->current_line; return $this->current_line;
} }
function key() { public function key()
{
return $this->line; return $this->line;
} }
function next() { public function next()
{
$this->current(); // ensure current line has been retrieved. $this->current(); // ensure current line has been retrieved.
$this->current_line = fgets( $this->fh ); $this->current_line = fgets($this->fh);
$this->line ++; $this->line++;
return $this->current_line; return $this->current_line;
} }
function valid() { public function valid()
return $this->fh != false && !feof( $this->fh ); {
return $this->fh != false && !feof($this->fh);
} }
/* --- /* ---
* End PHP Iterator implementation * End PHP Iterator implementation
* --- * ---
*/ */
function read($size=null) { public function read($size = null)
if( $size !== null) { {
return fread( $this->fh, $size); if ($size !== null) {
} return fread($this->fh, $size);
return stream_get_contents( $this->fh );
} }
function readline($size=null) { return stream_get_contents($this->fh);
return fgets( $this->fh, $size );
} }
function readlines($sizehint=null) { public function readline($size = null)
{
return fgets($this->fh, $size);
}
public function readlines($sizehint = null)
{
$len = 0; $len = 0;
$lines = array(); $lines = [];
while( $line = fgets( $this->fh ) ) { while ($line = fgets($this->fh)) {
$len += strlen( $line ); $len += strlen($line);
$lines[] = $line; $lines[] = $line;
if( $sizehint && $len >= $sizehint ) { if ($sizehint && $len >= $sizehint) {
break; break;
} }
} }
return $lines; return $lines;
} }
function seek($offset, $whence=SEEK_SET) { public function seek($offset, $whence = SEEK_SET)
return fseek( $this->fh, $offset, $whence); {
return fseek($this->fh, $offset, $whence);
} }
function tell() { public function tell()
{
return ftell($this->fh); return ftell($this->fh);
} }
function truncate( $size ) { public function truncate($size)
$rc = ftruncate( $this->fh, $size ); {
$rc = ftruncate($this->fh, $size);
} }
function write( $str ) { public function write($str)
fwrite( $this->fh, $str ); {
fwrite($this->fh, $str);
} }
function writelines($sequence) { public function writelines($sequence)
foreach($sequence as $line) { {
$this->write( $line ); foreach ($sequence as $line) {
$this->write($line);
} }
} }
} }

View File

@ -1,11 +1,12 @@
<?php <?php
class OSError extends Exception{ class OSError extends Exception
{
} }
class os { class os
{
const F_OK = 0x0001; const F_OK = 0x0001;
const R_OK = 0x0002; const R_OK = 0x0002;
const W_OK = 0x0004; const W_OK = 0x0004;
@ -47,524 +48,636 @@ class os {
public $environ; public $environ;
public $pathconf_names = []; public $pathconf_names = [];
static public function ctermid() { public static function ctermid()
{
return posix_ctermid(); return posix_ctermid();
} }
static public function getegid() { public static function getegid()
{
return posix_getegid(); return posix_getegid();
} }
static public function geteuid() { public static function geteuid()
{
return posix_geteuid(); return posix_geteuid();
} }
static public function getgid() { public static function getgid()
{
return posix_getgid(); return posix_getgid();
} }
static public function getgroups() { public static function getgroups()
{
return posix_getgroups(); return posix_getgroups();
} }
static public function initgroups($username, $gid) { public static function initgroups($username, $gid)
{
return posix_initgroups($username, $gid); return posix_initgroups($username, $gid);
} }
static public function getlogin() { public static function getlogin()
{
return posix_getlogin(); return posix_getlogin();
} }
static public function getpgid() { public static function getpgid()
{
return posix_getpgid(); return posix_getpgid();
} }
static public function getpgrp() { public static function getpgrp()
{
return posix_getpgrp(); return posix_getpgrp();
} }
static public function getpid() { public static function getpid()
{
return posix_getpid(); return posix_getpid();
} }
static public function getresuid() { public static function getresuid()
{
self::_unimplemented(); self::_unimplemented();
} }
static public function getresgid() { public static function getresgid()
{
self::_unimplemented(); self::_unimplemented();
} }
static public function getuid() { public static function getuid()
{
return posix_getuid(); return posix_getuid();
} }
static public function getenv($varname, $value=null) { public static function getenv($varname, $value = null)
{
return getenv($varname, $value); return getenv($varname, $value);
} }
static public function putenv($varname, $value) { public static function putenv($varname, $value)
{
putenv("$varname=$value"); putenv("$varname=$value");
} }
static public function setegid($egid) { public static function setegid($egid)
{
posix_setegid($egid); posix_setegid($egid);
} }
static public function seteuid($euid) { public static function seteuid($euid)
{
posix_seteuid($euid); posix_seteuid($euid);
} }
static public function setgid($gid) { public static function setgid($gid)
{
posix_setgid($gid); posix_setgid($gid);
} }
static public function setgroups($groups) { public static function setgroups($groups)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function setpgrp() { public static function setpgrp()
{
self::_unimplemented(); self::_unimplemented();
} }
static public function setpgid($pid, $pgrp) { public static function setpgid($pid, $pgrp)
{
posix_setpgid($pid, $pgrp); posix_setpgid($pid, $pgrp);
} }
static public function setregid($rgid, $egid) { public static function setregid($rgid, $egid)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function setresgid($rgid, $egid, $sgid) { public static function setresgid($rgid, $egid, $sgid)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function setresuid($ruid, $euid, $suid) { public static function setresuid($ruid, $euid, $suid)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function setreuid($ruid, $euid) { public static function setreuid($ruid, $euid)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function getsid($pid) { public static function getsid($pid)
{
return posix_getsid(); return posix_getsid();
} }
static public function setsid() { public static function setsid()
{
posix_setsid(); posix_setsid();
} }
static public function setuid($uid) { public static function setuid($uid)
{
posix_setuid($uid); posix_setuid($uid);
} }
static public function strerror($code) { public static function strerror($code)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function umask($mask) { public static function umask($mask)
{
umask($mask); umask($mask);
} }
static public function uname() { public static function uname()
{
return posix_uname(); return posix_uname();
} }
static public function unsetenv($varname) { public static function unsetenv($varname)
{
unset($_ENV[$varname]); unset($_ENV[$varname]);
} }
static public function fdopen($fd, $mode=null, $bufsize=null) { public static function fdopen($fd, $mode = null, $bufsize = null)
{
return new pyjslib_file($fd); return new pyjslib_file($fd);
} }
static public function popen($command, $mode=null, $bufsize=null) { public static function popen($command, $mode = null, $bufsize = null)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function tmpfile() { public static function tmpfile()
{
return tmpfile(); return tmpfile();
} }
static public function popen2($cmd, $mode=null, $bufsize=null) { public static function popen2($cmd, $mode = null, $bufsize = null)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function popen3($cmd, $mode=null, $bufsize=null) { public static function popen3($cmd, $mode = null, $bufsize = null)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function popen4($cmd, $mode=null, $bufsize=null) { public static function popen4($cmd, $mode = null, $bufsize = null)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function close($fd) { public static function close($fd)
fclose( $fd ); {
fclose($fd);
} }
static public function closerange($fd_low, $fd_high) { public static function closerange($fd_low, $fd_high)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function dup($fd) { public static function dup($fd)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function dup2($fd) { public static function dup2($fd)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fchmod($fd, $mode) { public static function fchmod($fd, $mode)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fchown($fd, $uid, $gid) { public static function fchown($fd, $uid, $gid)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fdatasync($fd) { public static function fdatasync($fd)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fpathconf($fd, $name) { public static function fpathconf($fd, $name)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fstat($fd) { public static function fstat($fd)
{
$info = fstat($fd); $info = fstat($fd);
$obj = new stdClass; $obj = new stdClass();
foreach($arr as $key => $v) { foreach ($arr as $key => $v) {
$attr = "st_" . $key; $attr = 'st_'.$key;
$obj->$attr = $v; $obj->$attr = $v;
} }
return $obj; return $obj;
} }
static public function fstatvfs($fd) { public static function fstatvfs($fd)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function fsync($fd) { public static function fsync($fd)
{
fsync($fd); fsync($fd);
} }
static public function ftruncate($fd, $length) { public static function ftruncate($fd, $length)
{
ftruncate($fd, $length); ftruncate($fd, $length);
} }
static public function isatty($fd) { public static function isatty($fd)
return posix_isatty( $fd ); {
return posix_isatty($fd);
} }
static public function lseek($fd, $pos, $how) { public static function lseek($fd, $pos, $how)
{
lseek($fd, $pos, $how); lseek($fd, $pos, $how);
} }
static public function open($file, $flags, $mode=0777) { public static function open($file, $flags, $mode = 0777)
{
// todo: define and map flag constants. See list at: // todo: define and map flag constants. See list at:
// https://docs.python.org/2/library/os.html#open-flag-constants // https://docs.python.org/2/library/os.html#open-flag-constants
$fl = ''; $fl = '';
if( $flags & self::O_RDONLY ) { if ($flags & self::O_RDONLY) {
$fl .= 'r'; $fl .= 'r';
} }
if( $flags & self::O_WRONLY ) { if ($flags & self::O_WRONLY) {
$fl .= 'w'; $fl .= 'w';
} }
if( $flags & self::O_RDWR ) { if ($flags & self::O_RDWR) {
$fl .= 'rw'; $fl .= 'rw';
} }
if( $flags & self::O_APPEND ) { if ($flags & self::O_APPEND) {
$fl .= 'a'; $fl .= 'a';
} }
if( $flags & self::O_CREAT ) { if ($flags & self::O_CREAT) {
$fl .= 'c'; $fl .= 'c';
} }
if( $flags & self::O_EXCL ) { if ($flags & self::O_EXCL) {
$fl .= 'x'; $fl .= 'x';
} }
if( $flags & self::O_TRUNC ) { if ($flags & self::O_TRUNC) {
$fl .= 'w'; $fl .= 'w';
} }
return fopen($file, $fl, false ); return fopen($file, $fl, false);
} }
static public function pipe() { public static function pipe()
{
self::_unimplemented(); self::_unimplemented();
} }
static public function read($fd, $n) { public static function read($fd, $n)
return fread( $fd, $n ); {
return fread($fd, $n);
} }
static public function tcgetpgrp($fd) { public static function tcgetpgrp($fd)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function tcsetpgrp($fd, $pg) { public static function tcsetpgrp($fd, $pg)
{
self::_unimplemented(); self::_unimplemented();
} }
static public function ttyname($fd) { public static function ttyname($fd)
{
return posix_ttyname($fd); return posix_ttyname($fd);
} }
static public function write($fd, $str) { public static function write($fd, $str)
return fwrite( $fd, $str ); {
return fwrite($fd, $str);
} }
static function access($path, $mode) { public static function access($path, $mode)
{
return posix_access($path, $mode); return posix_access($path, $mode);
} }
static function chdir($path) { public static function chdir($path)
chdir( $path ); {
chdir($path);
} }
static function fchdir($path) { public static function fchdir($path)
fchdir( $path ); {
fchdir($path);
} }
static function getcwd() { public static function getcwd()
{
return getcwd(); return getcwd();
} }
static function getcwdu() { public static function getcwdu()
{
return getcwd(); return getcwd();
} }
static function chflags($path, $flags) { public static function chflags($path, $flags)
{
self::_unimplemented(); self::_unimplemented();
} }
static function chroot($path) { public static function chroot($path)
{
chroot($path); chroot($path);
} }
static function chmode($path, $mode) { public static function chmode($path, $mode)
{
self::_unimplemented(); self::_unimplemented();
} }
static function chown($path, $uid, $gid) { public static function chown($path, $uid, $gid)
{
chown($path, $uid, $gid); chown($path, $uid, $gid);
} }
static function lchflags($path, $flags) { public static function lchflags($path, $flags)
{
self::_unimplemented(); self::_unimplemented();
} }
static function lchmod($path, $mode) { public static function lchmod($path, $mode)
{
self::_unimplemented(); self::_unimplemented();
} }
static function lchown($path, $uid, $gid) { public static function lchown($path, $uid, $gid)
{
self::_unimplemented(); self::_unimplemented();
} }
static function link($source, $link_name) { public static function link($source, $link_name)
{
link($source, $link_name); link($source, $link_name);
} }
static function listdir($path) { public static function listdir($path)
{
self::_unimplemented(); self::_unimplemented();
} }
static function lstat($path) { public static function lstat($path)
{
self::_unimplemented(); self::_unimplemented();
} }
static function mkfifo($path, $mode=0666) { public static function mkfifo($path, $mode = 0666)
{
posix_mkfifo($path, $mode); posix_mkfifo($path, $mode);
} }
static function mknod($filename, $mode=0666, $device=0) { public static function mknod($filename, $mode = 0666, $device = 0)
return posix_mknod( $filename, $mode ); {
return posix_mknod($filename, $mode);
} }
static function major($path, $flags) { public static function major($path, $flags)
{
self::_unimplemented(); self::_unimplemented();
} }
static function minor($path, $flags) { public static function minor($path, $flags)
{
self::_unimplemented(); self::_unimplemented();
} }
static function makedev($major, $minor) { public static function makedev($major, $minor)
{
self::_unimplemented(); self::_unimplemented();
} }
static function mkdir($path, $mode=0777) { public static function mkdir($path, $mode = 0777)
mkdir($path, $mode, $recursive=false); {
mkdir($path, $mode, $recursive = false);
} }
static function makedirs($path, $mode=0777) { public static function makedirs($path, $mode = 0777)
mkdir($path, $mode, $recursive=true); {
mkdir($path, $mode, $recursive = true);
} }
static function pathconf($path, $name) { public static function pathconf($path, $name)
{
self::_unimplemented(); self::_unimplemented();
} }
static function readlink($path) { public static function readlink($path)
{
return readlink($path); return readlink($path);
} }
static function remove($path) { public static function remove($path)
if( !is_file( $path ) ) { {
if (!is_file($path)) {
throw new OSError("Path is not a file. $path"); throw new OSError("Path is not a file. $path");
} }
try { try {
unlink( $path ); unlink($path);
} } catch (Exception $e) {
catch( Exception $e ) { throw new OSError($e->getMessage(), $e->getCode());
throw new OSError( $e->getMessage(), $e->getCode() );
} }
} }
static function removedirs($path) { public static function removedirs($path)
{
self::_unimplemented(); self::_unimplemented();
} }
static function rename($src, $dst) { public static function rename($src, $dst)
if( is_dir($dst)) { {
if (is_dir($dst)) {
throw new OSError("Destination is a directory. $dst"); throw new OSError("Destination is a directory. $dst");
} }
rename($src, $dst); rename($src, $dst);
} }
static function renames($old, $new) { public static function renames($old, $new)
self::makedirs( dirname($new) ); {
self::makedirs(dirname($new));
self::rename($old, $new); self::rename($old, $new);
} }
static function rmdir($path) { public static function rmdir($path)
{
rmdir($pat); rmdir($pat);
} }
static function stat($path) { public static function stat($path)
{
$arr = stat($path); $arr = stat($path);
if(!$arr) { if (!$arr) {
throw new OSError("Path does not exist. $path"); throw new OSError("Path does not exist. $path");
} }
$obj = new stdClass; $obj = new stdClass();
foreach($arr as $key => $v) { foreach ($arr as $key => $v) {
$attr = "st_" . $key; $attr = 'st_'.$key;
$obj->$attr = $v; $obj->$attr = $v;
} }
return $obj; return $obj;
} }
static function stat_float_times($newvalue=null) { public static function stat_float_times($newvalue = null)
{
self::_unimplemented(); self::_unimplemented();
} }
static function statvfs() { public static function statvfs()
{
self::_unimplemented(); self::_unimplemented();
} }
static function symlink($source, $link_name) { public static function symlink($source, $link_name)
{
symlink($source, $link_name); symlink($source, $link_name);
} }
static function tempnam($dir=null, $prefix='') { public static function tempnam($dir = null, $prefix = '')
if( !$dir ) { {
$dir = sys_get_temp_dir() ; if (!$dir) {
$dir = sys_get_temp_dir();
} }
$name = tempnam($dir, $prefix); $name = tempnam($dir, $prefix);
unlink($name); unlink($name);
return $name; return $name;
} }
static function tmpnam() { public static function tmpnam()
{
return self::tempnam(); return self::tempnam();
} }
static function unlink($path) { public static function unlink($path)
{
unlink($path); unlink($path);
} }
static function utime($path, $times) { public static function utime($path, $times)
{
self::_unimplemented(); self::_unimplemented();
} }
static function walk($top, $topdown=true, $onerror=null, $followlinks=false) { public static function walk($top, $topdown = true, $onerror = null, $followlinks = false)
{
self::_unimplemented(); self::_unimplemented();
} }
/** /**
* Begin Process Management * Begin Process Management.
*/ */
public static function abort()
static function abort() { {
self::_unimplemented(); self::_unimplemented();
} }
static function execl($path, $arg0, $arg1) { public static function execl($path, $arg0, $arg1)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execle($path, $arg0, $arg1, $env) { public static function execle($path, $arg0, $arg1, $env)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execlp($file, $arg0, $arg1) { public static function execlp($file, $arg0, $arg1)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execlpe($file, $arg0, $arg1, $env) { public static function execlpe($file, $arg0, $arg1, $env)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execv($path, $args) { public static function execv($path, $args)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execve($path, $args, $env) { public static function execve($path, $args, $env)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execvp($file, $args) { public static function execvp($file, $args)
{
self::_unimplemented(); self::_unimplemented();
} }
static function execvpe($file, $args, $env) { public static function execvpe($file, $args, $env)
{
self::_unimplemented(); self::_unimplemented();
} }
static function _exit($n) { public static function _exit($n)
{
exit($n); exit($n);
} }
static function fork() { public static function fork()
{
return pcntl_fork(); return pcntl_fork();
} }
static function forkpty() { public static function forkpty()
{
self::_unimplemented(); self::_unimplemented();
} }
static function kill($pid, $sig) { public static function kill($pid, $sig)
{
posix_kill($pid, $sig); posix_kill($pid, $sig);
} }
static function killpg($pgid, $sig) { public static function killpg($pgid, $sig)
{
self::_unimplemented(); self::_unimplemented();
} }
static function nice($increment) { public static function nice($increment)
{
proc_nice($increment); proc_nice($increment);
} }
static function plock($op) { public static function plock($op)
{
self::_unimplemented(); self::_unimplemented();
} }
private static function _unimplemented()
{
private static function _unimplemented() { throw new Exception('Unimplemented. Please consider submitting a patch to py2php project on github.');
throw new Exception( "Unimplemented. Please consider submitting a patch to py2php project on github.");
} }
} }

View File

@ -1,214 +1,251 @@
<?php <?php
require_once(dirname(__FILE__) . '/os.php'); require_once dirname(__FILE__).'/os.php';
/** /**
* A class to emulate python's os.path * A class to emulate python's os.path.
*/ */
class os_path { class os_path
{
const supports_unicode_filenames = true; const supports_unicode_filenames = true;
static function abspath($path) { public static function abspath($path)
{
return self::normpath(self::join(getcwd(), $path)); return self::normpath(self::join(getcwd(), $path));
} }
static function basename($path) { public static function basename($path)
{
// is this right? // is this right?
return basename($path); return basename($path);
} }
static function commonprefix($list) { public static function commonprefix($list)
{
$pl = 0; // common prefix length $pl = 0; // common prefix length
$n = count($list); $n = count($list);
$l = strlen($list[0]); $l = strlen($list[0]);
while ($pl < $l) { while ($pl < $l) {
$c = $list[0][$pl]; $c = $list[0][$pl];
for ($i=1; $i<$n; $i++) { for ($i = 1; $i < $n; $i++) {
if ($list[$i][$pl] !== $c) { if ($list[$i][$pl] !== $c) {
break 2; break 2;
} }
} }
$pl++; $pl++;
} }
return substr($list[0], 0, $pl); return substr($list[0], 0, $pl);
} }
static function dirname($path) { public static function dirname($path)
{
return dirname($path); return dirname($path);
} }
static function exists($path) { public static function exists($path)
{
return file_exists($path); return file_exists($path);
} }
static function lexists($path) { public static function lexists($path)
{
$rc = file_exists($path); $rc = file_exists($path);
if( !$rc && is_link($path) ) { if (!$rc && is_link($path)) {
return true; return true;
} }
return $rc; return $rc;
} }
static function expanduser($path) { public static function expanduser($path)
if( strpos($path, '~') !== false) { {
if (strpos($path, '~') !== false) {
$info = posix_getpwuid(posix_getuid()); $info = posix_getpwuid(posix_getuid());
$path = str_replace('~', $info['dir'], $path); $path = str_replace('~', $info['dir'], $path);
} }
return $path; return $path;
} }
static function expandvars($path) { public static function expandvars($path)
{
$env = count($_ENV) ?: $_SERVER; $env = count($_ENV) ?: $_SERVER;
$map = array(); $map = [];
foreach( $env as $k => $v ) { foreach ($env as $k => $v) {
if( !is_scalar( $v )) { if (!is_scalar($v)) {
continue; continue;
} }
$map['$' . $k] = $v; $map['$'.$k] = $v;
$map['${' . $k . '}'] = $v; $map['${'.$k.'}'] = $v;
} }
return strtr($path, $map); return strtr($path, $map);
} }
static function getatime($path) { public static function getatime($path)
{
try { try {
$rc = fileatime($path); $rc = fileatime($path);
return $rc; return $rc;
} } catch (Exception $e) {
catch( Exception $e ) {
throw new OSError($e->getMessage, $e->getCode()); throw new OSError($e->getMessage, $e->getCode());
} }
} }
static function getmtime($path) { public static function getmtime($path)
{
try { try {
$rc = filemtime($path); $rc = filemtime($path);
return $rc; return $rc;
} } catch (Exception $e) {
catch( Exception $e ) {
throw new OSError($e->getMessage, $e->getCode()); throw new OSError($e->getMessage, $e->getCode());
} }
} }
static function getctime($path) { public static function getctime($path)
{
try { try {
$rc = filectime($path); $rc = filectime($path);
return $rc; return $rc;
} } catch (Exception $e) {
catch( Exception $e ) {
throw new OSError($e->getMessage, $e->getCode()); throw new OSError($e->getMessage, $e->getCode());
} }
} }
static function getsize($path) { public static function getsize($path)
{
try { try {
$rc = filesize($path); $rc = filesize($path);
return $rc; return $rc;
} } catch (Exception $e) {
catch( Exception $e ) {
throw new OSError($e->getMessage, $e->getCode()); throw new OSError($e->getMessage, $e->getCode());
} }
} }
static function isabs($path) { public static function isabs($path)
{
// fixme: implement check for windows. // fixme: implement check for windows.
return $path[0] == '/'; return $path[0] == '/';
} }
static function isfile($path) { public static function isfile($path)
{
return is_file($path); return is_file($path);
} }
static function isdir($path) { public static function isdir($path)
{
return is_dir($path); return is_dir($path);
} }
static function islink($path) { public static function islink($path)
{
return is_link($path); return is_link($path);
} }
static function ismount($path) { public static function ismount($path)
{
self::_unimplemented(); self::_unimplemented();
} }
static function split($path) { public static function split($path)
{
$parts = explode(DIRECTORY_SEPARATOR, $path); $parts = explode(DIRECTORY_SEPARATOR, $path);
$first = implode(DIRECTORY_SEPARATOR, array_slice($parts, 0, count($parts)-1 )); $first = implode(DIRECTORY_SEPARATOR, array_slice($parts, 0, count($parts) - 1));
$last = $parts[count($parts)-1]; $last = $parts[count($parts) - 1];
return array($first, $last);
return [$first, $last];
} }
static function join($path, ...$paths) { public static function join($path, ...$paths)
{
$buf = rtrim($path, '/'); $buf = rtrim($path, '/');
foreach( $paths as $p ) { foreach ($paths as $p) {
$i = 0; $i = 0;
$p = trim( $p, '/'); $p = trim($p, '/');
$buf .= DIRECTORY_SEPARATOR . $p; $buf .= DIRECTORY_SEPARATOR.$p;
} }
return $buf; return $buf;
} }
static function normcase($path) { public static function normcase($path)
{
// fixme: different behavior on windows. // fixme: different behavior on windows.
return $path; return $path;
} }
static function normpath($path) { public static function normpath($path)
{
return realpath($path); return realpath($path);
} }
static function realpath($path) { public static function realpath($path)
{
return realpath($path); return realpath($path);
} }
static function relpath($path, $start) { public static function relpath($path, $start)
{
self::_unimplemented(); self::_unimplemented();
} }
static function samefile($path1, $path2) { public static function samefile($path1, $path2)
{
return fileinode($path1) == fileinode($path2); return fileinode($path1) == fileinode($path2);
} }
static function sameopenfile($fd1, $fd2) { public static function sameopenfile($fd1, $fd2)
$s1 = fstat( $fd1 ); {
$s2 = fstat( $fd2 ); $s1 = fstat($fd1);
$s2 = fstat($fd2);
return $s1['ino'] == $s2['ino']; return $s1['ino'] == $s2['ino'];
} }
static function samestat($stat1, $stat2) { public static function samestat($stat1, $stat2)
{
return $stat1 == $stat2; return $stat1 == $stat2;
} }
static function splitdrive($path) { public static function splitdrive($path)
{
//fixme: implement windows case. //fixme: implement windows case.
return array('', $path); return ['', $path];
} }
static function splitext($path) { public static function splitext($path)
{
$first = $path; $first = $path;
$second = ''; $second = '';
$pos = strrpos( $path, '.'); $pos = strrpos($path, '.');
if( $pos !== false ) { if ($pos !== false) {
$first = substr($path, 0, $pos); $first = substr($path, 0, $pos);
$second = substr($path, $pos); $second = substr($path, $pos);
} }
return array($first, $second); return [$first, $second];
} }
static function splitunc($path) { public static function splitunc($path)
{
self::_unimplemented(); self::_unimplemented();
} }
static function walk($path, $visit, $arg) { public static function walk($path, $visit, $arg)
{
// Note: deprecated in python 3 in favor of os.walk() // Note: deprecated in python 3 in favor of os.walk()
self::_unimplemented(); self::_unimplemented();
} }
private static function _unimplemented() { private static function _unimplemented()
throw new Exception( "Unimplemented. Please consider submitting a patch to py2php project on github."); {
throw new Exception('Unimplemented. Please consider submitting a patch to py2php project on github.');
} }
} }

View File

@ -7,18 +7,18 @@
* It is called in this file; the parent php file(s) should use require_once and do * It is called in this file; the parent php file(s) should use require_once and do
* not need to make any call. * not need to make any call.
*/ */
function init_strict_mode() { function init_strict_mode()
{
// these are safe to call multiple times per process without dups. // these are safe to call multiple times per process without dups.
error_reporting( E_ALL | E_STRICT ); error_reporting(E_ALL | E_STRICT);
restore_strict_error_handler(); restore_strict_error_handler();
restore_strict_exception_handler(); restore_strict_exception_handler();
// register_shutdown_function should only be called once per process to avoid dups. // register_shutdown_function should only be called once per process to avoid dups.
static $called = false; static $called = false;
if( !$called ) { if (!$called) {
register_shutdown_function('shutdown_handler');
register_shutdown_function( "shutdown_handler" );
$called = true; $called = true;
} }
} }
@ -28,19 +28,20 @@ function init_strict_mode() {
* eg by a 3rd party lib. Any error handlers that were registered after * eg by a 3rd party lib. Any error handlers that were registered after
* ours are removed. * ours are removed.
*/ */
function restore_strict_error_handler() { function restore_strict_error_handler()
{
$e_handler_name = function() { $e_handler_name = function () {
$name = set_error_handler('restore_strict_error_handler'); // will never be used. $name = set_error_handler('restore_strict_error_handler'); // will never be used.
restore_error_handler(); restore_error_handler();
return $name; return $name;
}; };
while( !in_array( $e_handler_name(), array( '_global_error_handler', null ) ) ) { while (!in_array($e_handler_name(), ['_global_error_handler', null])) {
restore_error_handler(); restore_error_handler();
} }
if( !$e_handler_name() ) { if (!$e_handler_name()) {
set_error_handler( '_global_error_handler' ); set_error_handler('_global_error_handler');
} }
} }
@ -49,19 +50,20 @@ function restore_strict_error_handler() {
* eg by a 3rd party lib. Any error handlers that were registered after * eg by a 3rd party lib. Any error handlers that were registered after
* ours are removed. * ours are removed.
*/ */
function restore_strict_exception_handler() { function restore_strict_exception_handler()
{
$exc_handler_name = function() { $exc_handler_name = function () {
$name = set_exception_handler('restore_strict_exception_handler'); // will never be used. $name = set_exception_handler('restore_strict_exception_handler'); // will never be used.
restore_exception_handler(); restore_exception_handler();
return $name; return $name;
}; };
while( !in_array( $exc_handler_name(), array( '_global_exception_handler', null ) ) ) { while (!in_array($exc_handler_name(), ['_global_exception_handler', null])) {
restore_exception_handler(); restore_exception_handler();
} }
if( !$exc_handler_name() ) { if (!$exc_handler_name()) {
set_exception_handler( '_global_exception_handler' ); set_exception_handler('_global_exception_handler');
} }
} }
@ -72,7 +74,8 @@ function restore_strict_exception_handler() {
* *
* However, we allow the @operator in the code to override. * However, we allow the @operator in the code to override.
*/ */
function _global_error_handler($errno, $errstr, $errfile, $errline ) { function _global_error_handler($errno, $errstr, $errfile, $errline)
{
/* from php.net /* from php.net
* error_reporting() settings will have no effect and your error handler will * error_reporting() settings will have no effect and your error handler will
@ -80,7 +83,7 @@ function _global_error_handler($errno, $errstr, $errfile, $errline ) {
* error_reporting and act appropriately. Of particular note is that this value will * error_reporting and act appropriately. Of particular note is that this value will
* be 0 if the statement that caused the error was prepended by the @ error-control operator. * be 0 if the statement that caused the error was prepended by the @ error-control operator.
*/ */
if( !error_reporting() ) { if (!error_reporting()) {
return; return;
} }
@ -91,44 +94,45 @@ function _global_error_handler($errno, $errstr, $errfile, $errline ) {
/*** /***
* This exception handler callback will be called for any exceptions that the application code does not catch. * This exception handler callback will be called for any exceptions that the application code does not catch.
*/ */
function _global_exception_handler( $e ) { function _global_exception_handler($e)
$msg = sprintf( "\nUncaught Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString() ); {
while( ( $e = $e->getPrevious() ) ) { $msg = sprintf("\nUncaught Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString());
$msg .= sprintf( "\nPrevious Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString() ); while (($e = $e->getPrevious())) {
$msg .= sprintf("\nPrevious Exception. code: %s, message: %s\n%s : %s\n\nStack Trace:\n%s\n", $e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString());
} }
echo $msg; echo $msg;
// error_log( $msg ); // error_log( $msg );
strict_mode_mail_admin( 'Uncaught exception!', $msg ); strict_mode_mail_admin('Uncaught exception!', $msg);
echo "\n\nNow exiting. Please report this problem to the software author\n\n"; echo "\n\nNow exiting. Please report this problem to the software author\n\n";
exit(1); exit(1);
} }
/** /**
* This shutdown handler callback prints a message and sends email on any PHP fatal error * This shutdown handler callback prints a message and sends email on any PHP fatal error.
*/ */
function shutdown_handler() { function shutdown_handler()
{
$error = error_get_last(); $error = error_get_last();
$ignore = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_STRICT | E_DEPRECATED | E_USER_DEPRECATED; $ignore = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_STRICT | E_DEPRECATED | E_USER_DEPRECATED;
if ( $error && ($error['type'] & $ignore) == 0) { if ($error && ($error['type'] & $ignore) == 0) {
// error keys: type, file, line, message // error keys: type, file, line, message
$msg = "Ouch! Encountered PHP Fatal Error. Shutting down.\n" . print_r( $error, true ); $msg = "Ouch! Encountered PHP Fatal Error. Shutting down.\n".print_r($error, true);
echo $msg; echo $msg;
strict_mode_mail_admin( 'PHP Fatal Error!', $msg ); strict_mode_mail_admin('PHP Fatal Error!', $msg);
} }
} }
/** /**
* email admin if defined * email admin if defined.
*/ */
function strict_mode_mail_admin( $subject, $msg ) { function strict_mode_mail_admin($subject, $msg)
$subject = sprintf( '[%s] [%s] %s [pid: %s]', gethostname(), basename($_SERVER['PHP_SELF']), $subject, getmypid() ); {
if( defined('ALERTS_MAIL_TO') ) { $subject = sprintf('[%s] [%s] %s [pid: %s]', gethostname(), basename($_SERVER['PHP_SELF']), $subject, getmypid());
mail( ALERTS_MAIL_TO, $subject, $msg ); if (defined('ALERTS_MAIL_TO')) {
} mail(ALERTS_MAIL_TO, $subject, $msg);
else { } else {
echo "\nWARNING: ALERTS_MAIL_TO not defined in environment. alert not sent with subject: $subject\n"; echo "\nWARNING: ALERTS_MAIL_TO not defined in environment. alert not sent with subject: $subject\n";
} }
} }

View File

@ -1,25 +1,30 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('os_path.php'); require_once 'libpy2php.php';
require_once ('crypt.php'); require_once 'os_path.php';
require_once ('prime.php'); require_once 'crypt.php';
require_once ('TL.php'); require_once 'prime.php';
require_once ('Struct.php'); require_once 'TL.php';
require_once 'Struct.php';
/** /**
* Function to get hex crc32 * Function to get hex crc32
* :param data: Data to encode * :param data: Data to encode.
*/ */
function newcrc32($data) { function newcrc32($data)
return hexdec(hash("crc32b", $data)); {
return hexdec(hash('crc32b', $data));
} }
/** /**
* Function to dump the hex version of a string. * Function to dump the hex version of a string.
* :param what: What to dump * :param what: What to dump.
*/ */
function hex_dump($what) { var_dump(bin2hex($what)); }; function hex_dump($what)
{
var_dump(bin2hex($what));
}
/** /**
* len. * len.
* *
@ -40,22 +45,27 @@ function hex_dump($what) { var_dump(bin2hex($what)); };
/** /**
* Function to visualize byte streams. Split into bytes, print to console. * Function to visualize byte streams. Split into bytes, print to console.
* :param bs: BYTE STRING * :param bs: BYTE STRING.
*/ */
function vis($bs) { function vis($bs)
{
$bs = str_split($bs); $bs = str_split($bs);
$symbols_in_one_line = 8; $symbols_in_one_line = 8;
$n = floor(len($bs) / $symbols_in_one_line); $n = floor(len($bs) / $symbols_in_one_line);
$i = 0; $i = 0;
foreach (pyjslib_range($n) as $i) { foreach (pyjslib_range($n) as $i) {
echo $i * $symbols_in_one_line . ' | ' . join(' ', echo $i * $symbols_in_one_line.' | '.implode(' ',
array_map(function($el) { return bin2hex($el); }, array_slice($bs,$i*$symbols_in_one_line, ($i+1)*$symbols_in_one_line)) array_map(function ($el) {
) . PHP_EOL; return bin2hex($el);
}, array_slice($bs, $i * $symbols_in_one_line, ($i + 1) * $symbols_in_one_line))
).PHP_EOL;
} }
if (!(len($bs) % $symbols_in_one_line == 0)) { if (!(len($bs) % $symbols_in_one_line == 0)) {
echo ($i + 1) * $symbols_in_one_line . ' | ' . join(' ', echo($i + 1) * $symbols_in_one_line.' | '.implode(' ',
array_map(function($el) { return bin2hex($el); }, array_slice($bs, ($i+1)*$symbols_in_one_line)) array_map(function ($el) {
) . PHP_EOL; return bin2hex($el);
}, array_slice($bs, ($i + 1) * $symbols_in_one_line))
).PHP_EOL;
} }
} }
/** /**
@ -63,7 +73,8 @@ function vis($bs) {
* Convert a byte string to a long integer. * Convert a byte string to a long integer.
* This is (essentially) the inverse of long_to_bytes(). * This is (essentially) the inverse of long_to_bytes().
*/ */
function bytes_to_long($s) { function bytes_to_long($s)
{
$acc = 0; $acc = 0;
$length = strlen($s); $length = strlen($s);
if (($length % 4)) { if (($length % 4)) {
@ -71,23 +82,28 @@ function bytes_to_long($s) {
$s = (($b('') * $extra) + $s); $s = (($b('') * $extra) + $s);
$length = ($length + $extra); $length = ($length + $extra);
} }
foreach( pyjslib_range(0, $length, 4) as $i ) { foreach (pyjslib_range(0, $length, 4) as $i) {
$acc = ($acc << 32 + $this->struct->unpack('I', array_slice($s, $i, ($i + 4) - $i))[0]); $acc = ($acc << 32 + $this->struct->unpack('I', array_slice($s, $i, ($i + 4) - $i))[0]);
} }
return $acc; return $acc;
} }
function fread_all($handle) { function fread_all($handle)
{
$pos = ftell($handle); $pos = ftell($handle);
fseek($handle, 0); fseek($handle, 0);
$content = fread($handle, fstat($handle)["size"]); $content = fread($handle, fstat($handle)['size']);
fseek($handle, $pos); fseek($handle, $pos);
return $content; return $content;
} }
function fopen_and_write($filename, $mode, $data) { function fopen_and_write($filename, $mode, $data)
{
$handle = fopen($filename, $mode); $handle = fopen($filename, $mode);
fwrite($handle, $data); fwrite($handle, $data);
rewind($handle); rewind($handle);
return $handle; return $handle;
} }
/** /**
@ -97,14 +113,15 @@ function fopen_and_write($filename, $mode, $data) {
* byte string with binary zeros so that the length is a multiple of * byte string with binary zeros so that the length is a multiple of
* blocksize. * blocksize.
*/ */
function long_to_bytes($n,$blocksize=0) { function long_to_bytes($n, $blocksize = 0)
{
$s = $b(''); $s = $b('');
$n = long($n); $n = long($n);
while (($n > 0)) { while (($n > 0)) {
$s = ($this->struct->pack('I', $n & 4294967295) + $s); $s = ($this->struct->pack('I', $n & 4294967295) + $s);
$n = $n >> 32; $n = $n >> 32;
} }
foreach( pyjslib_range(strlen($s)) as $i ) { foreach (pyjslib_range(strlen($s)) as $i) {
if (($s[$i] != $b('')[0])) { if (($s[$i] != $b('')[0])) {
break; break;
} }
@ -113,24 +130,31 @@ function long_to_bytes($n,$blocksize=0) {
if (($blocksize > 0) && (strlen($s) % $blocksize)) { if (($blocksize > 0) && (strlen($s) % $blocksize)) {
$s = ((($blocksize - (strlen($s) % $blocksize)) * $b('')) + $s); $s = ((($blocksize - (strlen($s) % $blocksize)) * $b('')) + $s);
} }
return $s; return $s;
} }
function string2bin($string) { function string2bin($string)
{
$res = null; $res = null;
foreach(explode('\\', $string) as $s) { foreach (explode('\\', $string) as $s) {
if($s != null && $s[0] == "x") { if ($s != null && $s[0] == 'x') {
$res .= hex2bin(substr($s, 1)); $res .= hex2bin(substr($s, 1));
} }
} }
return $res; return $res;
} }
/** /**
* Manages TCP Transport. encryption and message frames * Manages TCP Transport. encryption and message frames.
*/ */
class Session { class Session
function __construct($ip, $port, $auth_key = null, $server_salt = null) { {
$this->sock = fsockopen("tcp://".$ip.":".$port); public function __construct($ip, $port, $auth_key = null, $server_salt = null)
if(!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) throw new Exception("Couldn't connect to socket."); {
$this->sock = fsockopen('tcp://'.$ip.':'.$port);
if (!(get_resource_type($this->sock) == 'file' || get_resource_type($this->sock) == 'stream')) {
throw new Exception("Couldn't connect to socket.");
}
$this->number = 0; $this->number = 0;
$this->timedelta = 0; $this->timedelta = 0;
$this->session_id = random_bytes(8); $this->session_id = random_bytes(8);
@ -141,59 +165,65 @@ class Session {
$this->AUTH_MAX_RETRY = 5; $this->AUTH_MAX_RETRY = 5;
$this->struct = new \danog\PHP\Struct(); $this->struct = new \danog\PHP\Struct();
try { try {
$this->tl = new TL("https://core.telegram.org/schema/mtproto-json"); $this->tl = new TL('https://core.telegram.org/schema/mtproto-json');
} catch(Exception $e){ } catch (Exception $e) {
$this->tl = new TL(__DIR__ . '/TL_schema.JSON'); $this->tl = new TL(__DIR__.'/TL_schema.JSON');
} }
} }
function __destruct() {
public function __destruct()
{
fclose($this->sock); fclose($this->sock);
} }
/** /**
* Forming the message frame and sending message to server * Forming the message frame and sending message to server
* :param message: byte string to send * :param message: byte string to send.
*/ */
function send_message($message_data) { public function send_message($message_data)
$message_id = $this->struct->pack('<Q', (int)((time() + $this->timedelta) * pow(2, 30)) * 4); {
$message_id = $this->struct->pack('<Q', (int) ((time() + $this->timedelta) * pow(2, 30)) * 4);
if (($this->auth_key == null) || ($this->server_salt == null)) { if (($this->auth_key == null) || ($this->server_salt == null)) {
$message = string2bin('\x00\x00\x00\x00\x00\x00\x00\x00') . $message_id . $this->struct->pack('<I', strlen($message_data)) . $message_data; $message = string2bin('\x00\x00\x00\x00\x00\x00\x00\x00').$message_id.$this->struct->pack('<I', strlen($message_data)).$message_data;
} else { } else {
$encrypted_data = $encrypted_data =
$this->server_salt . $this->session_id . $message_id . $this->struct->pack('<II', $this->number, strlen($message_data)) . $message_data; $this->server_salt.$this->session_id.$message_id.$this->struct->pack('<II', $this->number, strlen($message_data)).$message_data;
$message_key = substr(sha1($encrypted_data, true), -16, null); $message_key = substr(sha1($encrypted_data, true), -16, null);
$padding = random_bytes((-strlen($encrypted_data) % 16)); $padding = random_bytes((-strlen($encrypted_data) % 16));
echo strlen($encrypted_data . $padding) . PHP_EOL; echo strlen($encrypted_data.$padding).PHP_EOL;
list($aes_key, $aes_iv) = $this->aes_calculate($message_key); list($aes_key, $aes_iv) = $this->aes_calculate($message_key);
$message = $this->auth_key_id . $message_key . crypt::ige_encrypt($encrypted_data . $padding, $aes_key, $aes_iv); $message = $this->auth_key_id.$message_key.crypt::ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
} }
$step1 = $this->struct->pack('<II', (strlen($message) + 12), $this->number) . $message; $step1 = $this->struct->pack('<II', (strlen($message) + 12), $this->number).$message;
$step2 = $step1 . $this->struct->pack('<I', newcrc32($step1)); $step2 = $step1.$this->struct->pack('<I', newcrc32($step1));
fwrite($this->sock, $step2); fwrite($this->sock, $step2);
$this->number += 1; $this->number += 1;
} }
/** /**
* Reading socket and receiving message from server. Check the CRC32. * Reading socket and receiving message from server. Check the CRC32.
*/ */
function recv_message() { public function recv_message()
{
$packet_length_data = fread($this->sock, 4); $packet_length_data = fread($this->sock, 4);
if (len($packet_length_data) < 4) { if (len($packet_length_data) < 4) {
throw new Exception('Nothing in the socket!'); throw new Exception('Nothing in the socket!');
} }
$packet_length = $this->struct->unpack('<I', $packet_length_data)[1]; $packet_length = $this->struct->unpack('<I', $packet_length_data)[1];
$packet = fread($this->sock, ($packet_length - 4)); $packet = fread($this->sock, ($packet_length - 4));
if (!(newcrc32($packet_length_data . substr($packet, 0, -4 - 0)) == $this->struct->unpack('<I', substr($packet, -4, null))[1])) { if (!(newcrc32($packet_length_data.substr($packet, 0, -4 - 0)) == $this->struct->unpack('<I', substr($packet, -4, null))[1])) {
throw new Exception('CRC32 was not correct!'); throw new Exception('CRC32 was not correct!');
} }
$x = $this->struct->unpack('<I', substr($packet, null, 4)); $x = $this->struct->unpack('<I', substr($packet, null, 4));
$auth_key_id = substr($packet, 4, 12 - 4); $auth_key_id = substr($packet, 4, 12 - 4);
if ($auth_key_id == string2bin('\x00\x00\x00\x00\x00\x00\x00\x00')) { if ($auth_key_id == string2bin('\x00\x00\x00\x00\x00\x00\x00\x00')) {
list($message_id, $message_length) = struct.unpack("<8sI", substr($packet, 12, 24)); list($message_id, $message_length) = struct.unpack('<8sI', substr($packet, 12, 24));
$data = substr($packet, 24, (24 + $message_length) - 24); $data = substr($packet, 24, (24 + $message_length) - 24);
} else if ($auth_key_id == $this->auth_key_id) { } elseif ($auth_key_id == $this->auth_key_id) {
$message_key = substr($packet, 12, 28 - 12); $message_key = substr($packet, 12, 28 - 12);
$encrypted_data = substr($packet, 28, -4 - 28); $encrypted_data = substr($packet, 28, -4 - 28);
list($aes_key, $aes_iv) = $this->aes_calculate($message_key,'from server'); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, 'from server');
$decrypted_data = crypt::ige_decrypt($encrypted_data, $aes_key, $aes_iv); $decrypted_data = crypt::ige_decrypt($encrypted_data, $aes_key, $aes_iv);
assert((substr($decrypted_data, 0, 8 - 0) == $this->server_salt)); assert((substr($decrypted_data, 0, 8 - 0) == $this->server_salt));
assert((substr($decrypted_data, 8, 16 - 8) == $this->session_id)); assert((substr($decrypted_data, 8, 16 - 8) == $this->session_id));
@ -204,27 +234,32 @@ class Session {
} else { } else {
throw new Exception('Got unknown auth_key id'); throw new Exception('Got unknown auth_key id');
} }
return $data; return $data;
} }
function method_call($method, $kwargs) {
public function method_call($method, $kwargs)
{
foreach (range(1, $this->MAX_RETRY) as $i) { foreach (range(1, $this->MAX_RETRY) as $i) {
try { try {
//var_dump(py2php_kwargs_function_call('serialize_method', [$method], $kwargs)); //var_dump(py2php_kwargs_function_call('serialize_method', [$method], $kwargs));
$this->send_message($this->tl->serialize_method($method, $kwargs)); $this->send_message($this->tl->serialize_method($method, $kwargs));
$server_answer = $this->recv_message(); $server_answer = $this->recv_message();
} } catch (Exception $e) {
catch(Exception $e) { echo $e->getMessage().PHP_EOL;
echo $e->getMessage() . PHP_EOL;
pyjslib_printnl('Retry call method'); pyjslib_printnl('Retry call method');
continue; continue;
} }
return $this->tl->deserialize(fopen_and_write("php://memory", "rw+b", $server_answer));
return $this->tl->deserialize(fopen_and_write('php://memory', 'rw+b', $server_answer));
} }
} }
function create_auth_key() {
public function create_auth_key()
{
$nonce = random_bytes(16); $nonce = random_bytes(16);
pyjslib_printnl('Requesting pq'); pyjslib_printnl('Requesting pq');
$ResPQ = $this->method_call('req_pq', ["nonce" => $nonce]); $ResPQ = $this->method_call('req_pq', ['nonce' => $nonce]);
$server_nonce = $ResPQ['server_nonce']; $server_nonce = $ResPQ['server_nonce'];
$public_key_fingerprint = $ResPQ['server_public_key_fingerprints'][0]; $public_key_fingerprint = $ResPQ['server_public_key_fingerprints'][0];
$pq_bytes = $ResPQ['pq']; $pq_bytes = $ResPQ['pq'];
@ -237,16 +272,16 @@ class Session {
pyjslib_printnl(sprintf('Factorization %d = %d * %d', [$pq, $p, $q])); pyjslib_printnl(sprintf('Factorization %d = %d * %d', [$pq, $p, $q]));
$p_bytes = long_to_bytes($p); $p_bytes = long_to_bytes($p);
$q_bytes = long_to_bytes($q); $q_bytes = long_to_bytes($q);
$f = pyjslib_open(__DIR__ . '/rsa.pub'); $f = pyjslib_open(__DIR__.'/rsa.pub');
$key = RSA::importKey($f->read()); $key = RSA::importKey($f->read());
$new_nonce = random_bytes(32); $new_nonce = random_bytes(32);
$data = py2php_kwargs_function_call('serialize_obj', ['p_q_inner_data'], ["pq" => $pq_bytes, "p" => $p_bytes, "q" => $q_bytes, "nonce" => $nonce, "server_nonce" => $server_nonce, "new_nonce" => $new_nonce]); $data = py2php_kwargs_function_call('serialize_obj', ['p_q_inner_data'], ['pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce]);
$sha_digest = sha($data, true); $sha_digest = sha($data, true);
$random_bytes = random_bytes(((255 - strlen($data)) - strlen($sha_digest))); $random_bytes = random_bytes(((255 - strlen($data)) - strlen($sha_digest)));
$to_encrypt = (($sha_digest + $data) + $random_bytes); $to_encrypt = (($sha_digest + $data) + $random_bytes);
$encrypted_data = $key->encrypt($to_encrypt, 0) [0]; $encrypted_data = $key->encrypt($to_encrypt, 0) [0];
pyjslib_printnl('Starting Diffie Hellman key exchange'); pyjslib_printnl('Starting Diffie Hellman key exchange');
$server_dh_params = $this->method_call('req_DH_params', ["nonce" => $nonce, "server_nonce" => $server_nonce, "p" => $p_bytes, "q" => $q_bytes, "public_key_fingerprint" => $public_key_fingerprint, "encrypted_data" => $encrypted_data]); $server_dh_params = $this->method_call('req_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'p' => $p_bytes, 'q' => $q_bytes, 'public_key_fingerprint' => $public_key_fingerprint, 'encrypted_data' => $encrypted_data]);
assert(($nonce == $server_dh_params['nonce'])); assert(($nonce == $server_dh_params['nonce']));
assert(($server_nonce == $server_dh_params['server_nonce'])); assert(($server_nonce == $server_dh_params['server_nonce']));
$encrypted_answer = $server_dh_params['encrypted_answer']; $encrypted_answer = $server_dh_params['encrypted_answer'];
@ -272,19 +307,19 @@ class Session {
$b = new bytes_to_long($b_str); $b = new bytes_to_long($b_str);
$g_b = pow($g, $b, $dh_prime); $g_b = pow($g, $b, $dh_prime);
$g_b_str = new long_to_bytes($g_b); $g_b_str = new long_to_bytes($g_b);
$data = py2php_kwargs_function_call('serialize_obj', ['client_DH_inner_data'], ["nonce" => $nonce, "server_nonce" => $server_nonce, "retry_id" => $retry_id, "g_b" => $g_b_str]); $data = py2php_kwargs_function_call('serialize_obj', ['client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str]);
$data_with_sha = (sha1($data, true) + $data); $data_with_sha = (sha1($data, true) + $data);
$data_with_sha_padded = ($data_with_sha + random_bytes((-strlen($data_with_sha) % 16))); $data_with_sha_padded = ($data_with_sha + random_bytes((-strlen($data_with_sha) % 16)));
$encrypted_data = crypt::ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv); $encrypted_data = crypt::ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
foreach (pyjslib_range(1, $this->AUTH_MAX_RETRY) as $i) { foreach (pyjslib_range(1, $this->AUTH_MAX_RETRY) as $i) {
$Set_client_DH_params_answer = $this->method_call('set_client_DH_params', ["nonce" => $nonce, "server_nonce" => $server_nonce, "encrypted_data" => $encrypted_data]); $Set_client_DH_params_answer = $this->method_call('set_client_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'encrypted_data' => $encrypted_data]);
$auth_key = pow($g_a, $b, $dh_prime); $auth_key = pow($g_a, $b, $dh_prime);
$auth_key_str = new long_to_bytes($auth_key); $auth_key_str = new long_to_bytes($auth_key);
$auth_key_sha = sha1($auth_key_str, true); $auth_key_sha = sha1($auth_key_str, true);
$auth_key_aux_hash = array_slice($auth_key_sha, null, 8); $auth_key_aux_hash = array_slice($auth_key_sha, null, 8);
$new_nonce_hash1 = array_slice(sha1($new_nonce . '' . $auth_key_aux_hash, true), -16, null); $new_nonce_hash1 = array_slice(sha1($new_nonce.''.$auth_key_aux_hash, true), -16, null);
$new_nonce_hash2 = array_slice(sha1($new_nonce . '' . $auth_key_aux_hash, true), -16, null); $new_nonce_hash2 = array_slice(sha1($new_nonce.''.$auth_key_aux_hash, true), -16, null);
$new_nonce_hash3 = array_slice(sha1($new_nonce . '' . $auth_key_aux_hash, true), -16, null); $new_nonce_hash3 = array_slice(sha1($new_nonce.''.$auth_key_aux_hash, true), -16, null);
assert(($Set_client_DH_params_answer['nonce'] == $nonce)); assert(($Set_client_DH_params_answer['nonce'] == $nonce));
assert(($Set_client_DH_params_answer['server_nonce'] == $server_nonce)); assert(($Set_client_DH_params_answer['server_nonce'] == $server_nonce));
if (($Set_client_DH_params_answer->name == 'dh_gen_ok')) { if (($Set_client_DH_params_answer->name == 'dh_gen_ok')) {
@ -294,11 +329,12 @@ class Session {
$this->auth_key = $auth_key_str; $this->auth_key = $auth_key_str;
$this->auth_key_id = array_slice($auth_key_sha, -8, null); $this->auth_key_id = array_slice($auth_key_sha, -8, null);
pyjslib_printnl('Auth key generated'); pyjslib_printnl('Auth key generated');
return 'Auth Ok'; return 'Auth Ok';
} else if (($Set_client_DH_params_answer->name == 'dh_gen_retry')) { } elseif (($Set_client_DH_params_answer->name == 'dh_gen_retry')) {
assert(($Set_client_DH_params_answer['new_nonce_hash2'] == $new_nonce_hash2)); assert(($Set_client_DH_params_answer['new_nonce_hash2'] == $new_nonce_hash2));
pyjslib_printnl('Retry Auth'); pyjslib_printnl('Retry Auth');
} else if (($Set_client_DH_params_answer->name == 'dh_gen_fail')) { } elseif (($Set_client_DH_params_answer->name == 'dh_gen_fail')) {
assert(($Set_client_DH_params_answer['new_nonce_hash3'] == $new_nonce_hash3)); assert(($Set_client_DH_params_answer['new_nonce_hash3'] == $new_nonce_hash3));
pyjslib_printnl('Auth Failed'); pyjslib_printnl('Auth Failed');
throw new Exception('Auth Failed'); throw new Exception('Auth Failed');
@ -307,7 +343,9 @@ class Session {
} }
} }
} }
function aes_calculate($msg_key, $direction = 'to server') {
public function aes_calculate($msg_key, $direction = 'to server')
{
$x = ($direction == 'to server') ? 0 : 8; $x = ($direction == 'to server') ? 0 : 8;
$sha1_a = sha1(($msg_key + array_slice($this->auth_key, $x, ($x + 32) - $x)), true); $sha1_a = sha1(($msg_key + array_slice($this->auth_key, $x, ($x + 32) - $x)), true);
$sha1_b = sha1(((array_slice($this->auth_key, ($x + 32), ($x + 48) - ($x + 32)) + $msg_key) + array_slice($this->auth_key, (48 + $x), (64 + $x) - (48 + $x))), true); $sha1_b = sha1(((array_slice($this->auth_key, ($x + 32), ($x + 48) - ($x + 32)) + $msg_key) + array_slice($this->auth_key, (48 + $x), (64 + $x) - (48 + $x))), true);
@ -315,6 +353,7 @@ class Session {
$sha1_d = sha1(($msg_key + array_slice($this->auth_key, ($x + 96), ($x + 128) - ($x + 96))))->digest(); $sha1_d = sha1(($msg_key + array_slice($this->auth_key, ($x + 96), ($x + 128) - ($x + 96))))->digest();
$aes_key = ((array_slice($sha1_a, 0, 8 - 0) + array_slice($sha1_b, 8, 20 - 8)) + array_slice($sha1_c, 4, 16 - 4)); $aes_key = ((array_slice($sha1_a, 0, 8 - 0) + array_slice($sha1_b, 8, 20 - 8)) + array_slice($sha1_c, 4, 16 - 4));
$aes_iv = (((array_slice($sha1_a, 8, 20 - 8) + array_slice($sha1_b, 0, 8 - 0)) + array_slice($sha1_c, 16, 20 - 16)) + array_slice($sha1_d, 0, 8 - 0)); $aes_iv = (((array_slice($sha1_a, 8, 20 - 8) + array_slice($sha1_b, 0, 8 - 0)) + array_slice($sha1_c, 16, 20 - 16)) + array_slice($sha1_d, 0, 8 - 0));
return [$aes_key, $aes_iv]; return [$aes_key, $aes_iv];
} }
} }

View File

@ -1,31 +1,39 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
function everynth($array, $n) { require_once 'libpy2php.php';
$result = array(); function everynth($array, $n)
{
$result = [];
$i = -1; $i = -1;
foreach($array as $key => $value) { foreach ($array as $key => $value) {
if ($i++ == $n) { if ($i++ == $n) {
$i = 0; $i = 0;
} }
if($i == 0) { if ($i == 0) {
$result[$key] = $value; $result[$key] = $value;
} }
} }
return $result; return $result;
} }
function array_merge_ignore_keys($array1, $array2) { function array_merge_ignore_keys($array1, $array2)
if(count($array1) == count($array2)) { {
if (count($array1) == count($array2)) {
$i = -1; $i = -1;
foreach ($array1 as $key => $val){ foreach ($array1 as $key => $val) {
$array1[$key] = $array2[$i++]; $array1[$key] = $array2[$i++];
} }
} else return null; } else {
return;
}
return $array1; return $array1;
} }
function primesbelow($N) { function primesbelow($N)
{
$correction = (($N % 6) > 1); $correction = (($N % 6) > 1);
$N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1) ][($N % 6) ]; $N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1)][($N % 6)];
$sieve = array_fill(0, floor($N / 3), true); $sieve = array_fill(0, floor($N / 3), true);
$sieve[0] = false; $sieve[0] = false;
foreach (pyjslib_range((floor(pyjslib_int(pow($N, 0.5)) / 3) + 1)) as $i) { foreach (pyjslib_range((floor(pyjslib_int(pow($N, 0.5)) / 3) + 1)) as $i) {
@ -37,10 +45,10 @@ function primesbelow($N) {
array_splice( array_splice(
$sieve, floor( $sieve, floor(
( (
$k*$k + 4*$k - 2*$k*($i%2) $k * $k + 4 * $k - 2 * $k * ($i % 2)
) / 3 ) / 3
) )
), 2*$k ), 2 * $k
), ),
( (
array_fill( array_fill(
@ -71,23 +79,29 @@ function primesbelow($N) {
); );
} }
} }
return ([2, 3] + array_map(function ($i, $sieve) { if($sieve[$i]) return (3 * $i + 1) | 1; }, pyjslib_range(1, (($N / 3) - $correction)), $sieve));
return [2, 3] + array_map(function ($i, $sieve) {
if ($sieve[$i]) {
return (3 * $i + 1) | 1;
}
}, pyjslib_range(1, (($N / 3) - $correction)), $sieve);
} }
$smallprimeset = array_unique(primesbelow(100000)); $smallprimeset = array_unique(primesbelow(100000));
$_smallprimeset = 100000; $_smallprimeset = 100000;
function isprime($n, $precision = 7) { function isprime($n, $precision = 7)
{
if (($n == 1) || (($n % 2) == 0)) { if (($n == 1) || (($n % 2) == 0)) {
return false; return false;
} else if (($n < 1)) { } elseif (($n < 1)) {
throw new $ValueError('Out of bounds, first argument must be > 0'); throw new $ValueError('Out of bounds, first argument must be > 0');
} else if (($n < $_smallprimeset)) { } elseif (($n < $_smallprimeset)) {
return in_array($n, $smallprimeset); return in_array($n, $smallprimeset);
} }
$d = ($n - 1); $d = ($n - 1);
$s = 0; $s = 0;
while ((($d % 2) == 0)) { while ((($d % 2) == 0)) {
$d = floor($d /2); $d = floor($d / 2);
$s+= 1; $s += 1;
} }
foreach (pyjslib_range($precision) as $repeat) { foreach (pyjslib_range($precision) as $repeat) {
$a = random::randrange(2, ($n - 2)); $a = random::randrange(2, ($n - 2));
@ -105,16 +119,18 @@ function isprime($n, $precision = 7) {
} }
} }
} }
return true; return true;
} }
function pollard_brent($n) { function pollard_brent($n)
{
if ((($n % 2) == 0)) { if ((($n % 2) == 0)) {
return 2; return 2;
} }
if ((($n % 3) == 0)) { if ((($n % 3) == 0)) {
return 3; return 3;
} }
list($y, $c, $m) = [random::randint(1, ($n - 1)), random::randint(1, ($n - 1)), random::randint(1, ($n - 1)) ]; list($y, $c, $m) = [random::randint(1, ($n - 1)), random::randint(1, ($n - 1)), random::randint(1, ($n - 1))];
list($g, $r, $q) = [1, 1, 1]; list($g, $r, $q) = [1, 1, 1];
while (($g == 1)) { while (($g == 1)) {
$x = $y; $x = $y;
@ -129,9 +145,9 @@ function pollard_brent($n) {
$q = (($q * abs(($x - $y))) % $n); $q = (($q * abs(($x - $y))) % $n);
} }
$g = gcd($q, $n); $g = gcd($q, $n);
$k+= $m; $k += $m;
} }
$r*= 2; $r *= 2;
} }
if (($g == $n)) { if (($g == $n)) {
while (true) { while (true) {
@ -142,10 +158,12 @@ function pollard_brent($n) {
} }
} }
} }
return $g; return $g;
} }
$smallprimes = primesbelow(10000); $smallprimes = primesbelow(10000);
function primefactors($n, $sort = false) { function primefactors($n, $sort = false)
{
global $smallprimes; global $smallprimes;
$factors = []; $factors = [];
$limit = (pyjslib_int(pow($n, 0.5)) + 1); $limit = (pyjslib_int(pow($n, 0.5)) + 1);
@ -173,51 +191,56 @@ function primefactors($n, $sort = false) {
$factor = pollard_brent($n); $factor = pollard_brent($n);
$factors->extend(primefactors($factor)); $factors->extend(primefactors($factor));
$n = floor($n / $factor); $n = floor($n / $factor);
} }
if ($sort) { if ($sort) {
$factors->sort(); $factors->sort();
} }
return $factors; return $factors;
} }
function factorization($n) { function factorization($n)
{
$factors = []; $factors = [];
foreach (primefactors($n) as $p1) { foreach (primefactors($n) as $p1) {
try { try {
$factors[$p1]+= 1; $factors[$p1] += 1;
} } catch (KeyError $e) {
catch(KeyError $e) {
$factors[$p1] = 1; $factors[$p1] = 1;
} }
} }
return $factors; return $factors;
} }
$totients = []; $totients = [];
function totient($n) { function totient($n)
{
if (($n == 0)) { if (($n == 0)) {
return 1; return 1;
} }
try { try {
return $totients[$n]; return $totients[$n];
} } catch (KeyError $e) {
catch(KeyError $e) {
} }
$tot = 1; $tot = 1;
foreach (factorization($n)->items() as list($p, $exp)) { foreach (factorization($n)->items() as list($p, $exp)) {
$tot*= (($p - 1) * pow($p, ($exp - 1))); $tot *= (($p - 1) * pow($p, ($exp - 1)));
} }
$totients[$n] = $tot; $totients[$n] = $tot;
return $tot; return $tot;
} }
function gcd($a, $b) { function gcd($a, $b)
{
if (($a == $b)) { if (($a == $b)) {
return $a; return $a;
} }
while (($b > 0)) { while (($b > 0)) {
list($a, $b) = [$b, ($a % $b) ]; list($a, $b) = [$b, ($a % $b)];
} }
return $a; return $a;
} }
function lcm($a, $b) { function lcm($a, $b)
{
return floor(abs(($a * $b)) / gcd($a, $b)); return floor(abs(($a * $b)) / gcd($a, $b));
} }

View File

@ -1,27 +1,30 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('mtproto.php'); require_once 'libpy2php.php';
require_once ('classes/shell.php'); require_once 'mtproto.php';
require_once 'classes/shell.php';
if (!debug_backtrace()) { if (!debug_backtrace()) {
$clidata = []; $clidata = [];
$clidata["description"] = 'MadelineProto: PHP implementation of telegram API. Translated from telepy by Daniil Gentili.'; $clidata['description'] = 'MadelineProto: PHP implementation of telegram API. Translated from telepy by Daniil Gentili.';
$clidata['args']['commands'] = array_merge(['cmd', 'dialog_list', 'contact_list'], array_map(function($sub) { return "chat_" . $sub; }, ['info', 'add_user', 'add_user_to_chat', 'del_user', 'set_photo', 'rename'])); $clidata['args']['commands'] = array_merge(['cmd', 'dialog_list', 'contact_list'], array_map(function ($sub) {
$clidata['args']['flags'] = "h"; return 'chat_'.$sub;
$clidata["help"] = $clidata["description"] . PHP_EOL . PHP_EOL . "Flags: "; }, ['info', 'add_user', 'add_user_to_chat', 'del_user', 'set_photo', 'rename']));
$clidata['args']['flags'] = 'h';
$clidata['help'] = $clidata['description'].PHP_EOL.PHP_EOL.'Flags: ';
foreach (str_split($clidata['args']['flags']) as $flag) { foreach (str_split($clidata['args']['flags']) as $flag) {
$clidata["help"] .= "-" . $flag . ", "; $clidata['help'] .= '-'.$flag.', ';
} }
$clidata["help"] .= PHP_EOL . "Commands: "; $clidata['help'] .= PHP_EOL.'Commands: ';
foreach ($clidata['args']['commands'] as $command) { foreach ($clidata['args']['commands'] as $command) {
$clidata["help"] .= $command . ", "; $clidata['help'] .= $command.', ';
} }
$clidata["help"] .= PHP_EOL; $clidata['help'] .= PHP_EOL;
if(isset(getopt($clidata['args']['flags'])["h"])) { if (isset(getopt($clidata['args']['flags'])['h'])) {
die($clidata["help"]); die($clidata['help']);
} }
if ($argc == 1) { if ($argc == 1) {
$newTelePyShell = new TelepyShell(); $newTelePyShell = new TelepyShell();

View File

@ -1,8 +1,9 @@
<?php <?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once ('libpy2php.php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once ('os.php'); require_once 'libpy2php.php';
require_once ('mtproto.php'); require_once 'os.php';
require_once 'mtproto.php';
$config = parse_ini_file('credentials', true); $config = parse_ini_file('credentials', true);
if (!($config)) { if (!($config)) {
pyjslib_printnl('File \'credentials\' seems to not exist.'); pyjslib_printnl('File \'credentials\' seems to not exist.');