예제 #1
0
 static function php($string, $urlInterpolation = false)
 {
     $string = (string) $string;
     false !== strpos($string, '&') && ($string = str_replace(array('&#039;', '&quot;', '&gt;', '&lt;', '&amp;'), array("'", '"', '>', '<', '&'), $string));
     $urlInterpolation && false !== strpos($string, '{') && ($string = str_replace(array('{/}', '{~}'), array(Patchwork::__HOST__(), Patchwork::__BASE__()), $string));
     return $string;
 }
 function __construct($url)
 {
     $url = (string) $url;
     $url = '' === $url ? '' : (preg_match("'^([^:/]+:/|\\.+)?/'", $url) ? $url : p::__BASE__() . ('index' === $url ? '' : $url));
     if ('.' === substr($url, 0, 1)) {
         user_error('Current redirection behaviour with relative URLs may change in a future version of Patchwork. As long as this notice appears, using relative URLs is strongly discouraged.');
     }
     $this->url = $url;
 }
예제 #3
0
 static function php($text, $url = '', $attributes = '')
 {
     $url = (string) $url;
     $a = strpos($url, '#');
     if (false !== $a) {
         $hash = substr($url, $a);
         $url = substr($url, 0, $a);
     } else {
         $hash = '';
     }
     return $url == htmlspecialchars(substr(Patchwork::__HOST__() . substr($_SERVER['REQUEST_URI'], 1), strlen(Patchwork::__BASE__()))) ? '<b class="linkloop">' . $text . '</b>' : '<a href="' . Patchwork::base($url, true) . $hash . '" ' . $attributes . '>' . $text . '</a>';
 }
예제 #4
0
 protected function doSchedule($time)
 {
     $db = $this->getPdoConnection();
     if ($time < $_SERVER['REQUEST_TIME'] - 366 * 86400) {
         $time += $_SERVER['REQUEST_TIME'];
     }
     $data = array('task' => $this, 'cookie' => &$_COOKIE, 'session' => class_exists('SESSION', false) ? s::getAll() : array());
     $sql = "INSERT INTO queue (base, data, run_time)\n                VALUES (?,?,?)";
     $db->prepare($sql)->execute(array(p::__BASE__(), serialize($data), $time));
     $id = $db->lastInsertId();
     $this->registerQueue();
     return $id;
 }
예제 #5
0
 function redirect($javascript)
 {
     p::disable();
     $url = $this->url;
     $url = '' === $url ? '' : (preg_match("'^([^:/]+:/|\\.+)?/'", $url) ? $url : p::__BASE__() . ('index' === $url ? '' : $url));
     if ($javascript) {
         $url = 'location.replace(' . ('' !== $url ? "'" . addslashes($url) . "'" : 'location') . ')';
         header('Content-Length: ' . strlen($url));
         echo $url;
     } else {
         header('HTTP/1.1 302 Found');
         header('Location: ' . ('' !== $url ? $url : $_SERVER['REQUEST_URI']));
     }
 }
 static function resolve($agent)
 {
     static $cache = array();
     if (isset($cache[$agent])) {
         return $cache[$agent];
     } else {
         $cache[$agent] =& $trace;
     }
     $args = array();
     $BASE = p::__BASE__();
     $agent = rawurlencode($agent);
     $agent = str_replace(array('%21', '%7E', '%2A', '%28', '%29', '%2C', '%2F', '%3A', '%40', '%24', '%3B'), array('!', '~', '*', '(', ')', ',', '/', ':', '@', '$', ';'), $agent);
     $agent = p::base($agent, true);
     $agent = preg_replace("'^.*?://[^/]*'", '', $agent);
     $h = patchwork_http_socket($_SERVER['SERVER_ADDR'], $_SERVER['SERVER_PORT'], isset($_SERVER['HTTPS']));
     $keys = p::$lang;
     $keys = "GET {$agent}?p:=k:{$keys} HTTP/1.0\r\n";
     $keys .= "Host: {$_SERVER['HTTP_HOST']}\r\n";
     $keys .= "Connection: close\r\n\r\n";
     fwrite($h, $keys);
     $keys = array();
     while (false !== ($a = fgets($h))) {
         $keys[] = $a;
     }
     fclose($h);
     $h = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
     $h = "/w\\.k\\((-?[0-9]+),({$h}),({$h}),({$h}),\\[((?:{$h}(?:,{$h})*)?)\\]\\)/su";
     if (!preg_match($h, implode('', $keys), $keys)) {
         user_error('Error while getting meta info data for ' . htmlspecialchars($agent));
         p::disable(true);
     }
     $appId = (int) $keys[1];
     $base = stripcslashes(substr($keys[2], 1, -1));
     $agent = stripcslashes(substr($keys[3], 1, -1));
     $a = stripcslashes(substr($keys[4], 1, -1));
     $keys = eval('return array(' . $keys[5] . ');');
     if ('' !== $a) {
         $args['__0__'] = $a;
         $i = 0;
         foreach (explode('/', $a) as $a) {
             $args['__' . ++$i . '__'] = $a;
         }
     }
     if ($base === $BASE) {
         $appId = $base = false;
     } else {
         p::watch('foreignTrace');
     }
     return $trace = array($appId, $base, $agent, $keys, $args);
 }
