<?php
header('Content-Type: text/plain'); class HasFriends
{
protected $__friends = array('HasFriends');
public function __get($key)
{
$res=NULL;
$frame=0;
while($frame < count($trace) && $trace[$frame]['class']==__CLASS__) $frame++; if(isset($trace[$frame]['class']) && in_array($trace[$frame]['class'], $this->__friends
)) { //return $this->$key;
$rc=new ReflectionClass($this);
$prop=$rc->getProperty($key);
$prop->setAccessible(true);
$res=$prop->getValue($this);
return $res;
}
// normal __get() code here
throw new Exception
('Cannot access private property ' . get_class($this) . '::$' . $key . "\r\n", E_USER_ERROR); }
public function __set($key, $value)
{
$res=NULL;
$frame=0;
while($frame < count($trace) && $trace[$frame]['class']==__CLASS__) $frame++; if(isset($trace[$frame]['class']) && in_array($trace[$frame]['class'], $this->__friends
)) { //return $this->$key = $value;
$rc=new ReflectionClass($this);
$prop=$rc->getProperty($key);
$prop->setAccessible(true);
$res=$prop->setValue($this, $value);
return $res;
}
// normal __set() code here
throw new Exception
('Cannot access private property ' . get_class($this) . '::$' . $key . "\r\n", E_USER_ERROR); }
public function __call($name, $arguments)
{
$res=NULL;
$frame=0;
while($frame < count($trace) && $trace[$frame]['class']==__CLASS__) $frame++; if(isset($trace[$frame]['class']) && in_array($trace[$frame]['class'], $this->__friends
)) { //return call_user_func_array(array($this, $name), $this->arguments);
$rc=new ReflectionClass($this);
$meth=$rc->getMethod($name);
$meth->setAccessible(true);
$res=$meth->invokeArgs($this, $arguments);
return $res;
}
// normal __call() code here
throw new Exception
('Cannot call private method ' . get_class($this) . '::' . $name . '()' . "\r\n", E_USER_ERROR); }
public static function __callStatic($name, $arguments)
{
$frame=0;
while($frame < count($trace) && $trace[$frame]['class']==__CLASS__) $frame++; if(isset($trace[$frame]['class']) && in_array($trace[$frame]['class'], $this->__friends
)) { //return call_user_func_array(array(get_class($this), $name), $this->arguments);
$meth=$rc->getMethod($name);
$meth->setAccessible(true);
$res=$meth->invokeArgs(NULL, $arguments);
return $res;
}
// normal __callStatic() code here
throw new Exception
('Cannot call static private method ' . get_class($this) . '::' . $name . '()' . "\r\n", E_USER_ERROR); }
};
class A extends HasFriends
{
public $a = 1;
protected $b = 2;
private $c = 3;
protected $__friends = array('B'); private function d() { return 4; }
};
class B
{
public $d = 4;
protected $e = 5;
private $f = 6;
public $a = NULL;
public function getC()
{
return $this->a->c;
}
public function g() { return $this->a->d(); }
};
$a = new A();
$b = new B();
$b->a = &$a;
echo 'var_dump($a)='."\r\n";
echo 'var_dump($b)='."\r\n";
try
{
echo 'Trying to access A::c'."\r\n";
}
catch(Exception $e)
{
echo $e->getMessage();
}
try
{
echo 'Trying to access B::a::c'."\r\n";
}
catch(Exception $e)
{
echo $e->getMessage();
}
echo 'Accessing B::getC(), which returns B::a::c'."\r\n";
try
{
echo 'Trying to access A::d()'."\r\n";
}
catch(Exception $e)
{
echo $e->getMessage();
}
echo 'Accessing B::g(), which returns B::a::d()'."\r\n";
PD9waHAKaGVhZGVyKCdDb250ZW50LVR5cGU6IHRleHQvcGxhaW4nKTsKY2xhc3MgSGFzRnJpZW5kcwp7Cglwcm90ZWN0ZWQgJF9fZnJpZW5kcyA9IGFycmF5KCdIYXNGcmllbmRzJyk7CgoJcHVibGljIGZ1bmN0aW9uIF9fZ2V0KCRrZXkpCgl7CgkJJHJlcz1OVUxMOwoJCSR0cmFjZSA9IGRlYnVnX2JhY2t0cmFjZSgpOwoJCSRmcmFtZT0wOwoJCXdoaWxlKCRmcmFtZSA8IGNvdW50KCR0cmFjZSkgJiYgJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ109PV9fQ0xBU1NfXykgJGZyYW1lKys7CgkJaWYoaXNzZXQoJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ10pICYmIGluX2FycmF5KCR0cmFjZVskZnJhbWVdWydjbGFzcyddLCAkdGhpcy0+X19mcmllbmRzKSkgewoJCQkvL3JldHVybiAkdGhpcy0+JGtleTsKCQkJJHJjPW5ldyBSZWZsZWN0aW9uQ2xhc3MoJHRoaXMpOwoJCQkkcHJvcD0kcmMtPmdldFByb3BlcnR5KCRrZXkpOwoJCQkkcHJvcC0+c2V0QWNjZXNzaWJsZSh0cnVlKTsKCQkJJHJlcz0kcHJvcC0+Z2V0VmFsdWUoJHRoaXMpOwoJCQlyZXR1cm4gJHJlczsKCQl9CgkJCgkJLy8gbm9ybWFsIF9fZ2V0KCkgY29kZSBoZXJlCgkJdGhyb3cgbmV3IEV4Y2VwdGlvbignQ2Fubm90IGFjY2VzcyBwcml2YXRlIHByb3BlcnR5ICcgLiBnZXRfY2xhc3MoJHRoaXMpIC4gJzo6JCcgLiAka2V5IC4gIlxyXG4iLCBFX1VTRVJfRVJST1IpOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBfX3NldCgka2V5LCAkdmFsdWUpCgl7CgkJJHJlcz1OVUxMOwoJCSR0cmFjZSA9IGRlYnVnX2JhY2t0cmFjZSgpOwoJCSRmcmFtZT0wOwoJCXdoaWxlKCRmcmFtZSA8IGNvdW50KCR0cmFjZSkgJiYgJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ109PV9fQ0xBU1NfXykgJGZyYW1lKys7CgkJaWYoaXNzZXQoJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ10pICYmIGluX2FycmF5KCR0cmFjZVskZnJhbWVdWydjbGFzcyddLCAkdGhpcy0+X19mcmllbmRzKSkgewoJCQkvL3JldHVybiAkdGhpcy0+JGtleSA9ICR2YWx1ZTsKCQkJJHJjPW5ldyBSZWZsZWN0aW9uQ2xhc3MoJHRoaXMpOwoJCQkkcHJvcD0kcmMtPmdldFByb3BlcnR5KCRrZXkpOwoJCQkkcHJvcC0+c2V0QWNjZXNzaWJsZSh0cnVlKTsKCQkJJHJlcz0kcHJvcC0+c2V0VmFsdWUoJHRoaXMsICR2YWx1ZSk7CgkJCXJldHVybiAkcmVzOwoJCX0KCQkKCQkvLyBub3JtYWwgX19zZXQoKSBjb2RlIGhlcmUKCQl0aHJvdyBuZXcgRXhjZXB0aW9uKCdDYW5ub3QgYWNjZXNzIHByaXZhdGUgcHJvcGVydHkgJyAuIGdldF9jbGFzcygkdGhpcykgLiAnOjokJyAuICRrZXkgLiAiXHJcbiIsIEVfVVNFUl9FUlJPUik7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBfX2NhbGwoJG5hbWUsICRhcmd1bWVudHMpCgl7CgkJJHJlcz1OVUxMOwoJCSR0cmFjZSA9IGRlYnVnX2JhY2t0cmFjZSgpOwoJCSRmcmFtZT0wOwoJCXdoaWxlKCRmcmFtZSA8IGNvdW50KCR0cmFjZSkgJiYgJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ109PV9fQ0xBU1NfXykgJGZyYW1lKys7CgkJaWYoaXNzZXQoJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ10pICYmIGluX2FycmF5KCR0cmFjZVskZnJhbWVdWydjbGFzcyddLCAkdGhpcy0+X19mcmllbmRzKSkgewoJCQkvL3JldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgkdGhpcywgJG5hbWUpLCAkdGhpcy0+YXJndW1lbnRzKTsKCQkJJHJjPW5ldyBSZWZsZWN0aW9uQ2xhc3MoJHRoaXMpOwoJCQkkbWV0aD0kcmMtPmdldE1ldGhvZCgkbmFtZSk7CgkJCSRtZXRoLT5zZXRBY2Nlc3NpYmxlKHRydWUpOwoJCQkkcmVzPSRtZXRoLT5pbnZva2VBcmdzKCR0aGlzLCAkYXJndW1lbnRzKTsKCQkJcmV0dXJuICRyZXM7CgkJfQoJCS8vIG5vcm1hbCBfX2NhbGwoKSBjb2RlIGhlcmUKCQl0aHJvdyBuZXcgRXhjZXB0aW9uKCdDYW5ub3QgY2FsbCBwcml2YXRlIG1ldGhvZCAnIC4gZ2V0X2NsYXNzKCR0aGlzKSAuICc6OicgLiAkbmFtZSAuICcoKScgLiAiXHJcbiIsIEVfVVNFUl9FUlJPUik7Cgl9CgkKCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gX19jYWxsU3RhdGljKCRuYW1lLCAkYXJndW1lbnRzKQoJewoJCSR0cmFjZSA9IGRlYnVnX2JhY2t0cmFjZSgpOwoJCSRmcmFtZT0wOwoJCXdoaWxlKCRmcmFtZSA8IGNvdW50KCR0cmFjZSkgJiYgJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ109PV9fQ0xBU1NfXykgJGZyYW1lKys7CgkJaWYoaXNzZXQoJHRyYWNlWyRmcmFtZV1bJ2NsYXNzJ10pICYmIGluX2FycmF5KCR0cmFjZVskZnJhbWVdWydjbGFzcyddLCAkdGhpcy0+X19mcmllbmRzKSkgewoJCQkvL3JldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheShnZXRfY2xhc3MoJHRoaXMpLCAkbmFtZSksICR0aGlzLT5hcmd1bWVudHMpOwoJCQkkcmM9bmV3IFJlZmxlY3Rpb25DbGFzcyhnZXRfY2xhc3MoJHRoaXMpKTsKCQkJJG1ldGg9JHJjLT5nZXRNZXRob2QoJG5hbWUpOwoJCQkkbWV0aC0+c2V0QWNjZXNzaWJsZSh0cnVlKTsKCQkJJHJlcz0kbWV0aC0+aW52b2tlQXJncyhOVUxMLCAkYXJndW1lbnRzKTsKCQkJcmV0dXJuICRyZXM7CgkJfQoJCS8vIG5vcm1hbCBfX2NhbGxTdGF0aWMoKSBjb2RlIGhlcmUKCQl0aHJvdyBuZXcgRXhjZXB0aW9uKCdDYW5ub3QgY2FsbCBzdGF0aWMgcHJpdmF0ZSBtZXRob2QgJyAuIGdldF9jbGFzcygkdGhpcykgLiAnOjonIC4gJG5hbWUgLiAnKCknIC4gIlxyXG4iLCBFX1VTRVJfRVJST1IpOwoJfQp9OwpjbGFzcyBBIGV4dGVuZHMgSGFzRnJpZW5kcwp7CgkKCXB1YmxpYyAkYSA9IDE7Cglwcm90ZWN0ZWQgJGIgPSAyOwoJcHJpdmF0ZSAkYyA9IDM7Cglwcm90ZWN0ZWQgJF9fZnJpZW5kcyA9IGFycmF5KCdCJyk7Cglwcml2YXRlIGZ1bmN0aW9uIGQoKSB7IHJldHVybiA0OyB9Cn07CmNsYXNzIEIKewoJcHVibGljICRkID0gNDsKCXByb3RlY3RlZCAkZSA9IDU7Cglwcml2YXRlICRmID0gNjsKCXB1YmxpYyAkYSA9IE5VTEw7CglwdWJsaWMgZnVuY3Rpb24gZ2V0QygpCgl7CgkJcmV0dXJuICR0aGlzLT5hLT5jOwoJfQoJcHVibGljIGZ1bmN0aW9uIGcoKSB7IHJldHVybiAkdGhpcy0+YS0+ZCgpOyB9Cn07CiRhID0gbmV3IEEoKTsKJGIgPSBuZXcgQigpOwokYi0+YSA9ICYkYTsKZWNobyAndmFyX2R1bXAoJGEpPScuIlxyXG4iOwp2YXJfZHVtcCgkYSk7CmVjaG8gJ3Zhcl9kdW1wKCRiKT0nLiJcclxuIjsKdmFyX2R1bXAoJGIpOwp0cnkKewoJZWNobyAnVHJ5aW5nIHRvIGFjY2VzcyBBOjpjJy4iXHJcbiI7Cgl2YXJfZHVtcCgkYS0+Yyk7Cn0KY2F0Y2goRXhjZXB0aW9uICRlKQp7CgllY2hvICRlLT5nZXRNZXNzYWdlKCk7Cn0KdHJ5CnsKCWVjaG8gJ1RyeWluZyB0byBhY2Nlc3MgQjo6YTo6YycuIlxyXG4iOwoJdmFyX2R1bXAoJGItPmEtPmMpOwp9CmNhdGNoKEV4Y2VwdGlvbiAkZSkKewoJZWNobyAkZS0+Z2V0TWVzc2FnZSgpOwp9CmVjaG8gJ0FjY2Vzc2luZyBCOjpnZXRDKCksIHdoaWNoIHJldHVybnMgQjo6YTo6YycuIlxyXG4iOwp2YXJfZHVtcCgkYi0+Z2V0QygpKTsKdHJ5CnsKCWVjaG8gJ1RyeWluZyB0byBhY2Nlc3MgQTo6ZCgpJy4iXHJcbiI7Cgl2YXJfZHVtcCgkYS0+ZCgpKTsKfQpjYXRjaChFeGNlcHRpb24gJGUpCnsKCWVjaG8gJGUtPmdldE1lc3NhZ2UoKTsKfQplY2hvICdBY2Nlc3NpbmcgQjo6ZygpLCB3aGljaCByZXR1cm5zIEI6OmE6OmQoKScuIlxyXG4iOwp2YXJfZHVtcCgkYi0+ZygpKTsK