MadelineProto/libpy2php/libpy2php.php

525 lines
12 KiB
PHP
Raw Normal View History

2016-06-23 23:51:08 +02:00
<?php
2016-07-14 15:15:50 +02:00
// 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.
2016-06-23 23:51:08 +02:00
/**
2016-07-14 15:15:50 +02:00
* This call makes three things happen:.
2016-06-23 23:51:08 +02:00
*
* 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
*/
2016-07-14 15:15:50 +02:00
require_once dirname(__FILE__).DIRECTORY_SEPARATOR.'strict_mode.php';
2016-06-23 23:51:08 +02:00
init_strict_mode();
2016-07-14 15:15:50 +02:00
// iteration from Bob Ippolito's Iteration in JavaScript
// pyjs_extend from Kevin Lindsey's Inteheritance Tutorial (http://www.kevlindev.com/tutorials/javascript/inheritance/)
2016-06-23 23:51:08 +02:00
2016-07-14 15:15:50 +02:00
// type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
function pyjslib_isObject($a)
{
2016-06-23 23:51:08 +02:00
return is_object($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isFunction($a)
{
2016-06-23 23:51:08 +02:00
return is_function($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isString($a)
{
2016-06-23 23:51:08 +02:00
return is_string($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isNull($a)
{
2016-06-23 23:51:08 +02:00
return is_null($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isArray($a)
{
2016-06-23 23:51:08 +02:00
return is_array($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isUndefined($a)
{
2016-06-23 23:51:08 +02:00
return !isset($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_isIteratable($a)
{
2016-06-23 23:51:08 +02:00
return $a instanceof Traversable;
}
2016-07-14 15:15:50 +02:00
function pyjslib_isNumber($a)
{
2016-06-23 23:51:08 +02:00
return is_numeric($a);
}
2016-07-14 15:15:50 +02:00
function pyjslib_int($a)
{
return (int) $a;
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
function pyjslib_str($val)
{
return (string) $val;
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
function pyjslib_del_slice(&$list, $from, $to, $step = 1)
{
if ($from <= 0) {
2016-06-23 23:51:08 +02:00
$from = 0;
}
2016-07-14 15:15:50 +02:00
if ($to === null) {
2016-06-23 23:51:08 +02:00
$to = count($list);
}
2016-07-14 15:15:50 +02:00
if ($step <= 0) {
2016-06-23 23:51:08 +02:00
$step = 1;
}
2016-07-14 15:15:50 +02:00
for ($i = $from; $i < $to; $i += $step) {
unset($list[$i]);
2016-06-23 23:51:08 +02:00
}
}
2016-07-14 15:15:50 +02:00
function pyjslib_array_slice($list, $from, $to, $step = 1)
{
2016-06-23 23:51:08 +02:00
$newlist = [];
2016-07-14 15:15:50 +02:00
if ($from <= 0) {
2016-06-23 23:51:08 +02:00
$from = 0;
}
2016-07-14 15:15:50 +02:00
if ($to === null) {
2016-06-23 23:51:08 +02:00
$to = count($list);
}
2016-07-14 15:15:50 +02:00
if ($step <= 0) {
2016-06-23 23:51:08 +02:00
$step = 1;
}
2016-07-14 15:15:50 +02:00
for ($i = $from; $i < $to; $i += $step) {
2016-06-23 23:51:08 +02:00
$newlist[] = $list[$i];
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $newlist;
}
2016-07-14 15:15:50 +02:00
// taken from mochikit: range( [start,] stop[, step] )
function pyjslib_range($start, $stop = null, $step = 1)
{
if ($stop === null) {
2016-06-23 23:51:08 +02:00
$stop = $start;
$start = 0;
}
2016-07-14 15:15:50 +02:00
if ($stop <= $start && $step < 0) {
$arr = range($stop, $start, -$step);
array_pop($arr);
return array_reverse($arr, false);
2016-06-23 23:51:08 +02:00
}
2016-07-29 17:19:34 +02:00
if ($step > 1 && $step > ($stop - $start)) {
$arr = [$start];
2016-07-20 17:34:23 +02:00
} else {
$arr = range($start, $stop, $step);
array_pop($arr);
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $arr;
}
2016-07-14 15:15:50 +02:00
function pyjslib_filter($callback, $iterable)
{
2016-06-23 23:51:08 +02:00
$a = [];
2016-07-14 15:15:50 +02:00
foreach ($iterable as $item) {
if (call_user_func($callback, $item)) {
2016-06-23 23:51:08 +02:00
$a[] = $item;
}
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $a;
}
2016-07-14 15:15:50 +02:00
function pyjslib_globals()
{
2016-06-23 23:51:08 +02:00
return $GLOBALS;
}
2016-07-14 15:15:50 +02:00
function pyjslib_map($callable)
{
2016-06-23 23:51:08 +02:00
$done = false;
$call_cnt = 0;
$results = [];
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
$params = func_get_args();
2016-07-14 15:15:50 +02:00
array_shift($params);
while (!$done) {
2016-06-23 23:51:08 +02:00
$func_args = [];
$found = false;
2016-07-14 15:15:50 +02:00
for ($i = 0; $i < count($params); $i++) {
2016-06-23 23:51:08 +02:00
$func_args[] = @$params[$i][$call_cnt];
2016-07-14 15:15:50 +02:00
if (count($params[$i]) > $call_cnt + 1) {
2016-06-23 23:51:08 +02:00
$found = true;
}
}
2016-07-14 15:15:50 +02:00
if (!$found) {
2016-06-23 23:51:08 +02:00
$done = true;
}
$results[] = call_user_func_array($callable, $func_args);
2016-07-14 15:15:50 +02:00
$call_cnt++;
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $results;
}
2016-07-14 15:15:50 +02:00
function pyjslib_zip()
{
2016-06-23 23:51:08 +02:00
$params = func_get_args();
2016-07-14 15:15:50 +02:00
if (count($params) === 1) { // this case could be probably cleaner
2016-06-23 23:51:08 +02:00
// single iterable passed
2016-07-14 15:15:50 +02:00
$result = [];
foreach ($params[0] as $item) {
$result[] = [$item];
}
2016-06-23 23:51:08 +02:00
return $result;
2016-07-14 15:15:50 +02:00
}
$result = call_user_func_array('array_map', array_merge([null], $params));
2016-06-23 23:51:08 +02:00
$length = min(array_map('count', $params));
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return array_slice($result, 0, $length);
}
function pyjslib_is_assoc($arr)
{
return array_keys($arr) !== range(0, count($arr) - 1);
}
2016-07-14 15:15:50 +02:00
function pyjslib_dict($arg = null)
{
if ($arg === null) {
2016-06-23 23:51:08 +02:00
return [];
}
2016-07-14 15:15:50 +02:00
if (pyjslib_is_assoc($arg)) {
2016-06-23 23:51:08 +02:00
return $arg;
}
$dict = [];
2016-07-14 15:15:50 +02:00
foreach ($arg as $a) {
if (count($a) == 2) {
2016-06-23 23:51:08 +02:00
$dict[$a[0]] = $a[1];
}
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $dict;
}
2016-07-14 15:15:50 +02:00
function pyjslib_printWorker($objs, $nl, $multi_arg, $depth = 1)
{
2016-06-23 23:51:08 +02:00
$buf = '';
2016-07-14 15:15:50 +02:00
if (is_array($objs) && $multi_arg && $depth == 1) {
2016-06-23 23:51:08 +02:00
$cnt = 0;
2016-07-14 15:15:50 +02:00
foreach ($objs as $obj) {
if ($cnt++ > 0) {
$buf .= ' ';
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
$buf .= pyjslib_printWorker($obj, $nl, $multi_arg, $depth + 1);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
} elseif (is_bool($objs)) {
$buf = $objs ? 'True' : 'False';
} elseif (is_null($objs)) {
2016-06-23 23:51:08 +02:00
$buf = 'None';
2016-07-14 15:15:50 +02:00
} elseif (is_float($objs)) {
$buf = (int) $objs;
} elseif (is_string($objs) && ($multi_arg && $depth > 2 || (!$multi_arg && $depth > 1))) {
2016-06-23 23:51:08 +02:00
$buf = "'$objs'";
2016-07-14 15:15:50 +02:00
} elseif (is_array($objs)) {
2016-06-23 23:51:08 +02:00
$buf = '[';
$cnt = 0;
2016-07-14 15:15:50 +02:00
foreach ($objs as $obj) {
2016-06-23 23:51:08 +02:00
$val = pyjslib_printWorker($obj, $nl, false, $depth + 1);
2016-07-14 15:15:50 +02:00
if ($cnt++ > 0) {
2016-06-23 23:51:08 +02:00
$buf .= ', ';
}
$buf .= $val;
}
2016-07-14 15:15:50 +02:00
$buf .= ']';
2016-06-23 23:51:08 +02:00
// $buf = '[' . implode( ", ", $objs ) . ']';
2016-07-14 15:15:50 +02:00
} else {
2016-06-23 23:51:08 +02:00
$buf = $objs;
}
2016-07-14 15:15:50 +02:00
if ($depth == 1 && (!strlen($buf) || $buf[strlen($buf) - 1] != "\n")) {
$buf .= $nl ? "\n" : ' ';
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $buf;
}
2016-07-14 15:15:50 +02:00
function pyjslib_repr($obj)
{
2016-06-23 23:51:08 +02:00
return pyjslib_printWorker($obj, false, false);
}
2016-07-14 15:15:50 +02:00
function pyjslib_print($objs, $multi_arg = false)
{
2016-06-23 23:51:08 +02:00
echo pyjslib_printWorker($objs, false, $multi_arg);
}
2016-07-14 15:15:50 +02:00
function pyjslib_printnl($objs, $multi_arg = false)
{
2016-06-23 23:51:08 +02:00
echo pyjslib_printWorker($objs, true, $multi_arg);
}
2016-07-14 15:15:50 +02:00
function py2php_kwargs_function_call($funcname, $ordered, $named)
{
if ($funcname == 'array' || $funcname == 'pyjslib_dict') {
2016-06-23 23:51:08 +02:00
return $named;
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
$num_ordered = count($ordered);
$count = 1;
$refFunc = new ReflectionFunction($funcname);
2016-07-14 15:15:50 +02:00
foreach ($refFunc->getParameters() as $param) {
if ($param->isVariadic()) {
$ordered[$count - 1] = $named;
2016-06-23 23:51:08 +02:00
break;
}
//invokes ReflectionParameter::__toString
2016-07-14 15:15:50 +02:00
if ($count > $num_ordered) {
2016-06-23 23:51:08 +02:00
$name = $param->name;
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
$ordered[] = @$named[$name] ?: $default;
}
2016-07-14 15:15:50 +02:00
$count++;
2016-06-23 23:51:08 +02:00
}
//var_dump($ordered);
return call_user_func_array($funcname, $ordered);
}
2016-07-14 15:15:50 +02:00
function py2php_kwargs_method_call($obj, $method, $ordered, $named)
{
2016-06-23 23:51:08 +02:00
$num_ordered = count($ordered);
$count = 1;
$refFunc = new ReflectionMethod($obj, $method);
2016-07-14 15:15:50 +02:00
foreach ($refFunc->getParameters() as $param) {
2016-06-23 23:51:08 +02:00
//invokes ReflectionParameter::__toString
2016-07-14 15:15:50 +02:00
if ($count > $num_ordered) {
2016-06-23 23:51:08 +02:00
$name = $param->name;
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
$ordered[] = @$named[$name] ?: $default;
}
2016-07-14 15:15:50 +02:00
$count++;
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
$callable = [$obj, $method];
2016-06-23 23:51:08 +02:00
return call_user_func_array($callable, $ordered);
}
2016-07-14 15:15:50 +02:00
class IOError extends Exception
{
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
class ValueError extends Exception
{
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
function pyjslib_open($name, $mode = 'r', $buffering = null)
{
return new pyjslib_file($name, $mode, $buffering);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
class pyjslib_file implements Iterator
{
2016-06-23 23:51:08 +02:00
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;
2016-07-14 15:15:50 +02:00
public function __construct($name_or_fd, $mode = 'r', $buffering = null)
{
if (is_resource($name_or_fd)) {
2016-06-23 23:51:08 +02:00
$this->fh = $name_or_fd;
$this->closed = false;
2016-07-14 15:15:50 +02:00
$meta = stream_get_meta_data($name_or_df);
2016-06-23 23:51:08 +02:00
$this->mode = $meta['mode'];
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return;
}
$name = $name_or_fd;
try {
$this->fh = fopen($name, $mode);
2016-07-14 15:15:50 +02:00
if (!$this->fh) {
2016-06-23 23:51:08 +02:00
throw new Exception("Could not open $name");
}
$this->closed = false;
$this->mode = $mode;
2016-07-14 15:15:50 +02:00
} catch (Exception $e) {
throw new IOError($e->getMessage(), $e->getCode());
2016-06-23 23:51:08 +02:00
}
}
2016-07-14 15:15:50 +02:00
public function close()
{
if ($this->fh) {
fclose($this->fh);
2016-06-23 23:51:08 +02:00
$this->fh = null;
$this->closed = true;
}
}
2016-07-14 15:15:50 +02:00
public function flush()
{
if (!$this->fh) {
throw new ValueError('File is closed.');
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
fflush($this->fh);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function fileno()
{
if (!$this->fh) {
throw new ValueError('File is closed.');
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $this->fh;
}
2016-07-14 15:15:50 +02:00
public function isatty()
{
if (!$this->fh) {
throw new ValueError('File is closed.');
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
return posix_isatty($this->fh);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
/* ---
* Begin PHP Iterator implementation
* ---
*/
2016-07-14 15:15:50 +02:00
public function rewind()
{
fseek($this->fh, 0);
2016-06-23 23:51:08 +02:00
$this->line = 0;
}
2016-07-14 15:15:50 +02:00
public function current()
{
if (!$this->current_line) {
$this->current_line = fgets($this->fh);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $this->current_line;
}
2016-07-14 15:15:50 +02:00
public function key()
{
2016-06-23 23:51:08 +02:00
return $this->line;
}
2016-07-14 15:15:50 +02:00
public function next()
{
2016-06-23 23:51:08 +02:00
$this->current(); // ensure current line has been retrieved.
2016-07-14 15:15:50 +02:00
$this->current_line = fgets($this->fh);
$this->line++;
2016-06-23 23:51:08 +02:00
return $this->current_line;
}
2016-07-14 15:15:50 +02:00
public function valid()
{
return $this->fh != false && !feof($this->fh);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
/* ---
* End PHP Iterator implementation
* ---
*/
2016-07-14 15:15:50 +02:00
public function read($size = null)
{
if ($size !== null) {
return fread($this->fh, $size);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
return stream_get_contents($this->fh);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function readline($size = null)
{
return fgets($this->fh, $size);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function readlines($sizehint = null)
{
2016-06-23 23:51:08 +02:00
$len = 0;
2016-07-14 15:15:50 +02:00
$lines = [];
while ($line = fgets($this->fh)) {
$len += strlen($line);
2016-06-23 23:51:08 +02:00
$lines[] = $line;
2016-07-14 15:15:50 +02:00
if ($sizehint && $len >= $sizehint) {
2016-06-23 23:51:08 +02:00
break;
}
}
2016-07-14 15:15:50 +02:00
2016-06-23 23:51:08 +02:00
return $lines;
}
2016-07-14 15:15:50 +02:00
public function seek($offset, $whence = SEEK_SET)
{
return fseek($this->fh, $offset, $whence);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function tell()
{
2016-06-23 23:51:08 +02:00
return ftell($this->fh);
}
2016-07-14 15:15:50 +02:00
public function truncate($size)
{
$rc = ftruncate($this->fh, $size);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function write($str)
{
fwrite($this->fh, $str);
2016-06-23 23:51:08 +02:00
}
2016-07-14 15:15:50 +02:00
public function writelines($sequence)
{
foreach ($sequence as $line) {
$this->write($line);
2016-06-23 23:51:08 +02:00
}
}
}