예제 #7
0
 protected function pushMail($mailer, &$headers, &$options)
 {
     if (isset($options['testMode'])) {
         $this->testMode = $options['testMode'];
     } else {
         if ($this->testMode) {
             $options['testMode'] = 1;
         }
     }
     $sent = -(int) (bool) (!empty($options['testMode']));
     $archive = (int) (!(empty($options['archive']) && empty($options['testMode'])));
     $time = isset($options['time']) ? $options['time'] : 0;
     if ($time < $_SERVER['REQUEST_TIME'] - 366 * 86400) {
         $time += $_SERVER['REQUEST_TIME'];
     }
     if (!empty($options['attachments']) && is_array($options['attachments'])) {
         $tmpToken = false;
         foreach ($options['attachments'] as &$file) {
             if (is_uploaded_file($file) || PATCHWORK_ZCACHE === substr($file, 0, strlen(PATCHWORK_ZCACHE))) {
                 $tmpToken || ($tmpToken = p::strongId(8));
                 $base = PATCHWORK_ZCACHE . p::strongId(8) . '~' . $tmpToken;
                 copy($file, $base);
                 $file = $base;
             }
         }
         unset($file, $options['attachments.tmpToken']);
         $tmpToken && ($options['attachments.tmpToken'] = $tmpToken);
     }
     $data = array('mailer' => $mailer, 'headers' => &$headers, 'options' => &$options, 'cookie' => &$_COOKIE, 'session' => class_exists('SESSION', false) ? s::getAll() : array());
     $db = $this->getPdoConnection();
     $sql = "INSERT INTO queue (base, data, send_time, archive, sent_time)\n                VALUES (?,?,?,?,?)";
     $db->prepare($sql)->execute(array(p::__BASE__(), serialize($data), $time, $archive, $sent));
     $sql = $db->lastInsertId();
     $this->registerQueue();
     return $sql;
 }
예제 #8
0
 function compose($o)
 {
     $o->DATA = '/*<script>/**/q="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $this->getJs($this->data)) . '"//</script>' . '<script src="' . Patchwork::__BASE__() . 'js/QJsrsHandler"></script>';
     return $o;
 }
