Let the madness begin!

This commit is contained in:
danogentili 2016-06-23 23:51:08 +02:00
parent 433e9bc5d3
commit b5326b4cbb
22 changed files with 2701 additions and 69 deletions

554
AES.class.php Normal file
View 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;
}
}
?>

View File

@ -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.

BIN
TL.php Normal file

Binary file not shown.

4
classes/__init__.php Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

171
prime.php Normal file
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,4 @@
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . DIRECTORY_SEPARATOR . 'libpy2php');
require_once('libpy2php.php');