_clone()->toRoot(); $location = $location ? $location // TODO use document.location : $self->document->xhr->getUri(true); // FIXME tmp $self->document->WebBrowserCallback = $callback; if (! $location) throw new Exception('Location needed to activate WebBrowser plugin !'); else { $self->bind('click', array($location, $callback), array('phpQueryPlugin_WebBrowser', 'hadleClick')); $self->bind('submit', array($location, $callback), array('phpQueryPlugin_WebBrowser', 'handleSubmit')); } } public static function browser($self, $callback = null, $location = null) { return $self->WebBrowser($callback, $location); } public static function downloadTo($self, $dir = null, $filename = null) { $url = null; if ($self->is('a[href]')) $url = $self->attr('href'); else if ($self->find('a')->length) $url = $self->find('a')->attr('href'); if ($url) { $url = resolve_url($self->document->location, $url); if (! $dir) $dir = getcwd(); // TODO resolv name from response headers if (! $filename) { $matches = null; preg_match('@/([^/]+)$@', $url, $matches); $filename = $matches[1]; } //print $url; $path = rtrim($dir, '/').'/'.$filename; phpQuery::debug("Requesting download of $url\n"); // TODO use AJAX instead of file_get_contents file_put_contents($path, file_get_contents($url)); } return $self; } /** * Method changing browser location. * Fires callback registered with WebBrowser(), if any. * @param $self * @param $url * @return unknown_type */ public static function location($self, $url = null) { // TODO if ! $url return actual location ??? $xhr = isset($self->document->xhr) ? $self->document->xhr : null; $xhr = phpQuery::ajax(array( 'url' => $url, ), $xhr); $return = false; if ($xhr->getLastResponse()->isSuccessful()) { $return = phpQueryPlugin_WebBrowser::browserReceive($xhr); if (isset($self->document->WebBrowserCallback)) phpQuery::callbackRun( $self->document->WebBrowserCallback, array($return) ); } return $return; } } class phpQueryPlugin_WebBrowser { /** * * @param $url * @param $callback * @param $param1 * @param $param2 * @param $param3 * @return Zend_Http_Client */ public static function browserGet($url, $callback, $param1 = null, $param2 = null, $param3 = null) { phpQuery::debug("[WebBrowser] GET: $url"); self::authorizeHost($url); $xhr = phpQuery::ajax(array( 'type' => 'GET', 'url' => $url, 'dataType' => 'html', )); $paramStructure = null; if (func_num_args() > 2) { $paramStructure = func_get_args(); $paramStructure = array_slice($paramStructure, 2); } if ($xhr->getLastResponse()->isSuccessful()) { phpQuery::callbackRun($callback, array(self::browserReceive($xhr)->WebBrowser()), $paramStructure ); // phpQuery::callbackRun($callback, array( // self::browserReceive($xhr)//->WebBrowser($callback) // )); return $xhr; } else { throw new Exception("[WebBrowser] GET request failed; url: $url"); return false; } } /** * * @param $url * @param $data * @param $callback * @param $param1 * @param $param2 * @param $param3 * @return Zend_Http_Client */ public static function browserPost($url, $data, $callback, $param1 = null, $param2 = null, $param3 = null) { self::authorizeHost($url); $xhr = phpQuery::ajax(array( 'type' => 'POST', 'url' => $url, 'dataType' => 'html', 'data' => $data, )); $paramStructure = null; if (func_num_args() > 3) { $paramStructure = func_get_args(); $paramStructure = array_slice($paramStructure, 3); } if ($xhr->getLastResponse()->isSuccessful()) { phpQuery::callbackRun($callback, array(self::browserReceive($xhr)->WebBrowser()), $paramStructure ); // phpQuery::callbackRun($callback, array( // self::browserReceive($xhr)//->WebBrowser($callback) // )); return $xhr; } else return false; } /** * * @param $ajaxSettings * @param $callback * @param $param1 * @param $param2 * @param $param3 * @return Zend_Http_Client */ public static function browser($ajaxSettings, $callback, $param1 = null, $param2 = null, $param3 = null) { self::authorizeHost($ajaxSettings['url']); $xhr = phpQuery::ajax( self::ajaxSettingsPrepare($ajaxSettings) ); $paramStructure = null; if (func_num_args() > 2) { $paramStructure = func_get_args(); $paramStructure = array_slice($paramStructure, 2); } if ($xhr->getLastResponse()->isSuccessful()) { phpQuery::callbackRun($callback, array(self::browserReceive($xhr)->WebBrowser()), $paramStructure ); // phpQuery::callbackRun($callback, array( // self::browserReceive($xhr)//->WebBrowser($callback) // )); return $xhr; } else return false; } protected static function authorizeHost($url) { $host = parse_url($url, PHP_URL_HOST); if ($host) phpQuery::ajaxAllowHost($host); } protected static function ajaxSettingsPrepare($settings) { unset($settings['success']); unset($settings['error']); return $settings; } /** * @param Zend_Http_Client $xhr */ public static function browserReceive($xhr) { phpQuery::debug("[WebBrowser] Received from ".$xhr->getUri(true)); // TODO handle meta redirects $body = $xhr->getLastResponse()->getBody(); // XXX error ??? if (strpos($body, '') !== false) { $body = '' .str_replace('', '', $body) .''; } $pq = phpQuery::newDocument($body); $pq->document->xhr = $xhr; $pq->document->location = $xhr->getUri(true); $refresh = $pq->find('meta[http-equiv=refresh]') ->add('meta[http-equiv=Refresh]'); if ($refresh->size()) { // print htmlspecialchars(var_export($xhr->getCookieJar()->getAllCookies(), true)); // print htmlspecialchars(var_export($xhr->getLastResponse()->getHeader('Set-Cookie'), true)); phpQuery::debug("Meta redirect... '{$refresh->attr('content')}'\n"); // there is a refresh, so get the new url $content = $refresh->attr('content'); $urlRefresh = substr($content, strpos($content, '=')+1); $urlRefresh = trim($urlRefresh, '\'"'); // XXX not secure ?! phpQuery::ajaxAllowURL($urlRefresh); // $urlRefresh = urldecode($urlRefresh); // make ajax call, passing last $xhr object to preserve important stuff $xhr = phpQuery::ajax(array( 'type' => 'GET', 'url' => $urlRefresh, 'dataType' => 'html', ), $xhr); if ($xhr->getLastResponse()->isSuccessful()) { // if all is ok, repeat this method... return call_user_func_array( array('phpQueryPlugin_WebBrowser', 'browserReceive'), array($xhr) ); } } else return $pq; } /** * * @param $e * @param $callback * @return unknown_type */ public static function hadleClick($e, $callback = null) { $node = phpQuery::pq($e->target); $type = null; if ($node->is('a[href]')) { // TODO document.location $xhr = isset($node->document->xhr) ? $node->document->xhr : null; $xhr = phpQuery::ajax(array( 'url' => resolve_url($e->data[0], $node->attr('href')), 'referer' => $node->document->location, ), $xhr); if ((! $callback || !($callback instanceof Callback)) && $e->data[1]) $callback = $e->data[1]; if ($xhr->getLastResponse()->isSuccessful() && $callback) phpQuery::callbackRun($callback, array( self::browserReceive($xhr) )); } else if ($node->is(':submit') && $node->parents('form')->size()) $node->parents('form')->trigger('submit', array($e)); } /** * Enter description here... * * @param unknown_type $e * @TODO trigger submit for form after form's submit button has a click event */ public static function handleSubmit($e, $callback = null) { $node = phpQuery::pq($e->target); if (!$node->is('form') || !$node->is('[action]')) return; // TODO document.location $xhr = isset($node->document->xhr) ? $node->document->xhr : null; $submit = pq($e->relatedTarget)->is(':submit') ? $e->relatedTarget // will this work ? // : $node->find(':submit:first')->get(0); : $node->find('*:submit:first')->get(0); $data = array(); foreach($node->serializeArray($submit) as $r) // XXXt.c maybe $node->not(':submit')->add($sumit) would be better ? // foreach($node->serializeArray($submit) as $r) $data[ $r['name'] ] = $r['value']; $options = array( 'type' => $node->attr('method') ? $node->attr('method') : 'GET', 'url' => resolve_url($e->data[0], $node->attr('action')), 'data' => $data, 'referer' => $node->document->location, // 'success' => $e->data[1], ); if ($node->attr('enctype')) $options['contentType'] = $node->attr('enctype'); $xhr = phpQuery::ajax($options, $xhr); if ((! $callback || !($callback instanceof Callback)) && $e->data[1]) $callback = $e->data[1]; if ($xhr->getLastResponse()->isSuccessful() && $callback) phpQuery::callbackRun($callback, array( self::browserReceive($xhr) )); } } /** * * @param unknown_type $parsed * @return unknown * @link http://www.php.net/manual/en/function.parse-url.php * @author stevenlewis at hotmail dot com */ function glue_url($parsed) { if (! is_array($parsed)) return false; $uri = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '':'//'): ''; $uri .= isset($parsed['user']) ? $parsed['user'].($parsed['pass']? ':'.$parsed['pass']:'').'@':''; $uri .= isset($parsed['host']) ? $parsed['host'] : ''; $uri .= isset($parsed['port']) ? ':'.$parsed['port'] : ''; if(isset($parsed['path'])) { $uri .= (substr($parsed['path'],0,1) == '/')?$parsed['path']:'/'.$parsed['path']; } $uri .= isset($parsed['query']) ? '?'.$parsed['query'] : ''; $uri .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : ''; return $uri; } /** * Enter description here... * * @param unknown_type $base * @param unknown_type $url * @return unknown * @author adrian-php at sixfingeredman dot net */ function resolve_url($base, $url) { if (!strlen($base)) return $url; // Step 2 if (!strlen($url)) return $base; // Step 3 if (preg_match('!^[a-z]+:!i', $url)) return $url; $base = parse_url($base); if ($url{0} == "#") { // Step 2 (fragment) $base['fragment'] = substr($url, 1); return unparse_url($base); } unset($base['fragment']); unset($base['query']); if (substr($url, 0, 2) == "//") { // Step 4 return unparse_url(array( 'scheme'=>$base['scheme'], 'path'=>substr($url,2), )); } else if ($url{0} == "/") { // Step 5 $base['path'] = $url; } else { // Step 6 $path = explode('/', $base['path']); $url_path = explode('/', $url); // Step 6a: drop file from base array_pop($path); // Step 6b, 6c, 6e: append url while removing "." and ".." from // the directory portion $end = array_pop($url_path); foreach ($url_path as $segment) { if ($segment == '.') { // skip } else if ($segment == '..' && $path && $path[sizeof($path)-1] != '..') { array_pop($path); } else { $path[] = $segment; } } // Step 6d, 6f: remove "." and ".." from file portion if ($end == '.') { $path[] = ''; } else if ($end == '..' && $path && $path[sizeof($path)-1] != '..') { $path[sizeof($path)-1] = ''; } else { $path[] = $end; } // Step 6h $base['path'] = join('/', $path); } // Step 7 return glue_url($base); }