예제 #9
0
    protected static function sendDebugInfo()
    {
        ob_start(function_exists('ob_gzhandler') ? 'ob_gzhandler' : null, 1 << 14);
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: max-age=0,private,must-revalidate');
        set_time_limit(0);
        ignore_user_abort(true);
        ?>
<!doctype html>
<html>
<head>
    <title>Debug Window</title>
    <link type="text/css" rel="stylesheet" href="<?php 
        echo p::__BASE__() . 'css/patchwork-console.css?' . $GLOBALS['patchwork_appId'];
        ?>
">
</head>
<body>
<script src="<?php 
        echo p::__BASE__() . 'js/patchwork-console.js?' . $GLOBALS['patchwork_appId'];
        ?>
"></script>
<div id="events" style="display:none">
<?php 
        $handlers = array();
        for (;;) {
            foreach (scandir(PATCHWORK_ZCACHE) as $log) {
                if ('.log' === substr($log = PATCHWORK_ZCACHE . $log, -4)) {
                    if (rename($log, $log .= '~')) {
                        ($h = fopen($log, 'rb')) ? $handlers[$log] = $h : unlink($log);
                    }
                }
            }
            $count = 0;
            foreach ($handlers as $log => $h) {
                if (false === ($next_line = fgets($h))) {
                    ++$count;
                } else {
                    while (false !== ($line = $next_line)) {
                        $next_line = fgets($h);
                        self::parseLine($line, $next_line);
                        for (;;) {
                            if (false !== ($line = reset(self::$buffer))) {
                                echo implode('', $line);
                                if ($line && false === end($line)) {
                                    unset(self::$buffer[key(self::$buffer)]);
                                    ob_flush();
                                    flush();
                                    if (connection_aborted()) {
                                        break 4;
                                    } else {
                                        continue;
                                    }
                                } else {
                                    self::$buffer[key(self::$buffer)] = array();
                                }
                            }
                            break;
                        }
                    }
                }
            }
            if ($count === count($handlers)) {
                break;
            }
            usleep(150000);
        }
        foreach ($handlers as $log => $h) {
            fclose($h) + unlink($log);
        }
        ?>
</div>
<script>
scrollTo(0,0);
var i, b = window.parent && parent.E && parent.E.buffer;
for (i in b) patchworkConsole.log("client-dump", b[i]);
parent.E.buffer = [];
</script>
<?php 
    }
