Let the madness begin!
This commit is contained in:
parent
433e9bc5d3
commit
b5326b4cbb
554
AES.class.php
Normal file
554
AES.class.php
Normal file
@ -0,0 +1,554 @@
|
||||
<?php
|
||||
/*
|
||||
* Author: Cody Phillips
|
||||
* Company: Phillips Data
|
||||
* Website: www.phpaes.com, www.phillipsdata.com
|
||||
* File: AES.class.php
|
||||
* October 1, 2007
|
||||
*
|
||||
* This software is sold as-is without any warranties, expressed or implied,
|
||||
* including but not limited to performance and/or merchantability. No
|
||||
* warranty of fitness for a particular purpose is offered. This script can
|
||||
* be used on as many servers as needed, as long as the servers are owned
|
||||
* by the purchaser. (Contact us if you want to distribute it as part of
|
||||
* another project) The purchaser cannot modify, rewrite, edit, or change any
|
||||
* of this code and then resell it, which would be copyright infringement.
|
||||
* This code can be modified for personal use only.
|
||||
*
|
||||
* Comments, Questions? Contact the author at cody [at] wshost [dot] net
|
||||
*/
|
||||
|
||||
class AES {
|
||||
// The number of 32-bit words comprising the plaintext and columns comrising the state matrix of an AES cipher.
|
||||
private static $Nb = 4;
|
||||
// The number of 32-bit words comprising the cipher key in this AES cipher.
|
||||
private $Nk;
|
||||
// The number of rounds in this AES cipher.
|
||||
private $Nr;
|
||||
|
||||
// The S-Box substitution table.
|
||||
private static $sBox = array(
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
|
||||
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
|
||||
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
|
||||
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
|
||||
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
|
||||
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
|
||||
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
|
||||
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
|
||||
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
|
||||
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
|
||||
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
|
||||
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
);
|
||||
|
||||
// The inverse S-Box substitution table.
|
||||
private static $invSBox = array(
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
|
||||
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
|
||||
0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
|
||||
0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
|
||||
0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
|
||||
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
|
||||
0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
|
||||
0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
|
||||
0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
|
||||
0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
|
||||
0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
|
||||
0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
);
|
||||
|
||||
// Log table based on 0xe5
|
||||
private static $ltable = array(
|
||||
0x00, 0xff, 0xc8, 0x08, 0x91, 0x10, 0xd0, 0x36,
|
||||
0x5a, 0x3e, 0xd8, 0x43, 0x99, 0x77, 0xfe, 0x18,
|
||||
0x23, 0x20, 0x07, 0x70, 0xa1, 0x6c, 0x0c, 0x7f,
|
||||
0x62, 0x8b, 0x40, 0x46, 0xc7, 0x4b, 0xe0, 0x0e,
|
||||
0xeb, 0x16, 0xe8, 0xad, 0xcf, 0xcd, 0x39, 0x53,
|
||||
0x6a, 0x27, 0x35, 0x93, 0xd4, 0x4e, 0x48, 0xc3,
|
||||
0x2b, 0x79, 0x54, 0x28, 0x09, 0x78, 0x0f, 0x21,
|
||||
0x90, 0x87, 0x14, 0x2a, 0xa9, 0x9c, 0xd6, 0x74,
|
||||
0xb4, 0x7c, 0xde, 0xed, 0xb1, 0x86, 0x76, 0xa4,
|
||||
0x98, 0xe2, 0x96, 0x8f, 0x02, 0x32, 0x1c, 0xc1,
|
||||
0x33, 0xee, 0xef, 0x81, 0xfd, 0x30, 0x5c, 0x13,
|
||||
0x9d, 0x29, 0x17, 0xc4, 0x11, 0x44, 0x8c, 0x80,
|
||||
0xf3, 0x73, 0x42, 0x1e, 0x1d, 0xb5, 0xf0, 0x12,
|
||||
0xd1, 0x5b, 0x41, 0xa2, 0xd7, 0x2c, 0xe9, 0xd5,
|
||||
0x59, 0xcb, 0x50, 0xa8, 0xdc, 0xfc, 0xf2, 0x56,
|
||||
0x72, 0xa6, 0x65, 0x2f, 0x9f, 0x9b, 0x3d, 0xba,
|
||||
0x7d, 0xc2, 0x45, 0x82, 0xa7, 0x57, 0xb6, 0xa3,
|
||||
0x7a, 0x75, 0x4f, 0xae, 0x3f, 0x37, 0x6d, 0x47,
|
||||
0x61, 0xbe, 0xab, 0xd3, 0x5f, 0xb0, 0x58, 0xaf,
|
||||
0xca, 0x5e, 0xfa, 0x85, 0xe4, 0x4d, 0x8a, 0x05,
|
||||
0xfb, 0x60, 0xb7, 0x7b, 0xb8, 0x26, 0x4a, 0x67,
|
||||
0xc6, 0x1a, 0xf8, 0x69, 0x25, 0xb3, 0xdb, 0xbd,
|
||||
0x66, 0xdd, 0xf1, 0xd2, 0xdf, 0x03, 0x8d, 0x34,
|
||||
0xd9, 0x92, 0x0d, 0x63, 0x55, 0xaa, 0x49, 0xec,
|
||||
0xbc, 0x95, 0x3c, 0x84, 0x0b, 0xf5, 0xe6, 0xe7,
|
||||
0xe5, 0xac, 0x7e, 0x6e, 0xb9, 0xf9, 0xda, 0x8e,
|
||||
0x9a, 0xc9, 0x24, 0xe1, 0x0a, 0x15, 0x6b, 0x3a,
|
||||
0xa0, 0x51, 0xf4, 0xea, 0xb2, 0x97, 0x9e, 0x5d,
|
||||
0x22, 0x88, 0x94, 0xce, 0x19, 0x01, 0x71, 0x4c,
|
||||
0xa5, 0xe3, 0xc5, 0x31, 0xbb, 0xcc, 0x1f, 0x2d,
|
||||
0x3b, 0x52, 0x6f, 0xf6, 0x2e, 0x89, 0xf7, 0xc0,
|
||||
0x68, 0x1b, 0x64, 0x04, 0x06, 0xbf, 0x83, 0x38
|
||||
);
|
||||
|
||||
// Inverse log table
|
||||
private static $atable = array(
|
||||
0x01, 0xe5, 0x4c, 0xb5, 0xfb, 0x9f, 0xfc, 0x12,
|
||||
0x03, 0x34, 0xd4, 0xc4, 0x16, 0xba, 0x1f, 0x36,
|
||||
0x05, 0x5c, 0x67, 0x57, 0x3a, 0xd5, 0x21, 0x5a,
|
||||
0x0f, 0xe4, 0xa9, 0xf9, 0x4e, 0x64, 0x63, 0xee,
|
||||
0x11, 0x37, 0xe0, 0x10, 0xd2, 0xac, 0xa5, 0x29,
|
||||
0x33, 0x59, 0x3b, 0x30, 0x6d, 0xef, 0xf4, 0x7b,
|
||||
0x55, 0xeb, 0x4d, 0x50, 0xb7, 0x2a, 0x07, 0x8d,
|
||||
0xff, 0x26, 0xd7, 0xf0, 0xc2, 0x7e, 0x09, 0x8c,
|
||||
0x1a, 0x6a, 0x62, 0x0b, 0x5d, 0x82, 0x1b, 0x8f,
|
||||
0x2e, 0xbe, 0xa6, 0x1d, 0xe7, 0x9d, 0x2d, 0x8a,
|
||||
0x72, 0xd9, 0xf1, 0x27, 0x32, 0xbc, 0x77, 0x85,
|
||||
0x96, 0x70, 0x08, 0x69, 0x56, 0xdf, 0x99, 0x94,
|
||||
0xa1, 0x90, 0x18, 0xbb, 0xfa, 0x7a, 0xb0, 0xa7,
|
||||
0xf8, 0xab, 0x28, 0xd6, 0x15, 0x8e, 0xcb, 0xf2,
|
||||
0x13, 0xe6, 0x78, 0x61, 0x3f, 0x89, 0x46, 0x0d,
|
||||
0x35, 0x31, 0x88, 0xa3, 0x41, 0x80, 0xca, 0x17,
|
||||
0x5f, 0x53, 0x83, 0xfe, 0xc3, 0x9b, 0x45, 0x39,
|
||||
0xe1, 0xf5, 0x9e, 0x19, 0x5e, 0xb6, 0xcf, 0x4b,
|
||||
0x38, 0x04, 0xb9, 0x2b, 0xe2, 0xc1, 0x4a, 0xdd,
|
||||
0x48, 0x0c, 0xd0, 0x7d, 0x3d, 0x58, 0xde, 0x7c,
|
||||
0xd8, 0x14, 0x6b, 0x87, 0x47, 0xe8, 0x79, 0x84,
|
||||
0x73, 0x3c, 0xbd, 0x92, 0xc9, 0x23, 0x8b, 0x97,
|
||||
0x95, 0x44, 0xdc, 0xad, 0x40, 0x65, 0x86, 0xa2,
|
||||
0xa4, 0xcc, 0x7f, 0xec, 0xc0, 0xaf, 0x91, 0xfd,
|
||||
0xf7, 0x4f, 0x81, 0x2f, 0x5b, 0xea, 0xa8, 0x1c,
|
||||
0x02, 0xd1, 0x98, 0x71, 0xed, 0x25, 0xe3, 0x24,
|
||||
0x06, 0x68, 0xb3, 0x93, 0x2c, 0x6f, 0x3e, 0x6c,
|
||||
0x0a, 0xb8, 0xce, 0xae, 0x74, 0xb1, 0x42, 0xb4,
|
||||
0x1e, 0xd3, 0x49, 0xe9, 0x9c, 0xc8, 0xc6, 0xc7,
|
||||
0x22, 0x6e, 0xdb, 0x20, 0xbf, 0x43, 0x51, 0x52,
|
||||
0x66, 0xb2, 0x76, 0x60, 0xda, 0xc5, 0xf3, 0xf6,
|
||||
0xaa, 0xcd, 0x9a, 0xa0, 0x75, 0x54, 0x0e, 0x01
|
||||
);
|
||||
|
||||
// The key schedule in this AES cipher.
|
||||
private $w;
|
||||
// The state matrix in this AES cipher with Nb columns and 4 rows
|
||||
private $s;
|
||||
// Determines the lenght of key z
|
||||
private $keyLength;
|
||||
|
||||
|
||||
/** constructs an AES cipher using a specific key.
|
||||
*/
|
||||
public function __construct($z) {
|
||||
$this->Nk = strlen($z)/4;
|
||||
$this->Nr = $this->Nk + self::$Nb + 2;
|
||||
|
||||
if ($this->Nk != 4 && $this->Nk != 6 && $this->Nk != 8)
|
||||
die("Key is " . ($this->Nk*32) . " bits long. *not* 128, 192, or 256.");
|
||||
|
||||
$this->Nr = $this->Nk+self::$Nb+2;
|
||||
$this->w = array(); // Nb*(Nr+1) 32-bit words
|
||||
$this->s = array(array()); // 2-D array of Nb colums and 4 rows
|
||||
|
||||
$this->KeyExpansion($z); // places expanded key in w
|
||||
}
|
||||
|
||||
/** Encrypts an aribtrary length String.
|
||||
* @params plaintext string
|
||||
* @returns ciphertext string
|
||||
* Whenever possible you should stream your plaintext through the
|
||||
* encryptBlock() function directly, as the amount of time required
|
||||
* to encrypt is linear to the size of the ciphertext.
|
||||
**/
|
||||
public function encrypt($x) {
|
||||
$t = ""; // 16-byte block
|
||||
$y = ""; // returned cipher text;
|
||||
|
||||
// put a 16-byte block into t
|
||||
$xsize = strlen($x);
|
||||
for ($i=0; $i<$xsize; $i+=16) {
|
||||
for ($j=0; $j<16; $j++) {
|
||||
if (($i+$j)<$xsize) {
|
||||
$t[$j] = $x[$i+$j];
|
||||
}
|
||||
else
|
||||
$t[$j] = chr(0);
|
||||
}
|
||||
|
||||
$y .= $this->encryptBlock($t);
|
||||
}
|
||||
return $y;
|
||||
}
|
||||
|
||||
/** Decrypts an aribtrary length String.
|
||||
* @params ciphertext string
|
||||
* @returns plaintext string
|
||||
* Whenever possible you should stream your ciphertext through the
|
||||
* decryptBlock() function directly, as the amount of time required
|
||||
* to decrypt is linear to the size of the ciphertext.
|
||||
**/
|
||||
public function decrypt($y) {
|
||||
$t = ""; // 16-byte block
|
||||
$x = ""; // returned plain text;
|
||||
|
||||
// put a 16-byte block into t
|
||||
$ysize = strlen($y);
|
||||
for ($i=0; $i<$ysize; $i+=16) {
|
||||
for ($j=0; $j<16; $j++) {
|
||||
if (($i+$j)<$ysize)
|
||||
$t[$j] = $y[$i+$j];
|
||||
else
|
||||
$t[$j] = chr(0);
|
||||
}
|
||||
$x .= $this->decryptBlock($t);
|
||||
}
|
||||
return $x;
|
||||
}
|
||||
|
||||
/** Encrypts the 16-byte plain text.
|
||||
* @params 16-byte plaintext string
|
||||
* @returns 16-byte ciphertext string
|
||||
**/
|
||||
public function encryptBlock($x) {
|
||||
$y = ""; // 16-byte string
|
||||
|
||||
// place input x into the initial state matrix in column order
|
||||
for ($i=0; $i<4*self::$Nb; $i++) {
|
||||
// we want integerger division for the second index
|
||||
$this->s[$i%4][($i-$i%self::$Nb)/self::$Nb] = ord($x[$i]);
|
||||
}
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey(0);
|
||||
|
||||
for ($i=1; $i<$this->Nr; $i++) {
|
||||
// substitute bytes
|
||||
$this->subBytes();
|
||||
|
||||
// shift rows
|
||||
$this->shiftRows();
|
||||
|
||||
// mix columns
|
||||
$this->mixColumns();
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey($i);
|
||||
}
|
||||
|
||||
// substitute bytes
|
||||
$this->subBytes();
|
||||
|
||||
// shift rows
|
||||
$this->shiftRows();
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey($i);
|
||||
|
||||
// place state matrix s into y in column order
|
||||
for ($i=0; $i<4*self::$Nb; $i++)
|
||||
$y .= chr($this->s[$i%4][($i-$i%self::$Nb)/self::$Nb]);
|
||||
return $y;
|
||||
}
|
||||
|
||||
/** Decrypts the 16-byte cipher text.
|
||||
* @params 16-byte ciphertext string
|
||||
* @returns 16-byte plaintext string
|
||||
**/
|
||||
public function decryptBlock($y) {
|
||||
$x = ""; // 16-byte string
|
||||
|
||||
// place input y into the initial state matrix in column order
|
||||
for ($i=0; $i<4*self::$Nb; $i++)
|
||||
$this->s[$i%4][($i-$i%self::$Nb)/self::$Nb] = ord($y[$i]);
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey($this->Nr);
|
||||
|
||||
for ($i=$this->Nr-1; $i>0; $i--) {
|
||||
// inverse shift rows
|
||||
$this->invShiftRows();
|
||||
|
||||
// inverse sub bytes
|
||||
$this->invSubBytes();
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey($i);
|
||||
|
||||
// inverse mix columns
|
||||
$this->invMixColumns();
|
||||
}
|
||||
|
||||
// inverse shift rows
|
||||
$this->invShiftRows();
|
||||
|
||||
// inverse sub bytes
|
||||
$this->invSubBytes();
|
||||
|
||||
// add round key
|
||||
$this->addRoundKey($i);
|
||||
|
||||
// place state matrix s into x in column order
|
||||
for ($i=0; $i<4*self::$Nb; $i++) {
|
||||
// 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]));
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
unset($this->w);
|
||||
unset($this->s);
|
||||
}
|
||||
|
||||
/** makes a big key out of a small one
|
||||
* @returns void
|
||||
**/
|
||||
private function KeyExpansion($z) {
|
||||
// Rcon is the round constant
|
||||
static $Rcon = array(
|
||||
0x00000000,
|
||||
0x01000000,
|
||||
0x02000000,
|
||||
0x04000000,
|
||||
0x08000000,
|
||||
0x10000000,
|
||||
0x20000000,
|
||||
0x40000000,
|
||||
0x80000000,
|
||||
0x1b000000,
|
||||
0x36000000,
|
||||
0x6c000000,
|
||||
0xd8000000,
|
||||
0xab000000,
|
||||
0x4d000000,
|
||||
0x9a000000,
|
||||
0x2f000000
|
||||
);
|
||||
|
||||
$temp = 0; // temporary 32-bit word
|
||||
|
||||
// the first Nk words of w are the cipher key z
|
||||
for ($i=0; $i<$this->Nk; $i++) {
|
||||
$this->w[$i] = 0;
|
||||
// fill an entire word of expanded key w
|
||||
// by pushing 4 bytes into the w[i] word
|
||||
$this->w[$i] = ord($z[4*$i]); // add a byte in
|
||||
$this->w[$i] <<= 8; // make room for the next byte
|
||||
$this->w[$i] += ord($z[4*$i+1]);
|
||||
$this->w[$i] <<= 8;
|
||||
$this->w[$i] += ord($z[4*$i+2]);
|
||||
$this->w[$i] <<= 8;
|
||||
$this->w[$i] += ord($z[4*$i+3]);
|
||||
}
|
||||
|
||||
|
||||
for (; $i<self::$Nb*($this->Nr+1); $i++) {
|
||||
$temp = $this->w[$i-1];
|
||||
|
||||
if ($i%$this->Nk == 0)
|
||||
$temp = $this->subWord($this->rotWord($temp)) ^ $Rcon[$i/$this->Nk];
|
||||
else if ($this->Nk > 6 && $i%$this->Nk == 4)
|
||||
$temp = $this->subWord($temp);
|
||||
|
||||
$this->w[$i] = $this->w[$i-$this->Nk] ^ $temp;
|
||||
|
||||
self::make32BitWord($this->w[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** adds the key schedule for a round to a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function addRoundKey($round) {
|
||||
$temp = "";
|
||||
|
||||
for ($i=0; $i<4; $i++) {
|
||||
for ($j=0; $j<self::$Nb; $j++) {
|
||||
// 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;
|
||||
// Cast temp from a 32-bit word into an 8-bit byte.
|
||||
$temp %= 256;
|
||||
// Can't do unsigned shifts, so we need to make this temp positive
|
||||
$temp = ($temp < 0 ? (256 + $temp) : $temp);
|
||||
|
||||
$this->s[$i][$j] ^= $temp; // xor temp with the byte at location (i,j) of the state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** unmixes each column of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function invMixColumns() {
|
||||
$s0 = $s1 = $s2 = $s3= '';
|
||||
|
||||
// There are Nb columns
|
||||
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];
|
||||
|
||||
$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[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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** applies an inverse cyclic shift to the last 3 rows of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function invShiftRows() {
|
||||
$temp = "";
|
||||
for ($i=1; $i<4; $i++) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/** applies inverse S-Box substitution to each byte of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function invSubBytes() {
|
||||
for ($i=0; $i<4; $i++)
|
||||
for ($j=0; $j<self::$Nb; $j++)
|
||||
$this->s[$i][$j] = self::$invSBox[$this->s[$i][$j]];
|
||||
}
|
||||
|
||||
/** mixes each column of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function mixColumns() {
|
||||
$s0 = $s1 = $s2 = $s3= '';
|
||||
|
||||
// There are Nb columns
|
||||
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];
|
||||
|
||||
$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[2][$i] = $this->mult(0x01, $s0) ^ $this->mult(0x01, $s1) ^ $this->mult(0x02, $s2) ^ $this->mult(0x03, $s3);
|
||||
$this->s[3][$i] = $this->mult(0x03, $s0) ^ $this->mult(0x01, $s1) ^ $this->mult(0x01, $s2) ^ $this->mult(0x02, $s3);
|
||||
}
|
||||
}
|
||||
|
||||
/** applies a cyclic shift to the last 3 rows of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function shiftRows() {
|
||||
$temp = "";
|
||||
for ($i=1; $i<4; $i++) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
/** applies S-Box substitution to each byte of a state matrix.
|
||||
* @returns void
|
||||
**/
|
||||
private function subBytes() {
|
||||
|
||||
for ($i=0; $i<4; $i++) {
|
||||
for ($j=0; $j<self::$Nb; $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
|
||||
* @returns 8-bit value
|
||||
**/
|
||||
private static function mult($a, $b) {
|
||||
$sum = self::$ltable[$a] + self::$ltable[$b];
|
||||
$sum %= 255;
|
||||
// Get the antilog
|
||||
$sum = self::$atable[$sum];
|
||||
return ($a == 0 ? 0 : ($b == 0 ? 0 : $sum));
|
||||
}
|
||||
|
||||
/** applies a cyclic permutation to a 4-byte word.
|
||||
* @returns 32-bit int
|
||||
**/
|
||||
private static function rotWord($w) {
|
||||
$temp = $w >> 24; // put the first 8-bits into temp
|
||||
$w <<= 8; // make room for temp to fill the lower end of the word
|
||||
self::make32BitWord($w);
|
||||
// Can't do unsigned shifts, so we need to make this temp positive
|
||||
$temp = ($temp < 0 ? (256 + $temp) : $temp);
|
||||
$w += $temp;
|
||||
|
||||
return $w;
|
||||
}
|
||||
|
||||
/** applies S-box substitution to each byte of a 4-byte word.
|
||||
* @returns 32-bit int
|
||||
**/
|
||||
private static function subWord($w) {
|
||||
$temp = 0;
|
||||
// loop through 4 bytes of a word
|
||||
for ($i=0; $i<4; $i++) {
|
||||
$temp = $w >> 24; // put the first 8-bits into temp
|
||||
// Can't do unsigned shifts, so we need to make this temp positive
|
||||
$temp = ($temp < 0 ? (256 + $temp) : $temp);
|
||||
$w <<= 8; // make room for the substituted byte in w;
|
||||
self::make32BitWord($w);
|
||||
$w += self::$sBox[$temp]; // add the substituted byte back
|
||||
}
|
||||
|
||||
self::make32BitWord($w);
|
||||
|
||||
return $w;
|
||||
}
|
||||
|
||||
/** reduces a 64-bit word to a 32-bit word
|
||||
* @returns void
|
||||
**/
|
||||
private static function make32BitWord(&$w) {
|
||||
// Reduce this 64-bit word to 32-bits on 64-bit machines
|
||||
$w &= 0x00000000FFFFFFFF;
|
||||
}
|
||||
}
|
||||
?>
|
73
README.md
73
README.md
@ -1,72 +1,7 @@
|
||||
[![Join the chat at https://gitter.im/griganton/telepy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/griganton/telepy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
# MadelineProto
|
||||
|
||||
# About this repo
|
||||
This is Telegram API for python.
|
||||
Main aim is to implement MTProto protocol Telegram API on pure Python (not wrapped CLI)
|
||||
PHP implementation of MTProto, converted from [telepy](https://github.com/griganton/telepy) using [py2php](https://github.com/dan-da/py2php).
|
||||
|
||||
### Plan
|
||||
- [ ] Make it work on Python 2 as well as 3.
|
||||
- [ ] Follow up the same functionality of CLI API.
|
||||
- [x] Serialize/Deserialize
|
||||
- [x] Send and receive PQ authorization with server [[doc]](https://core.telegram.org/mtproto/samples-auth_key)
|
||||
- [ ] Send and receive service messages with server like logging in to server [[doc]](https://core.telegram.org/mtproto/service_messages)
|
||||
This is a WIP.
|
||||
|
||||
### Useful start points to join
|
||||
Detailed description of API and protocol can be found here:
|
||||
* https://core.telegram.org/api
|
||||
* https://core.telegram.org/mtproto
|
||||
|
||||
API registration is needed to be done by yourself at http://my.telegram.org
|
||||
Follow Structure - Credentials for provide it your API information.
|
||||
|
||||
# Structure
|
||||
|
||||
- tests
|
||||
- Serialization and SHA.py
|
||||
- mtproto.py
|
||||
- testing.py
|
||||
- prime.py
|
||||
- credentials
|
||||
- rsa.pub
|
||||
|
||||
## Credentials
|
||||
Repo doesn't contain any credentials to connect Telegram servers.
|
||||
You can get yours from http://my.telegram.org
|
||||
|
||||
You should place 2 files in the root of your repo:
|
||||
- credentials
|
||||
- rsa.pub
|
||||
|
||||
Config example for "credentials" file:
|
||||
|
||||
```
|
||||
[App data]
|
||||
api_id: 12345
|
||||
api_hash: 1234567890abcdef1234567890abcdef
|
||||
ip_address: 112.134.156.178
|
||||
port: 443
|
||||
```
|
||||
rsa.pub contains your RSA key.
|
||||
|
||||
## mtproto.py
|
||||
|
||||
Contains functions to work with MTproto protocol:
|
||||
- TL schema parsing
|
||||
- serializing and deserializing
|
||||
- manage connections to server
|
||||
- send and receive messages
|
||||
|
||||
## testing.py
|
||||
|
||||
testing.py is used to test functionality of modules.
|
||||
Now it makes steps from https://core.telegram.org/mtproto/samples-auth_key:
|
||||
- sends PQ request to server
|
||||
- parses the result
|
||||
- factorizes PQ
|
||||
|
||||
## prime.py
|
||||
prime.py is used in PQ factorization. It has been copied from https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
|
||||
|
||||
## TL schema
|
||||
We use JSON format TL Shema. TL Schema file contains information about objects and methods, it is located in TL_schema.JSON file in the root of repo. It is fully equivalent to JSON TL Schema from
|
||||
https://core.telegram.org/schema/mtproto-json
|
||||
The name of this project is inspired by [this person](https://s-media-cache-ak0.pinimg.com/736x/f0/a1/70/f0a170718baeb0e3817c612d96f5d1cf.jpg), due to the obvious signs of madness this project has in common with her.
|
||||
|
4
classes/__init__.php
Normal file
4
classes/__init__.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
$__all__ = ['Chat', 'User', 'Message', 'Contact'];
|
11
classes/chat.php
Normal file
11
classes/chat.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
class Chat {
|
||||
function __construct() {
|
||||
$this->_users = [];
|
||||
}
|
||||
function add_user($user) {
|
||||
$this->_users+= $user;
|
||||
}
|
||||
}
|
5
classes/contact.php
Normal file
5
classes/contact.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
class Contact {
|
||||
}
|
43
classes/file.php
Normal file
43
classes/file.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('os.php');
|
||||
class File {
|
||||
function __construct($path) {
|
||||
$this->_path = $path;
|
||||
}
|
||||
/**
|
||||
* truncates the file and create new with :param bytes.
|
||||
* :return number of bytes written
|
||||
*/
|
||||
function write_bytes($bytes) {
|
||||
// py2php.fixme "with" unsupported.
|
||||
|
||||
}
|
||||
/**
|
||||
* read the file as bytes. :return b'' on file not exist
|
||||
*/
|
||||
function read_bytes() {
|
||||
if (!(new exists($this->_path))) {
|
||||
return '';
|
||||
}
|
||||
// py2php.fixme "with" unsupported.
|
||||
|
||||
}
|
||||
/**
|
||||
* tries to open with os default viewer
|
||||
*/
|
||||
function open() {
|
||||
new call((os::name == 'nt') ? 'cmd /c start "" "' . $this->_path . '"' : [platform::startswith('darwin') ? 'open' : 'xdg-open', $this->_path]);
|
||||
}
|
||||
/**
|
||||
* try to remove the file
|
||||
*/
|
||||
function remove() {
|
||||
try {
|
||||
os::remove($this->_path);
|
||||
}
|
||||
catch(FileNotFoundError $e) {
|
||||
}
|
||||
}
|
||||
}
|
6
classes/message.php
Normal file
6
classes/message.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('crypt.php');
|
||||
class Message {
|
||||
}
|
339
classes/shell.php
Normal file
339
classes/shell.php
Normal file
@ -0,0 +1,339 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('os.php');
|
||||
class TelepyShell extends Cmd {
|
||||
public $intro = 'Welcome to telepy interactive shell. Type help or ? for help.
|
||||
';
|
||||
public $prompt = '>';
|
||||
function preloop() {
|
||||
require_once ('classes.telepy.php');
|
||||
$this->_telepy = new Telepy();
|
||||
}
|
||||
function precmd($line) {
|
||||
$line = $line->lstrip();
|
||||
$blank_pos = $line->find(' ');
|
||||
if (($blank_pos < 0)) {
|
||||
return $line->lower();
|
||||
}
|
||||
return array_slice($line, null, $blank_pos)->lower() . ' ' . array_slice($line, ($blank_pos + 1), null);
|
||||
}
|
||||
function completedefault( . . . $ignored) {
|
||||
pyjslib_printnl($ignored);
|
||||
}
|
||||
function complete($text, $state) {
|
||||
$this->super()->complete($text, $state);
|
||||
pyjslib_printnl('completing');
|
||||
}
|
||||
/**
|
||||
* shell <command-line>
|
||||
* lets you use external shell. !<command-line> for short-hand.
|
||||
*/
|
||||
function do_shell($line) {
|
||||
pyjslib_printnl(os::popen($line)->read());
|
||||
}
|
||||
/**
|
||||
* msg <peer>
|
||||
* sends message to this peer
|
||||
*/
|
||||
function do_msg($arg) {
|
||||
}
|
||||
/**
|
||||
* fwd <user> <msg-no>
|
||||
* forward message to user. You can see message numbers starting client with -N
|
||||
*/
|
||||
function do_fwd($arg) {
|
||||
}
|
||||
/**
|
||||
* chat_with_peer <peer>
|
||||
* starts one on one chat session with this peer. /exit or /quit to end this mode.
|
||||
*/
|
||||
function do_chat_with_peer($arg) {
|
||||
}
|
||||
/**
|
||||
* add_contact <phone-number> <first-name> <last-name>
|
||||
* tries to add contact to contact-list by phone
|
||||
*/
|
||||
function do_add_contact($arg) {
|
||||
}
|
||||
/**
|
||||
* rename_contact <user> <first-name> <last-name>
|
||||
* tries to rename contact. If you have another device it will be a fight
|
||||
*/
|
||||
function do_rename_contact($arg) {
|
||||
}
|
||||
/**
|
||||
* mark_read <peer>
|
||||
* mark read all received messages with peer
|
||||
*/
|
||||
function do_mark_read($arg) {
|
||||
}
|
||||
/**
|
||||
* delete_msg <msg-no>
|
||||
* deletes message (not completly, though)
|
||||
*/
|
||||
function do_delete_msg($arg) {
|
||||
}
|
||||
/**
|
||||
* restore_msg <msg-no>
|
||||
* restores delete message. Impossible for secret chats. Only possible short time (one hour, I think) after deletion
|
||||
*/
|
||||
function do_restore_msg($arg) {
|
||||
}
|
||||
/**
|
||||
* send_photo <peer> <photo-file-name>
|
||||
* sends photo to peer
|
||||
*/
|
||||
function do_send_photo($arg) {
|
||||
}
|
||||
/**
|
||||
* send_video <peer> <video-file-name>
|
||||
* sends video to peer
|
||||
*/
|
||||
function do_send_video($arg) {
|
||||
}
|
||||
/**
|
||||
* send_text <peer> <text-file-name>
|
||||
* sends text file as plain messages
|
||||
*/
|
||||
function do_send_text($arg) {
|
||||
}
|
||||
/**
|
||||
* load_photo <msg-no>
|
||||
* loads photo to download dir
|
||||
*/
|
||||
function do_load_photo($arg) {
|
||||
}
|
||||
/**
|
||||
* load_video <msg-no>
|
||||
* loads video to download dir
|
||||
*/
|
||||
function do_load_video($arg) {
|
||||
}
|
||||
/**
|
||||
* load_video_thumb <msg-no>
|
||||
* loads video thumbnail to download dir
|
||||
*/
|
||||
function do_load_video_thumb($arg) {
|
||||
}
|
||||
/**
|
||||
* load_audio <msg-no>
|
||||
* loads audio to download dir
|
||||
*/
|
||||
function do_load_audio($arg) {
|
||||
}
|
||||
/**
|
||||
* load_document <msg-no>
|
||||
* loads document to download dir
|
||||
*/
|
||||
function do_load_document($arg) {
|
||||
}
|
||||
/**
|
||||
* load_document_thumb <msg-no>
|
||||
* loads document thumbnail to download dir
|
||||
*/
|
||||
function do_load_document_thumb($arg) {
|
||||
}
|
||||
/**
|
||||
* view_photo <msg-no>
|
||||
* loads photo/video to download dir and starts system default viewer
|
||||
*/
|
||||
function do_view_photo($arg) {
|
||||
}
|
||||
/**
|
||||
* view_video <msg-no>
|
||||
*/
|
||||
function do_view_video($arg) {
|
||||
}
|
||||
/**
|
||||
* view_video_thumb <msg-no>
|
||||
*/
|
||||
function do_view_video_thumb($arg) {
|
||||
}
|
||||
/**
|
||||
* view_audio <msg-no>
|
||||
*/
|
||||
function do_view_audio($arg) {
|
||||
}
|
||||
/**
|
||||
* view_document <msg-no>
|
||||
*/
|
||||
function do_view_document($arg) {
|
||||
}
|
||||
/**
|
||||
* view_document_thumb <msg-no>
|
||||
*/
|
||||
function do_view_document_thumb($arg) {
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
function do_fwd_media($arg) {
|
||||
}
|
||||
/**
|
||||
* set_profile_photo <photo-file-name>
|
||||
* sets userpic. Photo should be square, or server will cut biggest central square part
|
||||
*/
|
||||
function do_set_profile_photo($arg) {
|
||||
}
|
||||
/**
|
||||
* chat_info <chat>
|
||||
* prints info about chat
|
||||
*/
|
||||
function do_chat_info($arg) {
|
||||
$arg = $arg->split();
|
||||
if ((count($arg) == 1)) {
|
||||
pyjslib_printnl(['chat_info called with ', $arg[0]]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* chat_add_user <chat> <user>
|
||||
* add user to chat
|
||||
*/
|
||||
function do_chat_add_user($arg) {
|
||||
pyjslib_printnl($arg);
|
||||
}
|
||||
/**
|
||||
* chat_del_user <chat> <user>
|
||||
* remove user from chat
|
||||
*/
|
||||
function do_chat_del_user($arg) {
|
||||
}
|
||||
/**
|
||||
* chat_rename <chat> <new-name>
|
||||
* rename chat room
|
||||
*/
|
||||
function do_chat_rename($arg) {
|
||||
$arg = $arg->split();
|
||||
}
|
||||
/**
|
||||
* create_group_chat <chat topic> <user1> <user2> <user3> ...
|
||||
* creates a groupchat with users, use chat_add_user to add more users
|
||||
*/
|
||||
function do_create_group_chat($chat_topic, $user1, $user2, $user3) {
|
||||
pyjslib_printnl($chat_topic);
|
||||
pyjslib_printnl([$user1, $user2, $user3]);
|
||||
}
|
||||
/**
|
||||
* chat_set_photo <chat> <photo-file-name>
|
||||
* sets group chat photo. Same limits as for profile photos.
|
||||
*/
|
||||
function do_chat_set_photo($chat, $photo) {
|
||||
}
|
||||
/**
|
||||
* search <peer> <pattern>
|
||||
* searches pattern in messages with peer
|
||||
*/
|
||||
function do_search($pattern) {
|
||||
}
|
||||
/**
|
||||
* global_search <pattern>
|
||||
* searches pattern in all messages
|
||||
*/
|
||||
function do_global_search($pattern) {
|
||||
}
|
||||
/**
|
||||
* create_secret_chat <user>
|
||||
* creates secret chat with this user
|
||||
*/
|
||||
function do_create_secret_chat($user) {
|
||||
}
|
||||
/**
|
||||
* visualize_key <secret_chat>
|
||||
* prints visualization of encryption key. You should compare it to your partner's one
|
||||
*/
|
||||
function do_visualize_key($secret_chat) {
|
||||
}
|
||||
/**
|
||||
* set_ttl <secret_chat> <ttl>
|
||||
* 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) {
|
||||
}
|
||||
/**
|
||||
* accept_secret_chat <secret_chat>
|
||||
* manually accept secret chat (only useful when starting with -E key)
|
||||
*/
|
||||
function do_accept_secret_chat($secret_chat) {
|
||||
}
|
||||
/**
|
||||
* user_info <user>
|
||||
* prints info about user
|
||||
*/
|
||||
function do_user_info($user) {
|
||||
}
|
||||
/**
|
||||
* history <peer> [limit]
|
||||
* prints history (and marks it as read). Default limit = 40
|
||||
*/
|
||||
function do_history($peer, $limit = 40) {
|
||||
if (($peer == '')) {
|
||||
pyjslib_printnl('no peer have specified');
|
||||
return;
|
||||
}
|
||||
$args = $peer->split();
|
||||
if (!in_array(count($args), [1, 2])) {
|
||||
pyjslib_printnl(['not appropriate number of arguments : ', $peer]);
|
||||
return;
|
||||
}
|
||||
if ((count($args) == 2)) {
|
||||
if (!($args[1]->isdecimal()) || (pyjslib_int($args[1]) < 1)) {
|
||||
pyjslib_printnl(['not a valid limit:', $args[1]]);
|
||||
}
|
||||
$limit = pyjslib_int($args[1]);
|
||||
}
|
||||
pyjslib_printnl($peer);
|
||||
pyjslib_printnl($limit);
|
||||
}
|
||||
/**
|
||||
* dialog_list
|
||||
* prints info about your dialogs
|
||||
*/
|
||||
function do_dialog_list($ignored) {
|
||||
}
|
||||
/**
|
||||
* contact_list
|
||||
* prints info about users in your contact list
|
||||
*/
|
||||
function do_contact_list($ignored) {
|
||||
}
|
||||
/**
|
||||
* suggested_contacts
|
||||
* print info about contacts, you have max common friends
|
||||
*/
|
||||
function do_suggested_contacts($ignored) {
|
||||
}
|
||||
/**
|
||||
* stats
|
||||
* just for debugging
|
||||
*/
|
||||
function do_stats($ignored) {
|
||||
}
|
||||
/**
|
||||
* export_card
|
||||
* print your 'card' that anyone can later use to import your contact
|
||||
*/
|
||||
function do_export_card($card) {
|
||||
}
|
||||
/**
|
||||
* import_card <card>
|
||||
* gets user by card. You can write messages to him after that.
|
||||
*/
|
||||
function do_import_card($card) {
|
||||
}
|
||||
/**
|
||||
* quit_force
|
||||
* quit without waiting for query ends
|
||||
*/
|
||||
function do_quit_force($ignored) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* quit
|
||||
* wait for all queries to end then quit
|
||||
*/
|
||||
function do_quit($ignored) {
|
||||
return true;
|
||||
}
|
||||
}
|
26
classes/telepy.php
Normal file
26
classes/telepy.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
class Telepy {
|
||||
function __construct() {
|
||||
try {
|
||||
require_once ('configparser.php');
|
||||
}
|
||||
catch(ImportError $e) {
|
||||
require_once ('ConfigParser.php');
|
||||
}
|
||||
require_once ('mtproto.php');
|
||||
$this->_config = $configparser->ConfigParser();
|
||||
if (!($this->_config->read('credentials'))) {
|
||||
pyjslib_printnl('File \'credentials\' seems to not exist.');
|
||||
$exit(-1);
|
||||
}
|
||||
$ip = $this->_config->get('App data', 'ip_address');
|
||||
$port = $this->_config->getint('App data', 'port');
|
||||
$this->_session = $mtproto->Session($ip, $port);
|
||||
$this->_session->create_auth_key();
|
||||
$__temp22 = py2php_kwargs_method_call($this->_session, 'method_call', ['get_future_salts'], ["num" => 3]);
|
||||
$this->_salt = $__temp22;
|
||||
$future_salts = $__temp22;
|
||||
}
|
||||
}
|
12
classes/user.php
Normal file
12
classes/user.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
class User {
|
||||
public $me = null;
|
||||
// current connected user
|
||||
public $friends = [];
|
||||
// current connected user's friends
|
||||
function __construct($uid) {
|
||||
$this->uid = $uid;
|
||||
}
|
||||
}
|
58
crypt.php
Normal file
58
crypt.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('AES.class.php');
|
||||
function ige_encrypt($message, $key, $iv) {
|
||||
return py2php_kwargs_function_call('_ige', [$message, $key, $iv], ["operation" => 'encrypt']);
|
||||
}
|
||||
function ige_decrypt($message, $key, $iv) {
|
||||
return py2php_kwargs_function_call('_ige', [$message, $key, $iv], ["operation" => 'decrypt']);
|
||||
}
|
||||
/**
|
||||
* Given a key, given an iv, and message
|
||||
* do whatever operation asked in the operation field.
|
||||
* Operation will be checked for: "decrypt" and "encrypt" strings.
|
||||
* Returns the message encrypted/decrypted.
|
||||
* message must be a multiple by 16 bytes (for division in 16 byte blocks)
|
||||
* key must be 32 byte
|
||||
* iv must be 32 byte (it's not internally used in AES 256 ECB, but it's
|
||||
* needed for IGE)
|
||||
*/
|
||||
function _ige($message, $key, $iv, $operation = 'decrypt') {
|
||||
$message = $bytes($message);
|
||||
if ((count($key) != 32)) {
|
||||
throw new $ValueError('key must be 32 bytes long (was ' . pyjslib_str(count($key)) . ' bytes)');
|
||||
}
|
||||
if ((count($iv) != 32)) {
|
||||
throw new $ValueError('iv must be 32 bytes long (was ' . pyjslib_str(count($iv)) . ' bytes)');
|
||||
}
|
||||
$cipher = new AES($key);
|
||||
$cipher = $cipher->encrypt($iv);
|
||||
$blocksize = $cipher->block_size;
|
||||
if (((count($message) % $blocksize) != 0)) {
|
||||
throw new $ValueError('message must be a multiple of 16 bytes (try adding ' . pyjslib_str((16 - (count($message) % 16))) . ' bytes of padding)');
|
||||
}
|
||||
$ivp = array_slice($iv, 0, $blocksize - 0);
|
||||
$ivp2 = array_slice($iv, $blocksize, null);
|
||||
$ciphered = $bytes();
|
||||
foreach (pyjslib_range(0, count($message), $blocksize) as $i) {
|
||||
$indata = array_slice($message, $i, ($i + $blocksize) - $i);
|
||||
if (($operation == 'decrypt')) {
|
||||
$xored = new strxor($indata, $ivp2);
|
||||
$decrypt_xored = $cipher->decrypt($xored);
|
||||
$outdata = new strxor($decrypt_xored, $ivp);
|
||||
$ivp = $indata;
|
||||
$ivp2 = $outdata;
|
||||
} else if (($operation == 'encrypt')) {
|
||||
$xored = new strxor($indata, $ivp);
|
||||
$encrypt_xored = $cipher->encrypt($xored);
|
||||
$outdata = new strxor($encrypt_xored, $ivp2);
|
||||
$ivp = $outdata;
|
||||
$ivp2 = $indata;
|
||||
} else {
|
||||
throw new $ValueError('operation must be either \'decrypt\' or \'encrypt\'');
|
||||
}
|
||||
$ciphered+= $outdata;
|
||||
}
|
||||
return $ciphered;
|
||||
}
|
486
libpy2php/libpy2php.php
Normal file
486
libpy2php/libpy2php.php
Normal file
@ -0,0 +1,486 @@
|
||||
<?php
|
||||
|
||||
# Copyright 2006 James Tauber and contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
/**
|
||||
* This call makes three things happen:
|
||||
*
|
||||
* 1) a global error handler for php errors that causes an exception to be
|
||||
* thrown instead of standard php error handling.
|
||||
*
|
||||
* 2) a global exception handler for any exceptions that are somehow not
|
||||
* caught by the application code.
|
||||
*
|
||||
* 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
|
||||
* the minor issues during development, and hopefully fewer issues
|
||||
make it out into the world.
|
||||
*/
|
||||
require_once( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'strict_mode.php' );
|
||||
init_strict_mode();
|
||||
|
||||
|
||||
|
||||
# iteration from Bob Ippolito's Iteration in JavaScript
|
||||
# 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) {
|
||||
|
||||
return is_object($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isFunction($a) {
|
||||
|
||||
return is_function($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isString($a) {
|
||||
|
||||
return is_string($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isNull($a) {
|
||||
|
||||
return is_null($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isArray($a) {
|
||||
|
||||
return is_array($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isUndefined($a) {
|
||||
|
||||
return !isset($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isIteratable($a) {
|
||||
|
||||
return $a instanceof Traversable;
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_isNumber($a) {
|
||||
|
||||
return is_numeric($a);
|
||||
|
||||
}
|
||||
|
||||
function pyjslib_int($a) {
|
||||
return (int)$a;
|
||||
}
|
||||
|
||||
function pyjslib_str($val) {
|
||||
return (string)$val;
|
||||
}
|
||||
|
||||
function pyjslib_del_slice(&$list, $from, $to, $step=1) {
|
||||
if( $from <= 0 ) {
|
||||
$from = 0;
|
||||
}
|
||||
if( $to === null ) {
|
||||
$to = count($list);
|
||||
}
|
||||
if( $step <= 0 ) {
|
||||
$step = 1;
|
||||
}
|
||||
for( $i = $from; $i < $to; $i += $step ) {
|
||||
unset( $list[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
function pyjslib_array_slice($list, $from, $to, $step=1) {
|
||||
$newlist = [];
|
||||
if( $from <= 0 ) {
|
||||
$from = 0;
|
||||
}
|
||||
if( $to === null ) {
|
||||
$to = count($list);
|
||||
}
|
||||
if( $step <= 0 ) {
|
||||
$step = 1;
|
||||
}
|
||||
for( $i = $from; $i < $to; $i += $step ) {
|
||||
$newlist[] = $list[$i];
|
||||
}
|
||||
return $newlist;
|
||||
}
|
||||
|
||||
|
||||
# taken from mochikit: range( [start,] stop[, step] )
|
||||
function pyjslib_range($start, $stop = null, $step = 1) {
|
||||
if( $stop === null ) {
|
||||
$stop = $start;
|
||||
$start = 0;
|
||||
}
|
||||
if( $stop <= $start && $step < 0 ) {
|
||||
$arr = range( $stop, $start, -$step );
|
||||
array_pop( $arr );
|
||||
return array_reverse( $arr, false );
|
||||
}
|
||||
$arr = range( $start, $stop, $step );
|
||||
array_pop( $arr );
|
||||
return $arr;
|
||||
}
|
||||
|
||||
function pyjslib_filter($callback, $iterable) {
|
||||
$a = [];
|
||||
foreach( $iterable as $item ) {
|
||||
if( call_user_func( $callback, $item ) ) {
|
||||
$a[] = $item;
|
||||
}
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
|
||||
function pyjslib_globals() {
|
||||
return $GLOBALS;
|
||||
}
|
||||
|
||||
|
||||
function pyjslib_map($callable) {
|
||||
$done = false;
|
||||
$call_cnt = 0;
|
||||
$results = [];
|
||||
|
||||
$params = func_get_args();
|
||||
array_shift( $params );
|
||||
|
||||
while( !$done ) {
|
||||
$func_args = [];
|
||||
$found = false;
|
||||
for( $i = 0; $i < count($params); $i ++ ) {
|
||||
$func_args[] = @$params[$i][$call_cnt];
|
||||
if( count($params[$i]) > $call_cnt + 1 ) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
if( !$found ) {
|
||||
$done = true;
|
||||
}
|
||||
$results[] = call_user_func_array($callable, $func_args);
|
||||
$call_cnt ++;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
function pyjslib_zip() {
|
||||
$params = func_get_args();
|
||||
if (count($params) === 1){ // this case could be probably cleaner
|
||||
// single iterable passed
|
||||
$result = array();
|
||||
foreach ($params[0] as $item){
|
||||
$result[] = array($item);
|
||||
};
|
||||
return $result;
|
||||
};
|
||||
$result = call_user_func_array('array_map',array_merge(array(null),$params));
|
||||
$length = min(array_map('count', $params));
|
||||
return array_slice($result, 0, $length);
|
||||
}
|
||||
|
||||
function pyjslib_is_assoc($arr)
|
||||
{
|
||||
return array_keys($arr) !== range(0, count($arr) - 1);
|
||||
}
|
||||
|
||||
function pyjslib_dict($arg=null) {
|
||||
if( $arg === null ) {
|
||||
return [];
|
||||
}
|
||||
if( pyjslib_is_assoc( $arg )) {
|
||||
return $arg;
|
||||
}
|
||||
$dict = [];
|
||||
foreach( $arg as $a ) {
|
||||
if( count($a) == 2 ) {
|
||||
$dict[$a[0]] = $a[1];
|
||||
}
|
||||
}
|
||||
return $dict;
|
||||
}
|
||||
|
||||
function pyjslib_printWorker($objs, $nl, $multi_arg, $depth=1) {
|
||||
$buf = '';
|
||||
if( is_array( $objs ) && $multi_arg && $depth == 1) {
|
||||
$cnt = 0;
|
||||
foreach( $objs as $obj ) {
|
||||
if( $cnt ++ > 0 ) {
|
||||
$buf .= " ";
|
||||
}
|
||||
$buf .= pyjslib_printWorker( $obj, $nl, $multi_arg, $depth + 1 );
|
||||
}
|
||||
}
|
||||
else if( is_bool( $objs )) {
|
||||
$buf = $objs ? "True" : "False";
|
||||
}
|
||||
else if( is_null( $objs )) {
|
||||
$buf = 'None';
|
||||
}
|
||||
else if( is_float( $objs )) {
|
||||
$buf = (int)$objs;
|
||||
}
|
||||
else if( is_string( $objs ) && ($multi_arg && $depth > 2 || (!$multi_arg && $depth > 1) ) ) {
|
||||
$buf = "'$objs'";
|
||||
}
|
||||
elseif( is_array( $objs )) {
|
||||
$buf = '[';
|
||||
$cnt = 0;
|
||||
foreach( $objs as $obj ) {
|
||||
$val = pyjslib_printWorker($obj, $nl, false, $depth + 1);
|
||||
if( $cnt ++ > 0 ) {
|
||||
$buf .= ', ';
|
||||
}
|
||||
$buf .= $val;
|
||||
}
|
||||
$buf .= "]";
|
||||
// $buf = '[' . implode( ", ", $objs ) . ']';
|
||||
}
|
||||
else {
|
||||
$buf = $objs;
|
||||
}
|
||||
if( $depth == 1 && (!strlen($buf) || $buf[strlen($buf)-1] != "\n") ) {
|
||||
$buf .= $nl ? "\n" : " ";
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
function pyjslib_repr($obj) {
|
||||
return pyjslib_printWorker($obj, false, false);
|
||||
}
|
||||
|
||||
function pyjslib_print($objs, $multi_arg=false) {
|
||||
echo pyjslib_printWorker($objs, false, $multi_arg);
|
||||
}
|
||||
|
||||
function pyjslib_printnl($objs, $multi_arg=false) {
|
||||
echo pyjslib_printWorker($objs, true, $multi_arg);
|
||||
}
|
||||
|
||||
function py2php_kwargs_function_call($funcname, $ordered, $named) {
|
||||
|
||||
if( $funcname == 'array' || $funcname == 'pyjslib_dict' ) {
|
||||
return $named;
|
||||
}
|
||||
|
||||
$num_ordered = count($ordered);
|
||||
$count = 1;
|
||||
|
||||
$refFunc = new ReflectionFunction($funcname);
|
||||
foreach( $refFunc->getParameters() as $param ){
|
||||
if( $param->isVariadic() ) {
|
||||
$ordered[$count-1] = $named;
|
||||
break;
|
||||
}
|
||||
//invokes ReflectionParameter::__toString
|
||||
if( $count > $num_ordered ) {
|
||||
$name = $param->name;
|
||||
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
|
||||
$ordered[] = @$named[$name] ?: $default;
|
||||
}
|
||||
|
||||
$count ++;
|
||||
}
|
||||
//var_dump($ordered);
|
||||
return call_user_func_array($funcname, $ordered);
|
||||
}
|
||||
|
||||
function py2php_kwargs_method_call( $obj, $method, $ordered, $named ) {
|
||||
|
||||
$num_ordered = count($ordered);
|
||||
$count = 1;
|
||||
|
||||
$refFunc = new ReflectionMethod($obj, $method);
|
||||
foreach( $refFunc->getParameters() as $param ){
|
||||
//invokes ReflectionParameter::__toString
|
||||
if( $count > $num_ordered ) {
|
||||
$name = $param->name;
|
||||
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
|
||||
$ordered[] = @$named[$name] ?: $default;
|
||||
}
|
||||
|
||||
$count ++;
|
||||
}
|
||||
|
||||
$callable = [$obj, $method];
|
||||
return call_user_func_array($callable, $ordered);
|
||||
}
|
||||
|
||||
class IOError extends Exception{
|
||||
}
|
||||
|
||||
class ValueError extends Exception{
|
||||
}
|
||||
|
||||
|
||||
function pyjslib_open( $name, $mode="r", $buffering=null ) {
|
||||
return new pyjslib_file( $name, $mode, $buffering );
|
||||
}
|
||||
|
||||
class pyjslib_file implements Iterator {
|
||||
|
||||
private $fh = false;
|
||||
private $current_line = null;
|
||||
|
||||
// public attributes of python file class.
|
||||
public $closed = true;
|
||||
public $encoding = null;
|
||||
public $errors = [];
|
||||
public $mode = null;
|
||||
public $newlines = null;
|
||||
public $softspace = false;
|
||||
|
||||
function __construct($name_or_fd, $mode="r", $buffering=null) {
|
||||
if( is_resource($name_or_fd) ) {
|
||||
$this->fh = $name_or_fd;
|
||||
$this->closed = false;
|
||||
$meta = stream_get_meta_data( $name_or_df );
|
||||
$this->mode = $meta['mode'];
|
||||
return;
|
||||
}
|
||||
$name = $name_or_fd;
|
||||
try {
|
||||
$this->fh = fopen($name, $mode);
|
||||
if( !$this->fh ) {
|
||||
throw new Exception("Could not open $name");
|
||||
}
|
||||
$this->closed = false;
|
||||
$this->mode = $mode;
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new IOError( $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function close() {
|
||||
if( $this->fh ) {
|
||||
fclose( $this->fh );
|
||||
$this->fh = null;
|
||||
$this->closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
function flush() {
|
||||
if( !$this->fh ) {
|
||||
throw new ValueError("File is closed.");
|
||||
}
|
||||
fflush( $this->fh );
|
||||
}
|
||||
|
||||
function fileno() {
|
||||
if( !$this->fh ) {
|
||||
throw new ValueError("File is closed.");
|
||||
}
|
||||
return $this->fh;
|
||||
}
|
||||
|
||||
function isatty() {
|
||||
if( !$this->fh ) {
|
||||
throw new ValueError("File is closed.");
|
||||
}
|
||||
return posix_isatty( $this->fh );
|
||||
}
|
||||
|
||||
/* ---
|
||||
* Begin PHP Iterator implementation
|
||||
* ---
|
||||
*/
|
||||
function rewind() {
|
||||
fseek( $this->fh, 0 );
|
||||
$this->line = 0;
|
||||
}
|
||||
|
||||
function current() {
|
||||
if( !$this->current_line ) {
|
||||
$this->current_line = fgets( $this->fh );
|
||||
}
|
||||
return $this->current_line;
|
||||
}
|
||||
|
||||
function key() {
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
function next() {
|
||||
$this->current(); // ensure current line has been retrieved.
|
||||
$this->current_line = fgets( $this->fh );
|
||||
$this->line ++;
|
||||
return $this->current_line;
|
||||
}
|
||||
|
||||
function valid() {
|
||||
return $this->fh != false && !feof( $this->fh );
|
||||
}
|
||||
/* ---
|
||||
* End PHP Iterator implementation
|
||||
* ---
|
||||
*/
|
||||
|
||||
function read($size=null) {
|
||||
if( $size !== null) {
|
||||
return fread( $this->fh, $size);
|
||||
}
|
||||
return stream_get_contents( $this->fh );
|
||||
}
|
||||
|
||||
function readline($size=null) {
|
||||
return fgets( $this->fh, $size );
|
||||
}
|
||||
|
||||
function readlines($sizehint=null) {
|
||||
$len = 0;
|
||||
$lines = array();
|
||||
while( $line = fgets( $this->fh ) ) {
|
||||
$len += strlen( $line );
|
||||
$lines[] = $line;
|
||||
if( $sizehint && $len >= $sizehint ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
||||
function seek($offset, $whence=SEEK_SET) {
|
||||
return fseek( $this->fh, $offset, $whence);
|
||||
}
|
||||
|
||||
function tell() {
|
||||
return ftell($this->fh);
|
||||
}
|
||||
|
||||
function truncate( $size ) {
|
||||
$rc = ftruncate( $this->fh, $size );
|
||||
}
|
||||
|
||||
function write( $str ) {
|
||||
fwrite( $this->fh, $str );
|
||||
}
|
||||
|
||||
function writelines($sequence) {
|
||||
foreach($sequence as $line) {
|
||||
$this->write( $line );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
570
libpy2php/os.php
Normal file
570
libpy2php/os.php
Normal file
@ -0,0 +1,570 @@
|
||||
<?php
|
||||
|
||||
class OSError extends Exception{
|
||||
}
|
||||
|
||||
|
||||
class os {
|
||||
|
||||
const F_OK = 0x0001;
|
||||
const R_OK = 0x0002;
|
||||
const W_OK = 0x0004;
|
||||
const X_OK = 0x0008;
|
||||
|
||||
const SEEK_SET = SEEK_SET;
|
||||
const SEEK_CUR = SEEK_CUR;
|
||||
const SEEK_END = SEEK_END;
|
||||
|
||||
const EX_OK = 0;
|
||||
const EX_USAGE = 1;
|
||||
const EX_DATAERR = 2;
|
||||
const EX_NOINPUT = 3;
|
||||
const EX_NOUSER = 4;
|
||||
const EX_NOHOST = 5;
|
||||
const EX_UNAVAILABLE = 6;
|
||||
const EX_SOFTWARE = 7;
|
||||
const EX_OSERR = 8;
|
||||
const EX_OSFILE = 9;
|
||||
const EX_CANTCREAT = 10;
|
||||
const EX_IOERR = 11;
|
||||
const EX_TEMPFAIL = 12;
|
||||
const EX_PROTOCOL = 13;
|
||||
const EX_NOPERM = 14;
|
||||
const EX_CONFIG = 15;
|
||||
const EX_NOTFOUND = 16;
|
||||
const EX_ = 17;
|
||||
|
||||
const O_RDONLY = 0x0001;
|
||||
const O_WRONLY = 0x0002;
|
||||
const O_RDWR = 0x0004;
|
||||
const O_APPEND = 0x0008;
|
||||
const O_CREAT = 0x0010;
|
||||
const O_EXCL = 0x0020;
|
||||
const O_TRUNC = 0x0040;
|
||||
|
||||
const TMP_MAX = PHP_INT_MAX;
|
||||
|
||||
public $environ;
|
||||
public $pathconf_names = [];
|
||||
|
||||
static public function ctermid() {
|
||||
return posix_ctermid();
|
||||
}
|
||||
|
||||
static public function getegid() {
|
||||
return posix_getegid();
|
||||
}
|
||||
|
||||
static public function geteuid() {
|
||||
return posix_geteuid();
|
||||
}
|
||||
|
||||
static public function getgid() {
|
||||
return posix_getgid();
|
||||
}
|
||||
|
||||
static public function getgroups() {
|
||||
return posix_getgroups();
|
||||
}
|
||||
|
||||
static public function initgroups($username, $gid) {
|
||||
return posix_initgroups($username, $gid);
|
||||
}
|
||||
|
||||
static public function getlogin() {
|
||||
return posix_getlogin();
|
||||
}
|
||||
|
||||
static public function getpgid() {
|
||||
return posix_getpgid();
|
||||
}
|
||||
|
||||
static public function getpgrp() {
|
||||
return posix_getpgrp();
|
||||
}
|
||||
|
||||
static public function getpid() {
|
||||
return posix_getpid();
|
||||
}
|
||||
|
||||
static public function getresuid() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function getresgid() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function getuid() {
|
||||
return posix_getuid();
|
||||
}
|
||||
|
||||
static public function getenv($varname, $value=null) {
|
||||
return getenv($varname, $value);
|
||||
}
|
||||
|
||||
static public function putenv($varname, $value) {
|
||||
putenv("$varname=$value");
|
||||
}
|
||||
|
||||
static public function setegid($egid) {
|
||||
posix_setegid($egid);
|
||||
}
|
||||
|
||||
static public function seteuid($euid) {
|
||||
posix_seteuid($euid);
|
||||
}
|
||||
|
||||
static public function setgid($gid) {
|
||||
posix_setgid($gid);
|
||||
}
|
||||
|
||||
static public function setgroups($groups) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function setpgrp() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function setpgid($pid, $pgrp) {
|
||||
posix_setpgid($pid, $pgrp);
|
||||
}
|
||||
|
||||
static public function setregid($rgid, $egid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function setresgid($rgid, $egid, $sgid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function setresuid($ruid, $euid, $suid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function setreuid($ruid, $euid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function getsid($pid) {
|
||||
return posix_getsid();
|
||||
}
|
||||
|
||||
static public function setsid() {
|
||||
posix_setsid();
|
||||
}
|
||||
|
||||
static public function setuid($uid) {
|
||||
posix_setuid($uid);
|
||||
}
|
||||
|
||||
static public function strerror($code) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function umask($mask) {
|
||||
umask($mask);
|
||||
}
|
||||
|
||||
static public function uname() {
|
||||
return posix_uname();
|
||||
}
|
||||
|
||||
static public function unsetenv($varname) {
|
||||
unset($_ENV[$varname]);
|
||||
}
|
||||
|
||||
static public function fdopen($fd, $mode=null, $bufsize=null) {
|
||||
return new pyjslib_file($fd);
|
||||
}
|
||||
|
||||
static public function popen($command, $mode=null, $bufsize=null) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function tmpfile() {
|
||||
return tmpfile();
|
||||
}
|
||||
|
||||
static public function popen2($cmd, $mode=null, $bufsize=null) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function popen3($cmd, $mode=null, $bufsize=null) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function popen4($cmd, $mode=null, $bufsize=null) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function close($fd) {
|
||||
fclose( $fd );
|
||||
}
|
||||
|
||||
static public function closerange($fd_low, $fd_high) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function dup($fd) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function dup2($fd) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fchmod($fd, $mode) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fchown($fd, $uid, $gid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fdatasync($fd) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fpathconf($fd, $name) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fstat($fd) {
|
||||
$info = fstat($fd);
|
||||
$obj = new stdClass;
|
||||
foreach($arr as $key => $v) {
|
||||
$attr = "st_" . $key;
|
||||
$obj->$attr = $v;
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
static public function fstatvfs($fd) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function fsync($fd) {
|
||||
fsync($fd);
|
||||
}
|
||||
|
||||
static public function ftruncate($fd, $length) {
|
||||
ftruncate($fd, $length);
|
||||
}
|
||||
|
||||
static public function isatty($fd) {
|
||||
return posix_isatty( $fd );
|
||||
}
|
||||
|
||||
static public function lseek($fd, $pos, $how) {
|
||||
lseek($fd, $pos, $how);
|
||||
}
|
||||
|
||||
static public function open($file, $flags, $mode=0777) {
|
||||
// todo: define and map flag constants. See list at:
|
||||
// https://docs.python.org/2/library/os.html#open-flag-constants
|
||||
|
||||
$fl = '';
|
||||
if( $flags & self::O_RDONLY ) {
|
||||
$fl .= 'r';
|
||||
}
|
||||
if( $flags & self::O_WRONLY ) {
|
||||
$fl .= 'w';
|
||||
}
|
||||
if( $flags & self::O_RDWR ) {
|
||||
$fl .= 'rw';
|
||||
}
|
||||
if( $flags & self::O_APPEND ) {
|
||||
$fl .= 'a';
|
||||
}
|
||||
if( $flags & self::O_CREAT ) {
|
||||
$fl .= 'c';
|
||||
}
|
||||
if( $flags & self::O_EXCL ) {
|
||||
$fl .= 'x';
|
||||
}
|
||||
if( $flags & self::O_TRUNC ) {
|
||||
$fl .= 'w';
|
||||
}
|
||||
|
||||
return fopen($file, $fl, false );
|
||||
}
|
||||
|
||||
static public function pipe() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function read($fd, $n) {
|
||||
return fread( $fd, $n );
|
||||
}
|
||||
|
||||
static public function tcgetpgrp($fd) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function tcsetpgrp($fd, $pg) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static public function ttyname($fd) {
|
||||
return posix_ttyname($fd);
|
||||
}
|
||||
|
||||
static public function write($fd, $str) {
|
||||
return fwrite( $fd, $str );
|
||||
}
|
||||
|
||||
static function access($path, $mode) {
|
||||
return posix_access($path, $mode);
|
||||
}
|
||||
|
||||
static function chdir($path) {
|
||||
chdir( $path );
|
||||
}
|
||||
|
||||
static function fchdir($path) {
|
||||
fchdir( $path );
|
||||
}
|
||||
|
||||
static function getcwd() {
|
||||
return getcwd();
|
||||
}
|
||||
|
||||
static function getcwdu() {
|
||||
return getcwd();
|
||||
}
|
||||
|
||||
static function chflags($path, $flags) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function chroot($path) {
|
||||
chroot($path);
|
||||
}
|
||||
|
||||
static function chmode($path, $mode) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function chown($path, $uid, $gid) {
|
||||
chown($path, $uid, $gid);
|
||||
}
|
||||
|
||||
static function lchflags($path, $flags) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function lchmod($path, $mode) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function lchown($path, $uid, $gid) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function link($source, $link_name) {
|
||||
link($source, $link_name);
|
||||
}
|
||||
|
||||
static function listdir($path) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function lstat($path) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function mkfifo($path, $mode=0666) {
|
||||
posix_mkfifo($path, $mode);
|
||||
}
|
||||
|
||||
static function mknod($filename, $mode=0666, $device=0) {
|
||||
return posix_mknod( $filename, $mode );
|
||||
}
|
||||
|
||||
static function major($path, $flags) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function minor($path, $flags) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function makedev($major, $minor) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function mkdir($path, $mode=0777) {
|
||||
mkdir($path, $mode, $recursive=false);
|
||||
}
|
||||
|
||||
static function makedirs($path, $mode=0777) {
|
||||
mkdir($path, $mode, $recursive=true);
|
||||
}
|
||||
|
||||
static function pathconf($path, $name) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function readlink($path) {
|
||||
return readlink($path);
|
||||
}
|
||||
|
||||
static function remove($path) {
|
||||
if( !is_file( $path ) ) {
|
||||
throw new OSError("Path is not a file. $path");
|
||||
}
|
||||
try {
|
||||
unlink( $path );
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new OSError( $e->getMessage(), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
static function removedirs($path) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function rename($src, $dst) {
|
||||
if( is_dir($dst)) {
|
||||
throw new OSError("Destination is a directory. $dst");
|
||||
}
|
||||
rename($src, $dst);
|
||||
}
|
||||
|
||||
static function renames($old, $new) {
|
||||
self::makedirs( dirname($new) );
|
||||
self::rename($old, $new);
|
||||
}
|
||||
|
||||
static function rmdir($path) {
|
||||
rmdir($pat);
|
||||
}
|
||||
|
||||
static function stat($path) {
|
||||
$arr = stat($path);
|
||||
if(!$arr) {
|
||||
throw new OSError("Path does not exist. $path");
|
||||
}
|
||||
$obj = new stdClass;
|
||||
foreach($arr as $key => $v) {
|
||||
$attr = "st_" . $key;
|
||||
$obj->$attr = $v;
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
static function stat_float_times($newvalue=null) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function statvfs() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function symlink($source, $link_name) {
|
||||
symlink($source, $link_name);
|
||||
}
|
||||
|
||||
static function tempnam($dir=null, $prefix='') {
|
||||
if( !$dir ) {
|
||||
$dir = sys_get_temp_dir() ;
|
||||
}
|
||||
$name = tempnam($dir, $prefix);
|
||||
unlink($name);
|
||||
return $name;
|
||||
}
|
||||
|
||||
static function tmpnam() {
|
||||
return self::tempnam();
|
||||
}
|
||||
|
||||
static function unlink($path) {
|
||||
unlink($path);
|
||||
}
|
||||
|
||||
static function utime($path, $times) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function walk($top, $topdown=true, $onerror=null, $followlinks=false) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin Process Management
|
||||
*/
|
||||
|
||||
static function abort() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execl($path, $arg0, $arg1) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execle($path, $arg0, $arg1, $env) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execlp($file, $arg0, $arg1) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execlpe($file, $arg0, $arg1, $env) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execv($path, $args) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execve($path, $args, $env) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execvp($file, $args) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function execvpe($file, $args, $env) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function _exit($n) {
|
||||
exit($n);
|
||||
}
|
||||
|
||||
static function fork() {
|
||||
return pcntl_fork();
|
||||
}
|
||||
|
||||
static function forkpty() {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function kill($pid, $sig) {
|
||||
posix_kill($pid, $sig);
|
||||
}
|
||||
|
||||
static function killpg($pgid, $sig) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function nice($increment) {
|
||||
proc_nice($increment);
|
||||
}
|
||||
|
||||
static function plock($op) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static function _unimplemented() {
|
||||
throw new Exception( "Unimplemented. Please consider submitting a patch to py2php project on github.");
|
||||
}
|
||||
}
|
||||
|
214
libpy2php/os_path.php
Normal file
214
libpy2php/os_path.php
Normal file
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/os.php');
|
||||
|
||||
/**
|
||||
* A class to emulate python's os.path
|
||||
*/
|
||||
class os_path {
|
||||
|
||||
const supports_unicode_filenames = true;
|
||||
|
||||
static function abspath($path) {
|
||||
return self::normpath(self::join(getcwd(), $path));
|
||||
}
|
||||
|
||||
static function basename($path) {
|
||||
// is this right?
|
||||
return basename($path);
|
||||
}
|
||||
|
||||
static function commonprefix($list) {
|
||||
$pl = 0; // common prefix length
|
||||
$n = count($list);
|
||||
$l = strlen($list[0]);
|
||||
while ($pl < $l) {
|
||||
$c = $list[0][$pl];
|
||||
for ($i=1; $i<$n; $i++) {
|
||||
if ($list[$i][$pl] !== $c) {
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
$pl++;
|
||||
}
|
||||
return substr($list[0], 0, $pl);
|
||||
}
|
||||
|
||||
static function dirname($path) {
|
||||
return dirname($path);
|
||||
}
|
||||
|
||||
static function exists($path) {
|
||||
return file_exists($path);
|
||||
}
|
||||
|
||||
static function lexists($path) {
|
||||
$rc = file_exists($path);
|
||||
if( !$rc && is_link($path) ) {
|
||||
return true;
|
||||
}
|
||||
return $rc;
|
||||
}
|
||||
|
||||
static function expanduser($path) {
|
||||
if( strpos($path, '~') !== false) {
|
||||
$info = posix_getpwuid(posix_getuid());
|
||||
$path = str_replace('~', $info['dir'], $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
static function expandvars($path) {
|
||||
$env = count($_ENV) ?: $_SERVER;
|
||||
$map = array();
|
||||
foreach( $env as $k => $v ) {
|
||||
if( !is_scalar( $v )) {
|
||||
continue;
|
||||
}
|
||||
$map['$' . $k] = $v;
|
||||
$map['${' . $k . '}'] = $v;
|
||||
}
|
||||
return strtr($path, $map);
|
||||
}
|
||||
|
||||
static function getatime($path) {
|
||||
try {
|
||||
$rc = fileatime($path);
|
||||
return $rc;
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new OSError($e->getMessage, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
static function getmtime($path) {
|
||||
try {
|
||||
$rc = filemtime($path);
|
||||
return $rc;
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new OSError($e->getMessage, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
static function getctime($path) {
|
||||
try {
|
||||
$rc = filectime($path);
|
||||
return $rc;
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new OSError($e->getMessage, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
static function getsize($path) {
|
||||
try {
|
||||
$rc = filesize($path);
|
||||
return $rc;
|
||||
}
|
||||
catch( Exception $e ) {
|
||||
throw new OSError($e->getMessage, $e->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
static function isabs($path) {
|
||||
// fixme: implement check for windows.
|
||||
return $path[0] == '/';
|
||||
}
|
||||
|
||||
static function isfile($path) {
|
||||
return is_file($path);
|
||||
}
|
||||
|
||||
static function isdir($path) {
|
||||
return is_dir($path);
|
||||
}
|
||||
|
||||
static function islink($path) {
|
||||
return is_link($path);
|
||||
}
|
||||
|
||||
static function ismount($path) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function split($path) {
|
||||
$parts = explode(DIRECTORY_SEPARATOR, $path);
|
||||
$first = implode(DIRECTORY_SEPARATOR, array_slice($parts, 0, count($parts)-1 ));
|
||||
$last = $parts[count($parts)-1];
|
||||
return array($first, $last);
|
||||
}
|
||||
|
||||
static function join($path, ...$paths) {
|
||||
$buf = rtrim($path, '/');
|
||||
foreach( $paths as $p ) {
|
||||
$i = 0;
|
||||
$p = trim( $p, '/');
|
||||
$buf .= DIRECTORY_SEPARATOR . $p;
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
static function normcase($path) {
|
||||
// fixme: different behavior on windows.
|
||||
return $path;
|
||||
}
|
||||
|
||||
static function normpath($path) {
|
||||
return realpath($path);
|
||||
}
|
||||
|
||||
static function realpath($path) {
|
||||
return realpath($path);
|
||||
}
|
||||
|
||||
static function relpath($path, $start) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function samefile($path1, $path2) {
|
||||
return fileinode($path1) == fileinode($path2);
|
||||
}
|
||||
|
||||
static function sameopenfile($fd1, $fd2) {
|
||||
$s1 = fstat( $fd1 );
|
||||
$s2 = fstat( $fd2 );
|
||||
return $s1['ino'] == $s2['ino'];
|
||||
}
|
||||
|
||||
static function samestat($stat1, $stat2) {
|
||||
return $stat1 == $stat2;
|
||||
}
|
||||
|
||||
static function splitdrive($path) {
|
||||
//fixme: implement windows case.
|
||||
return array('', $path);
|
||||
}
|
||||
|
||||
static function splitext($path) {
|
||||
$first = $path;
|
||||
$second = '';
|
||||
|
||||
$pos = strrpos( $path, '.');
|
||||
if( $pos !== false ) {
|
||||
$first = substr($path, 0, $pos);
|
||||
$second = substr($path, $pos);
|
||||
}
|
||||
|
||||
return array($first, $second);
|
||||
}
|
||||
|
||||
static function splitunc($path) {
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
static function walk($path, $visit, $arg) {
|
||||
// Note: deprecated in python 3 in favor of os.walk()
|
||||
self::_unimplemented();
|
||||
}
|
||||
|
||||
private static function _unimplemented() {
|
||||
throw new Exception( "Unimplemented. Please consider submitting a patch to py2php project on github.");
|
||||
}
|
||||
|
||||
}
|
134
libpy2php/strict_mode.php
Normal file
134
libpy2php/strict_mode.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This will initialize strict mode. It is safe to be called multiple times per process
|
||||
* eg in the event that a 3rd party lib overrides an error or exception handler.
|
||||
*
|
||||
* It is called in this file; the parent php file(s) should use require_once and do
|
||||
* not need to make any call.
|
||||
*/
|
||||
function init_strict_mode() {
|
||||
|
||||
// these are safe to call multiple times per process without dups.
|
||||
error_reporting( E_ALL | E_STRICT );
|
||||
restore_strict_error_handler();
|
||||
restore_strict_exception_handler();
|
||||
|
||||
// register_shutdown_function should only be called once per process to avoid dups.
|
||||
static $called = false;
|
||||
if( !$called ) {
|
||||
|
||||
register_shutdown_function( "shutdown_handler" );
|
||||
$called = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function restores the error handler if it should get overridden
|
||||
* eg by a 3rd party lib. Any error handlers that were registered after
|
||||
* ours are removed.
|
||||
*/
|
||||
function restore_strict_error_handler() {
|
||||
|
||||
$e_handler_name = function() {
|
||||
$name = set_error_handler('restore_strict_error_handler'); // will never be used.
|
||||
restore_error_handler();
|
||||
return $name;
|
||||
};
|
||||
|
||||
while( !in_array( $e_handler_name(), array( '_global_error_handler', null ) ) ) {
|
||||
restore_error_handler();
|
||||
}
|
||||
if( !$e_handler_name() ) {
|
||||
set_error_handler( '_global_error_handler' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function restores the exception handler if it should get overridden
|
||||
* eg by a 3rd party lib. Any error handlers that were registered after
|
||||
* ours are removed.
|
||||
*/
|
||||
function restore_strict_exception_handler() {
|
||||
|
||||
$exc_handler_name = function() {
|
||||
$name = set_exception_handler('restore_strict_exception_handler'); // will never be used.
|
||||
restore_exception_handler();
|
||||
return $name;
|
||||
};
|
||||
|
||||
while( !in_array( $exc_handler_name(), array( '_global_exception_handler', null ) ) ) {
|
||||
restore_exception_handler();
|
||||
}
|
||||
if( !$exc_handler_name() ) {
|
||||
set_exception_handler( '_global_exception_handler' );
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* This error handler callback will be called for every type of PHP notice/warning/error.
|
||||
*
|
||||
* We aspire to write solid code. everything is an exception, even minor warnings.
|
||||
*
|
||||
* However, we allow the @operator in the code to override.
|
||||
*/
|
||||
function _global_error_handler($errno, $errstr, $errfile, $errline ) {
|
||||
|
||||
/* from php.net
|
||||
* error_reporting() settings will have no effect and your error handler will
|
||||
* be called regardless - however you are still able to read the current value of
|
||||
* 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.
|
||||
*/
|
||||
if( !error_reporting() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* This exception handler callback will be called for any exceptions that the application code does not catch.
|
||||
*/
|
||||
function _global_exception_handler( Exception $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( "\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;
|
||||
// error_log( $msg );
|
||||
strict_mode_mail_admin( 'Uncaught exception!', $msg );
|
||||
echo "\n\nNow exiting. Please report this problem to the software author\n\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This shutdown handler callback prints a message and sends email on any PHP fatal error
|
||||
*/
|
||||
function shutdown_handler() {
|
||||
|
||||
$error = error_get_last();
|
||||
|
||||
$ignore = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_STRICT | E_DEPRECATED | E_USER_DEPRECATED;
|
||||
if ( $error && ($error['type'] & $ignore) == 0) {
|
||||
|
||||
// error keys: type, file, line, message
|
||||
$msg = "Ouch! Encountered PHP Fatal Error. Shutting down.\n" . print_r( $error, true );
|
||||
echo $msg;
|
||||
strict_mode_mail_admin( 'PHP Fatal Error!', $msg );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* email admin if defined
|
||||
*/
|
||||
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') ) {
|
||||
mail( ALERTS_MAIL_TO, $subject, $msg );
|
||||
}
|
||||
else {
|
||||
echo "\nWARNING: ALERTS_MAIL_TO not defined in environment. alert not sent with subject: $subject\n";
|
||||
}
|
||||
}
|
BIN
mtproto.php
Executable file
BIN
mtproto.php
Executable file
Binary file not shown.
171
prime.php
Normal file
171
prime.php
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('random.php');
|
||||
function primesbelow($N) {
|
||||
$correction = (($N % 6) > 1);
|
||||
$N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1) ][($N % 6) ];
|
||||
$sieve = ([true] * ($N / 3));
|
||||
$sieve[0] = false;
|
||||
foreach (pyjslib_range(((pyjslib_int(pow($N, 0.5)) / 3) + 1)) as $i) {
|
||||
if ($sieve[$i]) {
|
||||
$k = ((3 * $i) + 1) | 1;
|
||||
$sieve[(($k * $k) / 3), null, (2 * $k) ] = // finish this
|
||||
([false] * ((((($N / 6) - (($k * $k) / 6)) - 1) / $k) + 1));
|
||||
$sieve[(((($k * $k) + (4 * $k)) - ((2 * $k) * ($i % 2))) / 3), null, (2 * $k) ] = ([false] * ((((($N / 6) - (((($k * $k) + (4 * $k)) - ((2 * $k) * ($i % 2))) / 6)) - 1) / $k) + 1));
|
||||
}
|
||||
}
|
||||
// finish this
|
||||
return ([2, 3] + [(3 * $i + 1) | 1 for $i in range(1, floor($N/3) - $correction) if $sieve[$i]]
|
||||
);
|
||||
}
|
||||
$smallprimeset = set(primesbelow(100000));
|
||||
$_smallprimeset = 100000;
|
||||
function isprime($n, $precision = 7) {
|
||||
if (($n == 1) || (($n % 2) == 0)) {
|
||||
return false;
|
||||
} else if (($n < 1)) {
|
||||
throw new $ValueError('Out of bounds, first argument must be > 0');
|
||||
} else if (($n < $_smallprimeset)) {
|
||||
return in_array($n, $smallprimeset);
|
||||
}
|
||||
$d = ($n - 1);
|
||||
$s = 0;
|
||||
while ((($d % 2) == 0)) {
|
||||
$d
|
||||
//= 2;
|
||||
$s+= 1;
|
||||
}
|
||||
foreach (pyjslib_range($precision) as $repeat) {
|
||||
$a = random::randrange(2, ($n - 2));
|
||||
$x = pow($a, $d, $n);
|
||||
if (($x == 1) || ($x == ($n - 1))) {
|
||||
continue;
|
||||
}
|
||||
foreach (pyjslib_range(($s - 1)) as $r) {
|
||||
$x = pow($x, 2, $n);
|
||||
if (($x == 1)) {
|
||||
return false;
|
||||
}
|
||||
if (($x == ($n - 1))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function pollard_brent($n) {
|
||||
if ((($n % 2) == 0)) {
|
||||
return 2;
|
||||
}
|
||||
if ((($n % 3) == 0)) {
|
||||
return 3;
|
||||
}
|
||||
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];
|
||||
while (($g == 1)) {
|
||||
$x = $y;
|
||||
foreach (pyjslib_range($r) as $i) {
|
||||
$y = ((pow($y, 2, $n) + $c) % $n);
|
||||
}
|
||||
$k = 0;
|
||||
while (($k < $r) && ($g == 1)) {
|
||||
$ys = $y;
|
||||
foreach (pyjslib_range(min($m, ($r - $k))) as $i) {
|
||||
$y = ((pow($y, 2, $n) + $c) % $n);
|
||||
$q = (($q * abs(($x - $y))) % $n);
|
||||
}
|
||||
$g = gcd($q, $n);
|
||||
$k+= $m;
|
||||
}
|
||||
$r*= 2;
|
||||
}
|
||||
if (($g == $n)) {
|
||||
while (true) {
|
||||
$ys = ((pow($ys, 2, $n) + $c) % $n);
|
||||
$g = gcd(abs(($x - $ys)), $n);
|
||||
if (($g > 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $g;
|
||||
}
|
||||
$smallprimes = primesbelow(10000);
|
||||
function primefactors($n, $sort = false) {
|
||||
$factors = [];
|
||||
$limit = (pyjslib_int(pow($n, 0.5)) + 1);
|
||||
foreach ($smallprimes as $checker) {
|
||||
if (($checker > $limit)) {
|
||||
break;
|
||||
}
|
||||
while ((($n % $checker) == 0)) {
|
||||
$factors[] = $checker;
|
||||
$n
|
||||
//= $checker;
|
||||
$limit = (pyjslib_int(pow($n, 0.5)) + 1);
|
||||
if (($checker > $limit)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($n < 2)) {
|
||||
return $factors;
|
||||
}
|
||||
while (($n > 1)) {
|
||||
if (isprime($n)) {
|
||||
$factors[] = $n;
|
||||
break;
|
||||
}
|
||||
$factor = pollard_brent($n);
|
||||
$factors->extend(primefactors($factor));
|
||||
$n
|
||||
//= $factor;
|
||||
|
||||
}
|
||||
if ($sort) {
|
||||
$factors->sort();
|
||||
}
|
||||
return $factors;
|
||||
}
|
||||
function factorization($n) {
|
||||
$factors = [];
|
||||
foreach (primefactors($n) as $p1) {
|
||||
try {
|
||||
$factors[$p1]+= 1;
|
||||
}
|
||||
catch(KeyError $e) {
|
||||
$factors[$p1] = 1;
|
||||
}
|
||||
}
|
||||
return $factors;
|
||||
}
|
||||
$totients = [];
|
||||
function totient($n) {
|
||||
if (($n == 0)) {
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
return $totients[$n];
|
||||
}
|
||||
catch(KeyError $e) {
|
||||
}
|
||||
$tot = 1;
|
||||
foreach (factorization($n)->items() as list($p, $exp)) {
|
||||
$tot*= (($p - 1) * pow($p, ($exp - 1)));
|
||||
}
|
||||
$totients[$n] = $tot;
|
||||
return $tot;
|
||||
}
|
||||
function gcd($a, $b) {
|
||||
if (($a == $b)) {
|
||||
return $a;
|
||||
}
|
||||
while (($b > 0)) {
|
||||
list($a, $b) = [$b, ($a % $b) ];
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
function lcm($a, $b) {
|
||||
return (abs(($a * $b)) / gcd($a, $b));
|
||||
}
|
14
telepy.php
Normal file
14
telepy.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('argparse.php');
|
||||
if (($__name__ == '__main__')) {
|
||||
$parser = py2php_kwargs_function_call('argparse::ArgumentParser', ['telepy'], ["description" => 'Python implementation of telegram API.']);
|
||||
py2php_kwargs_method_call($parser, 'add_argument', ['command'], ["nargs" => '?', "choices" => (['cmd', 'dialog_list', 'contact_list'] + /* py2php.fixme listcomp unsupported. */
|
||||
) ]);
|
||||
py2php_kwargs_method_call($parser, 'add_argument', ['args'], ["nargs" => '*']);
|
||||
$args = $parser->parse_args();
|
||||
if (($args->command == null)) {
|
||||
new TelepyShell()->cmdloop();
|
||||
}
|
||||
}
|
22
testing.php
Normal file
22
testing.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
require_once ('os.php');
|
||||
try {
|
||||
require_once ('configparser.php');
|
||||
}
|
||||
catch(ImportError $e) {
|
||||
require_once ('ConfigParser.php');
|
||||
}
|
||||
require_once ('mtproto.php');
|
||||
$config = $configparser->ConfigParser();
|
||||
if (!($config->read('credentials'))) {
|
||||
pyjslib_printnl('File \'credentials\' seems to not exist.');
|
||||
$exit(-1);
|
||||
}
|
||||
$ip = $config->get('App data', 'ip_address');
|
||||
$port = $config->getint('App data', 'port');
|
||||
$Session = mtproto::Session($ip, $port);
|
||||
Session::create_auth_key();
|
||||
$future_salts = py2php_kwargs_function_call('Session::method_call', ['get_future_salts'], ["num" => 3]);
|
||||
pyjslib_printnl($future_salts);
|
24
tests/SHA.php.tmp
Normal file
24
tests/SHA.php.tmp
Normal file
@ -0,0 +1,24 @@
|
||||
--------------------------
|
||||
- BEGIN OF Serialization -
|
||||
--------------------------
|
||||
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
|
||||
--------------------------
|
||||
- END OF Serialization -
|
||||
--------------------------
|
||||
|
||||
--------------------------
|
||||
- BEGIN OF Serialization -
|
||||
--------------------------
|
||||
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once ('libpy2php.php');
|
||||
|
||||
--------------------------
|
||||
- END OF Serialization -
|
||||
--------------------------
|
||||
|
4
tests/Serialization
Normal file
4
tests/Serialization
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
|
||||
require_once('libpy2php.php');
|
||||
|
Loading…
Reference in New Issue
Block a user