예제 #10
0
 static function render($agent, $liveAgent)
 {
     $config_maxage = $CONFIG['maxage'];
     // Get the calling URI
     if (isset($_COOKIE['R$'])) {
         p::$uri = $_COOKIE['R$'];
         setcookie('R$', '', 1, '/');
         // Check the Referer header
         // T$ starts with 2 when the Referer's confidence is unknown
         //                1 when it is trusted
         if (isset($_SERVER['HTTP_REFERER']) && $_COOKIE['R$'] === $_SERVER['HTTP_REFERER']) {
             if (class_exists('SESSION', false)) {
                 $_COOKIE['T$'] = '1';
                 s::regenerateId();
             } else {
                 self::$antiCsrfToken[0] = '1';
                 setcookie('T$', self::$antiCsrfToken, 0, $CONFIG['session.cookie_path'], $CONFIG['session.cookie_domain']);
             }
         }
     } else {
         p::$uri = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : p::$base;
     }
     if ($liveAgent) {
         // The output is both html and js, but iframe transport layer needs html
         p::$binaryMode = true;
         header('Content-Type: text/html');
         echo '/*<script>/**/q="';
     } else {
         echo 'w(';
     }
     p::openMeta($agent);
     try {
         if (isset($_GET['T$']) && !p::$antiCsrfMatch) {
             throw new e\PrivateResource();
         }
         $a = new $agent($_GET);
         $group = p::closeGroupStage();
         if ($is_cacheable = 'POST' !== $_SERVER['REQUEST_METHOD'] && !in_array('private', $group)) {
             $cagent = p::agentCache($agent, $a->get, 'js.ser', $group);
             $dagent = p::getContextualCachePath('jsdata.' . $agent, 'js.ser', $cagent);
             if ($liveAgent) {
                 if (file_exists($dagent)) {
                     if (filemtime($dagent) > $_SERVER['REQUEST_TIME']) {
                         $data = unserialize(file_get_contents($dagent));
                         p::setMaxage($data['maxage']);
                         p::setExpires($data['expires']);
                         p::writeWatchTable($data['watch']);
                         array_map('header', $data['headers']);
                         p::closeMeta();
                         echo str_replace(array('\\', '"', '</'), array('\\\\', '\\"', '<\\/'), $data['rawdata']), '"//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>';
                         return;
                     } else {
                         @(unlink($cagent) + unlink($dagent));
                     }
                 }
             } else {
                 if (file_exists($cagent)) {
                     if (filemtime($cagent) > $_SERVER['REQUEST_TIME']) {
                         $data = unserialize(file_get_contents($cagent));
                         p::setMaxage($data['maxage']);
                         p::setExpires($data['expires']);
                         p::writeWatchTable($data['watch']);
                         array_map('header', $data['headers']);
                         p::closeMeta();
                         echo $data['rawdata'];
                         return;
                     } else {
                         @(unlink($cagent) + unlink($dagent));
                     }
                 }
             }
         }
         ob_start();
         ++p::$ob_level;
         try {
             $data = (object) $a->compose((object) array());
             if (!p::$is_enabled) {
                 p::closeMeta();
                 return;
             }
             $template = $a->getTemplate();
             echo '{';
             $comma = '';
             foreach ($data as $key => $value) {
                 $key = jsquote($key);
                 is_string($key) || ($key = "'" . $key . "'");
                 echo $comma, $key, ':';
                 if ($value instanceof \loop) {
                     self::writeAgent($value);
                 } else {
                     echo jsquote($value);
                 }
                 $comma = ',';
             }
             echo '}';
         } catch (e\PrivateResource $data) {
             ob_end_clean();
             --p::$ob_level;
             p::closeMeta();
             throw $data;
         }
         $data = ob_get_clean();
         --p::$ob_level;
         $a->metaCompose();
         list($maxage, $group, $expires, $watch, $headers) = p::closeMeta();
     } catch (e\PrivateResource $data) {
         if ($liveAgent) {
             echo 'false";(window.E||alert)("You must provide an auth token to get this liveAgent:\\n"+', jsquote($_SERVER['REQUEST_URI']), ')';
             echo '//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>';
         } else {
             if ($data->getMessage()) {
                 echo 'w.r(0,' . (int) (!DEBUG) . '));';
             } else {
                 echo ');window.E&&E("You must provide an auth token to get this agent:\\n"+', jsquote($_SERVER['REQUEST_URI']), ')';
             }
         }
         exit;
     }
     if ($liveAgent) {
         echo str_replace(array('\\', '"', '</'), array('\\\\', '\\"', '<\\/'), $data), '"//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>';
     } else {
         echo $data;
     }
     if ('ontouch' === $expires && !($watch || $config_maxage == $maxage)) {
         $expires = 'auto';
     }
     $expires = 'auto' === $expires && ($watch || $config_maxage == $maxage) ? 'ontouch' : 'onmaxage';
     $is_cacheable = $is_cacheable && !in_array('private', $group) && ($maxage || 'ontouch' === $expires);
     if (!$liveAgent || $is_cacheable) {
         if ($is_cacheable) {
             ob_start();
         }
         if ($config_maxage == $maxage && Superloader::$turbo) {
             $ctemplate = p::getContextualCachePath("templates/{$template}", 'txt');
             $readHandle = true;
             if ($h = p::fopenX($ctemplate, $readHandle)) {
                 p::openMeta('agent__template/' . $template, false);
                 $template = new \ptlCompiler_js($template);
                 echo $template = ',' . $template->compile() . ')';
                 fwrite($h, $template);
                 flock($h, LOCK_UN);
                 fclose($h);
                 list(, , , $template) = p::closeMeta();
                 p::writeWatchTable($template, $ctemplate);
             } else {
                 fpassthru($readHandle);
                 flock($readHandle, LOCK_UN);
                 fclose($readHandle);
             }
             $watch[] = 'public/templates/js';
         } else {
             echo ',[1,', jsquote($template), ',0,0,0])';
         }
         if ($is_cacheable) {
             $ob = true;
             $template = array('maxage' => $maxage, 'expires' => $expires, 'watch' => $watch, 'headers' => $headers, 'rawdata' => $data);
             $expires = 'ontouch' === $expires ? $config_maxage : $maxage;
             if ($h = p::fopenX($dagent)) {
                 fwrite($h, serialize($template));
                 flock($h, LOCK_UN);
                 fclose($h);
                 touch($dagent, $_SERVER['REQUEST_TIME'] + $expires);
                 p::writeWatchTable($watch, $dagent);
             }
             if ($h = p::fopenX($cagent)) {
                 $ob = false;
                 $template['rawdata'] .= $liveAgent ? ob_get_clean() : ob_get_flush();
                 fwrite($h, serialize($template));
                 flock($h, LOCK_UN);
                 fclose($h);
                 touch($cagent, $_SERVER['REQUEST_TIME'] + $expires);
                 p::writeWatchTable($watch, $cagent);
             }
             if ($ob) {
                 $liveAgent ? ob_end_clean() : ob_end_flush();
             }
         }
     }
 }
예제 #11
0
    protected static function sendDebugInfo()
    {
        ob_start(function_exists('ob_gzhandler') ? 'ob_gzhandler' : null, 1 << 14);
        header('Content-Type: text/html; charset=utf-8');
        header('Cache-Control: max-age=0,private,must-revalidate');
        set_time_limit(0);
        ignore_user_abort(true);
        ?>
<!doctype html>
<html>
<head>
    <title>Debug Window</title>
    <link rel="stylesheet" href="<?php 
        echo p::__BASE__() . 'css/patchwork-console.css?' . $GLOBALS['patchwork_appId'];
        ?>
">
</head>
<body>
<script src="<?php 
        echo p::__BASE__() . 'js/patchwork-console.js?' . $GLOBALS['patchwork_appId'];
        ?>
"></script>
<div id="events" style="display:none">
<?php 
        for (;;) {
            $continue = false;
            foreach (scandir(PATCHWORK_ZCACHE) as $log) {
                if ('.log' !== substr($log = PATCHWORK_ZCACHE . $log, -4)) {
                    continue;
                }
                /**/
                // On Windows only, rename() fails if the file is opened in an other process.
                /**/
                // We use this behavior to detect this and cancel sending the file.
                /**/
                if ('\\' === DIRECTORY_SEPARATOR) {
                    if (!@rename($log, $log .= '~')) {
                        $continue = true;
                        continue;
                    }
                    /**/
                }
                if (!($h = @fopen($log, 'rb'))) {
                    /**/
                    if ('\\' === DIRECTORY_SEPARATOR) {
                        rename($log, substr($log, 0, -1));
                    }
                    continue;
                }
                /**/
                if ('\\' !== DIRECTORY_SEPARATOR) {
                    usleep(1);
                    // Give priority for locking to the error handler process
                    if (@flock($h, LOCK_EX | LOCK_NB, $j) && !$j) {
                        unlink($log);
                    } else {
                        $continue = true;
                        continue;
                    }
                    /**/
                }
                $it = new p\PHP\JsonDumpIterator($h);
                try {
                    unset($j);
                    foreach ($it as $j) {
                        echo '<script>patchworkConsole.log(', $it->jsonStr($j['type']), ',', $j['json'], ',', $it->jsonStr(substr(md5($log), -10)), ')</script>', "\n";
                        ob_flush();
                        flush();
                        if (connection_aborted()) {
                            $continue = false;
                            break;
                        }
                    }
                } catch (p\PHP\JsonDumpIteratorException $it) {
                }
                flock($h, LOCK_UN);
                fclose($h);
                /**/
                if ('\\' === DIRECTORY_SEPARATOR) {
                    unlink($log);
                }
            }
            if ($continue && isset($j)) {
                usleep(150000);
            } else {
                break;
            }
        }
        ?>
</div>
<script>
scrollTo(0,0);
var i, b = window.parent && parent.E && parent.E.buffer;
for (i in b) patchworkConsole.log("client-dump", b[i]);
parent.E.buffer = [];
</script>
<?php 
    }
예제 #12
0
 protected static function get_html(&$value, &$args)
 {
     $a = array();
     if ($result = self::get_text($value, $a)) {
         $result = self::sanitizeHtml($result);
         $a = strip_tags($result);
         $a = html_entity_decode($a, ENT_COMPAT, 'UTF-8');
         $a = preg_replace('/^[\\s\\pZ]+/u', '', $a);
         if ('' === $a) {
             $result = '';
         } else {
             $result = preg_replace("'[ \t]+\$'m", '', trim($result));
             $result = preg_replace("'\n{3,}'", "\n\n", $result);
             $result = preg_replace("'(?<!>)\n\n'", "<br>\n<br>\n", $result);
             $result = preg_replace("'(?<!>)\n'", "<br>\n", $result);
             $result = str_replace(array('{~}', '{/}', Patchwork::__BASE__(), Patchwork::__HOST__()), array('{&#126;}', '{&#047;}', '{~}', '{/}'), $result);
         }
     }
     return $result;
 }
예제 #13
0
 static function filter($buffer, $mode)
 {
     static $rest = '', $base;
     if (!isset($base)) {
         $base = dirname($_SERVER['PATCHWORK_REQUEST'] . ' ');
         if (1 === strlen($base) && strspn($base, '/\\.')) {
             $base = '';
         }
         $base = p::__BASE__() . $base . '/';
     }
     $buffer = preg_split(self::$filterRx, $rest . $buffer, -1, PREG_SPLIT_DELIM_CAPTURE);
     $len = count($buffer);
     for ($i = 1; $i < $len; $i += 2) {
         $buffer[$i] .= $base;
     }
     if (PHP_OUTPUT_HANDLER_END & $mode) {
         $rest = '';
     } else {
         --$len;
         $rest = substr($buffer[$len], 4096);
         $buffer[$len] = substr($buffer[$len], 0, 4096);
     }
     $buffer = implode('', $buffer);
     return $buffer;
 }
예제 #14
0
 static function loadAgent($agent, $args, $is_exo)
 {
     if (null === $agent) {
         return;
     }
     $a =& $_GET;
     if (false === $args) {
         $reset_get = true;
         $cache = '';
         if ('s' === p::$requestMode) {
             ob_start(array(__CLASS__, 'ob_htmlspecialchars'), 32768);
             ++p::$ob_level;
             self::$get = (object) $a;
         } else {
             $args = array();
             if (is_array($a)) {
                 reset($a);
                 while (list($k, $v) = each($a)) {
                     $args[$k] = is_string($v) ? htmlspecialchars($v) : $v;
                 }
             }
             self::$get = (object) $args;
         }
         self::$get->__DEBUG__ = DEBUG ? DEBUG : 0;
         self::$get->__HOST__ = htmlspecialchars(p::__HOST__());
         $cache .= self::$get->__LANG__ = htmlspecialchars(p::__LANG__());
         $cache .= self::$get->__BASE__ = htmlspecialchars(p::__BASE__());
         self::$get->__AGENT__ = 'agent_index' === $agent ? '' : p\Superloader::class2file(substr($agent, 6)) . '/';
         self::$get->__URI__ = htmlspecialchars(p::$uri);
         self::$get->__REFERER__ = isset($_SERVER['HTTP_REFERER']) ? htmlspecialchars($_SERVER['HTTP_REFERER']) : '';
         self::$get->__LANG_ALT__ = new \loop_altLang();
         self::$args = self::$get;
         if (!isset(self::$masterCache[$cache])) {
             self::$masterCache[$cache] = array();
         }
         self::$cache =& self::$masterCache[$cache];
     } else {
         $reset_get = false;
         $_GET =& $args;
         if ($agent instanceof \loop && $agent->__toString()) {
             $agent->autoResolve = false;
             while ($i = $agent->loop()) {
                 $data = $i;
             }
             if (!(p::$binaryMode || $agent instanceof LoopFreezed)) {
                 foreach ($data as &$v) {
                     is_string($v) && ($v = htmlspecialchars($v));
                 }
             }
             $agent = $data->{'a$'};
             $args = array_merge((array) $data, $args);
         }
         $BASE = p::__BASE__();
         $agent = p::base($agent, true);
         if (0 === strncmp($agent, $BASE, strlen($BASE))) {
             $agent = substr($agent, strlen($BASE));
             if ($is_exo) {
                 user_error("Patchwork Security Restriction Error: an AGENT ({$agent}) is called with EXOAGENT");
                 $_GET =& $a;
                 return;
             }
         } else {
             if ($is_exo) {
                 $k = $CONFIG['i18n.lang_list'][p::__LANG__()];
                 $agent = implode($k, explode('__', $agent, 2)) . '?p:=s';
                 foreach ($args as $k => $v) {
                     $agent .= '&' . urlencode($k) . '=' . urlencode($v);
                 }
                 if (ini_get_bool('allow_url_fopen')) {
                     $agent = file_get_contents($agent);
                 } else {
                     $agent = new \HTTP_Request($agent);
                     $agent->sendRequest();
                     $agent = $agent->getResponseBody();
                 }
                 echo str_replace(array('&gt;', '&lt;', '&quot;', '&#039;', '&amp;'), array('>', '<', '"', "'", '&'), $agent);
             } else {
                 user_error("Patchwork Security Restriction Error: an EXOAGENT ({$agent}) is called with AGENT");
             }
             $_GET =& $a;
             return;
         }
         try {
             $agent = p::resolveAgentClass($agent, $args);
         } catch (e\StaticResource $agent) {
             readfile($agent->getMessage());
             $_GET =& $a;
             return;
         }
         self::$args = (object) $args;
     }
     self::render($agent);
     $_GET =& $a;
     if ($reset_get) {
         self::$get = false;
     }
 }