/**
  * Add the button BackToStream in controls page
  *
  * @param X_Streamer_Engine $engine
  * @param Zend_Controller_Action $controller the controller who handle the request
  * @return array
  */
 public function preGetControlItems(X_Streamer_Engine $engine, Zend_Controller_Action $controller)
 {
     $urlHelper = $controller->getHelper('url');
     $return = new X_Page_ItemList_PItem();
     if ($this->config('show.title', true)) {
         $onAirName = X_Env::_("p_streaminfo_unknown_source");
         if ($engine instanceof X_Streamer_Engine_Vlc) {
             $vlc = $engine->getVlcWrapper();
             $onAirName = $vlc->getCurrentName();
         } else {
             // try to find the name from the location (if any)
             $providerId = $controller->getRequest()->getParam('p', false);
             $location = $controller->getRequest()->getParam('l', false);
             if ($providerId && $location) {
                 $providerObj = X_VlcShares_Plugins::broker()->getPlugins($providerId);
                 $location = X_Env::decode($location);
                 if ($providerObj instanceof X_VlcShares_Plugins_ResolverInterface) {
                     $onAirName = $providerObj->resolveLocation($location);
                 }
             }
         }
         // show the title of the file
         $item = new X_Page_Item_PItem('streaminfo-onair', X_Env::_('p_streaminfo_onair') . ": {$onAirName}");
         $item->setType(X_Page_Item_PItem::TYPE_ELEMENT)->setLink(X_Env::completeUrl($urlHelper->url()));
         $return->append($item);
     }
     if ($engine instanceof X_Streamer_Engine_Vlc) {
         $vlc = $engine->getVlcWrapper();
         if ($this->config('show.time', false)) {
             $currentTime = X_Env::formatTime($vlc->getCurrentTime());
             $totalTime = X_Env::formatTime($vlc->getTotalTime());
             $item = new X_Page_Item_PItem('streaminfo-time', "{$currentTime}/{$totalTime}");
             $item->setType(X_Page_Item_PItem::TYPE_ELEMENT)->setLink(X_Env::completeUrl($urlHelper->url()));
             $return->append($item);
         }
     }
     return $return;
 }
 protected function _convertoToSrt(Zend_Dom_Query $dom)
 {
     $this->getResponse()->setHeader('Content-type', 'application/x-subrip', true);
     //$this->getResponse()->setHeader('Content-type', 'text/plain', true);
     $results = $dom->queryXpath('//text');
     $i = 1;
     $string = '';
     while ($results->valid()) {
         $current = $results->current();
         $from = $current->getAttribute('start');
         $dur = $current->getAttribute('dur');
         $text = $current->nodeValue;
         $end = (double) $from + (double) $dur;
         $from = explode('.', (string) $from);
         $from = X_Env::formatTime($from[0]) . ',' . str_pad(substr($from[1], 0, 3), 3, '0', STR_PAD_RIGHT);
         $end = explode('.', (string) $end);
         $end = X_Env::formatTime($end[0]) . ',' . str_pad(substr($end[1], 0, 3), 3, '0', STR_PAD_RIGHT);
         $text = str_replace(array('"', '&', '''), array("\"", "&", "'"), utf8_decode($text));
         $string .= "{$i}\r\n";
         $string .= "{$from} --> {$end}\r\n";
         $string .= "{$text}\r\n";
         $string .= "\r\n";
         $results->next();
         $i++;
     }
     return $string;
 }
 private function _prepareVideo(X_Page_ItemList_PItem $items, Zend_Gdata_Media_Feed $feed, $locationPrefix)
 {
     foreach ($feed as $yvideo) {
         /* @var $yvideo Zend_Gdata_YouTube_VideoEntry */
         if ($yvideo->getVideoDuration() == 0) {
             continue;
         }
         // no duration = no video
         $item = new X_Page_Item_PItem('youtube-video-' . $yvideo->getVideoId(), $yvideo->getVideoTitle() . ' [' . X_Env::formatTime($yvideo->getVideoDuration()) . ']');
         $thumb = $yvideo->getVideoThumbnails();
         @($thumb = $thumb[0]['url']);
         $item->setDescription($yvideo->getVideoDescription())->setType(X_Page_Item_PItem::TYPE_ELEMENT)->setIcon('/images/youtube/icons/video.png')->setThumbnail($thumb)->setCustom(__CLASS__ . ':location', "{$locationPrefix}/{$yvideo->getVideoId()}")->setLink(array('action' => 'mode', 'l' => X_Env::encode("{$locationPrefix}/{$yvideo->getVideoId()}")), 'default', false)->setGenerator(__CLASS__);
         $items->append($item);
     }
 }
 /**
  * get an array with standard information about the playable
  * @param string $url the hoster page or resource ID
  * @param boolean $isId
  * @return array format:
  * 		array(
  * 			'title' => TITLE
  * 			'description' => DESCRIPTION
  * 			'length' => LENGTH
  * 			...
  * 		)
  */
 function getPlayableInfos($url, $isId = true)
 {
     if (!$isId) {
         $url = $this->getResourceId($url);
     }
     // $url is an id now for sure
     /* @var $youtubeHelper X_VlcShares_Plugins_Helper_Youtube */
     $youtubeHelper = X_VlcShares_Plugins::helpers()->helper('youtube');
     try {
         $videoEntry = $youtubeHelper->getVideo($url);
         $thumb = $videoEntry->getVideoThumbnails();
         $thumb = @$thumb[0]['url'];
         $thumb = str_replace('default', '0', $thumb);
         // use cached values
         $infos = array('title' => $videoEntry->getVideoTitle(), 'description' => $videoEntry->getVideoDescription(), 'length' => X_Env::formatTime($videoEntry->getVideoDuration()), 'thumbnail' => $thumb);
         return $infos;
     } catch (Exception $e) {
         throw new Exception("Invalid video", self::E_ID_INVALID);
     }
 }
 public function gen_afterPageBuild(X_Page_ItemList_PItem $list, Zend_Controller_Action $controller)
 {
     // force Rendering win over everythings
     /*if ( !$this->_forceRendering ) {
     			if ( !((bool) $this->config('forced.enabled', false)) && !$this->helpers()->devices()->isWiimc() ) return;
     		} 
     		*/
     // new renderer interface
     if (!$this->isDefaultRenderer()) {
         return;
     }
     X_Debug::i("Plugin triggered");
     $request = $controller->getRequest();
     $enhanced = $this->helpers()->devices()->isWiimcEnhanced() && $this->config('support.enhanced', true);
     $plx = new X_Plx(X_Env::_('p_wiimcplxrenderer_plxtitle_' . $request->getControllerName() . '_' . $request->getActionName()), X_Env::_('p_wiimcplxrenderer_plxdescription_' . $request->getControllerName() . '_' . $request->getActionName()));
     // wiimc plus custom tags
     if ($enhanced) {
         $plx->setWiimcplus_generator_name('vlc-shares');
         // uses the __call api
         $plx->setWiimcplus_generator_version(X_VlcShares::VERSION_CLEAN);
         // uses the __call api
         if ($request->getControllerName() == 'index' && $request->getActionName() == 'collections') {
             $plx->setWiimcplus_assert_mainmenu('true');
             // uses the __call api
         }
         // show the current time as custom playlist header tag if the page is controls/control or browse/stream
         if ($request->getControllerName() == 'controls' && $request->getActionName() == 'control' || $request->getControllerName() == 'browse' && $request->getActionName() == 'stream') {
             $vlc = X_Vlc::getLastInstance();
             if ($vlc) {
                 // check to be sure that vlc is running right now
                 $currentTime = X_Env::formatTime($vlc->getCurrentTime());
                 $totalTime = X_Env::formatTime($vlc->getTotalTime());
                 $plx->setWiimcplus_current_time("{$currentTime}/{$totalTime}");
                 // uses the __call api
             }
         } elseif ($request->getControllerName() == 'browse' && $request->getActionName() == 'selection') {
             $plx->setWiimcplus_assert_nohistory('true');
             // uses the __call api
         }
     }
     foreach ($list->getItems() as $i => $item) {
         /* @var $item X_Page_Item_PItem */
         $plxItemName = ($item->isHighlight() ? '-) ' : '') . $item->getLabel();
         $plxItemWiimcplusIcon = null;
         switch ($item->getType()) {
             case X_Page_Item_PItem::TYPE_CONTAINER:
                 $plxItemType = X_Plx_Item::TYPE_PLAYLIST;
                 $plxItemWiimcplusIcon = 'folder';
                 break;
             case X_Page_Item_PItem::TYPE_ELEMENT:
                 $plxItemType = X_Plx_Item::TYPE_PLAYLIST;
                 if ($request->getControllerName() == 'browse' && $request->getActionName() == 'share') {
                     $plxItemWiimcplusIcon = 'file';
                 }
                 break;
             case X_Page_Item_PItem::TYPE_REQUEST:
                 $plxItemType = X_Plx_Item::TYPE_SEARCH;
                 break;
             case X_Page_Item_PItem::TYPE_PLAYABLE:
                 $plxItemType = X_Plx_Item::TYPE_VIDEO;
                 break;
             default:
                 $plxItemType = $item->getType();
         }
         /* @var $urlHelper Zend_Controller_Action_Helper_Url */
         $urlHelper = $controller->getHelper('url');
         $plxItemUrl = $item->isUrl() ? $item->getLink() : X_Env::completeUrl($urlHelper->url($item->getLink(), $item->getRoute(), $item->isReset()));
         $plxItem = new X_Plx_Item($plxItemName, $plxItemUrl, $plxItemType);
         if ($item->getThumbnail() != null) {
             if (X_Env::startWith($item->getThumbnail(), 'http') || X_Env::startWith($item->getThumbnail(), 'https')) {
                 $plxItem->setThumb($item->getThumbnail());
             } else {
                 $plxItem->setThumb(X_Env::completeUrl($item->getThumbnail()));
             }
         }
         if ($enhanced) {
             if ($plxItemWiimcplusIcon !== null) {
                 $plxItem->setWiimcplus_icon($plxItemWiimcplusIcon);
             }
             if ($item->getKey() == 'core-separator') {
                 $plxItem->setWiimcplus_assert_separator('true');
             }
             if ($item->getKey() == 'core-directwatch') {
                 $plxItem->setWiimcplus_assert_directwatch('true');
                 if ($item->getCustom('subtitle') != null) {
                     $plxItem->setWiimcplus_subtitle($item->getCustom('subtitle'));
                 }
             }
             if ($item->getKey() == 'core-play') {
                 $plxItem->setWiimcplus_assert_startvlc('true');
             }
         }
         $plx->addItem($plxItem);
     }
     $this->_render($plx, $controller);
 }
 /**
  * get an array with standard information about the playable
  * @param string $url the hoster page or resource ID
  * @param boolean $isId
  * @return array format:
  * 		array(
  * 			'title' => TITLE
  * 			'description' => DESCRIPTION
  * 			'length' => LENGTH
  * 			...
  * 		)
  */
 function getPlayableInfos($url, $isId = true)
 {
     if (!$isId) {
         $url = $this->getResourceId($url);
     }
     // use cached values
     if (array_key_exists($url, $this->info_cache)) {
         return $this->info_cache[$url];
     }
     // use the api
     $http = new Zend_Http_Client("http://www.vimeo.com/moogaloop/load/clip:{$url}/local?param_force_embed=0&param_clip_id={$url}&param_show_portrait=0&param_multimoog=&param_server=vimeo.com&param_show_title=0&param_autoplay=0&param_show_byline=0&param_color=00ADEF&param_fullscreen=1&param_md5=0&param_context_id=&context_id=null", array('headers' => array('User-Agent' => "vlc-shares/" . X_VlcShares::VERSION . " vimeo/" . X_VlcShares_Plugins_Vimeo::VERSION)));
     $datas = $http->request()->getBody();
     $xml = new SimpleXMLElement($datas);
     if (@$xml['error']) {
         throw new Exception("Invalid ID {{$url}}", self::E_ID_INVALID);
     }
     $infos = array('title' => (string) @$xml->video->caption, 'description' => '', 'length' => X_Env::formatTime((string) @$xml->video->duration), 'thumbnail' => (string) @$xml->video->thumbnail, 'request_signature' => (string) @$xml->request_signature, 'request_signature_expires' => (string) @$xml->request_signature_expires);
     // add in cache
     $this->info_cache[$url] = $infos;
     return $infos;
 }
 public function getPositions($location, $sourceFile)
 {
     $positions = array();
     try {
         /* @var $cacheHelper X_VlcShares_Plugins_Helper_Cache */
         $cacheHelper = X_VlcShares_Plugins::helpers('cache');
         $positions = $cacheHelper->retrieveItem("streamseeker::{$location}");
         if ($positions) {
             $positions = @unserialize($positions);
         }
         X_Debug::i("Using positions values stored in cache about {$location}");
         // return stored values
         return $positions;
     } catch (Exception $e) {
         // no cache plugin or no positions cached
         X_Debug::i("No FLV info in cache about {$location}");
     }
     // dump 9kb of the file to analyze it
     $tmpFile = tempnam(sys_get_temp_dir(), 'fia');
     $sampleSize = intval($this->options->get('samplesize', 100)) * 1000;
     X_Debug::i("Downloading {$sampleSize} bytes in {$tmpFile} from {$sourceFile}");
     $src = fopen($sourceFile, 'r');
     $dest = fopen($tmpFile, 'w');
     $copied = stream_copy_to_stream($src, $dest, $sampleSize);
     fclose($src);
     fclose($dest);
     X_Debug::i("{$copied} bytes downloaded");
     try {
         $flvinfo = new X_FLVInfo();
         $fileInfo = $flvinfo->getInfo($tmpFile, true, true);
         if ($fileInfo->signature) {
             $keyframes = @$fileInfo->rawMeta[1]['keyframes'];
             $times = $keyframes->times;
             $filepositions = $keyframes->filepositions;
             $lastAdd = 0;
             //$firstKey = 0;
             $minDelta = intval($this->options->get('mindelta', 5)) * 60;
             // mindelta is in minutes
             // time to parse and filter the response
             // filter using a minDelta function
             foreach ($times as $key => $seconds) {
                 /*
                 					if ( $key == 0 ) {
                 						$firstKey = $filepositions[$key];
                 						continue;
                 					}*/
                 if ($seconds - $lastAdd > $minDelta) {
                     // new step
                     //$positions["{$filepositions[$key]},{$firstKey}"] = X_Env::formatTime(intval($seconds));
                     $positions[$filepositions[$key]] = X_Env::formatTime(intval($seconds));
                     $lastAdd = intval($seconds);
                 }
             }
             X_Debug::i("Valid position found in flv file: " . count($positions));
             // parse done, store
             try {
                 /* @var $cacheHelper X_VlcShares_Plugins_Helper_Cache */
                 $cacheHelper = X_VlcShares_Plugins::helpers('cache');
                 $cacheHelper->storeItem("streamseeker::{$location}", serialize($positions), $this->options->get('cachevalidity', 10));
             } catch (Exception $e) {
                 X_Debug::e("Cache is disabled. This is really bad for streamseeker");
             }
         } else {
             X_Debug::w("Wrong signature. Can't analyze");
         }
     } catch (Exception $e) {
         X_Debug::e("FLVInfo throws an error: {$e->getMessage()}");
     }
     return $positions;
 }
 public function fetch($infoOnly = false)
 {
     if ($this->_location == null) {
         X_Debug::w('Trying to fetch a hulu location without a location');
         throw new Exception('Trying to fetch a hulu location without a location');
     }
     if ($this->_fetched === false) {
         // ported code form http://gitorious.org/get-flash-videos-plugins/gfv-plugins/blobs/raw/release/Hulu.pm
         $http = $this->getHttpClient("http://www.hulu.com/watch/{$this->_location}");
         $response = $http->request();
         $datas = $response->getBody();
         X_Debug::i("Fetching main page for: {{$this->_location}}");
         //echo "<b>REQUESTED PAGE</b><textarea>".htmlentities($datas)."</textarea><br/>";
         $pageUrl = str_replace('.com:80/', '.com/', $http->getUri(true));
         X_Debug::i("Last location is {{$pageUrl}}");
         /*
         $matches = array();
         if ( !preg_match('/content_id\"\, (?P<CID>[0-9]+?)\)/', $datas, $matches) ) {
         	X_Debug::e("Content_ID pattern failure");
         	throw new Exception("Content_ID pattern failure");
         }
         $content_id = $matches['CID'];
         
         echo "<b>CONTENT ID FOUND:</b><textarea>".htmlentities($content_id)."</textarea><br/>";
         */
         $matches = array();
         if (!preg_match('/videoEmbedId = "(?P<EID>[^\\"]+?)"/', $datas, $matches)) {
             X_Debug::e("EID pattern failure");
             X_Debug::i("Searching EID in: \n{$datas}");
             throw new Exception("EID pattern failure");
         }
         $eid = $matches['EID'];
         //echo "<b>EID FOUND:</b><textarea>".htmlentities($eid)."</textarea><br/>";
         X_Debug::i("EID Found {{$eid}}");
         // fetch information about the player, required by rtmp
         //list($swfsize, $swfhash, $swfUrl) = $this->getPlayerData();
         //$http->setHeaders('Host', 'r.hulu.com');
         //echo "<b>API URL:</b><textarea>".htmlentities("http://r.hulu.com/videos?content_id=$content_id")."</textarea><br/>";
         //$http->setUri("http://r.hulu.com/videos?content_id=$content_id");
         $apiUrl = 'http://r.hulu.com/videos?eid=' . $eid;
         X_Debug::i("Fetching video info from {{$apiUrl}}");
         $http->setUri($apiUrl);
         //echo "<b>API URL:</b><textarea>".htmlentities($apiUrl)."</textarea><br/>";
         $datas = $http->request()->getBody();
         //$http->setHeaders('Host', null);
         //echo "<b>API RESPONSE 1</b><textarea>".htmlentities($datas)."</textarea><br/>";
         $xml = new SimpleXMLElement($datas);
         if ($xml->video == null) {
             X_Debug::e("Invalid response for EID {{$eid}}");
             X_Debug::i("Response: \n{$datas}");
             throw new Exception("Invalid response for EID {{$eid}}");
         }
         //echo "<b>ENCODED PID</b><textarea>".htmlentities((string) $xml->video->pid[0])."</textarea><br/>";
         X_Debug::i("Encoded PID: {{$xml->video[0]->pid[0]}}");
         $pid = $this->decodePid((string) $xml->video[0]->pid[0]);
         X_Debug::i("Decoded PID: {{$pid}}");
         //echo "<b>DECRYPTED PID</b><textarea>".htmlentities($pid)."</textarea><br/>";
         $title = (string) $xml->video->title[0];
         if ($xml->video->{'media-type'} == "TV") {
             $show_name = $xml->video->show->name[0];
             $season = $xml->video->{"season-number"}[0];
             $episode_number = $xml->video->{"episode-number"}[0];
             $title = sprintf('%s - S%02dE%02d - %s', $show_name, $season, $episode_number, $title);
         }
         $description = (string) $xml->video->description[0];
         $length = X_Env::formatTime((int) $xml->video->duration[0]);
         $thumbnail = (string) $xml->video->{"thumbnail-url"}[0];
         $needProxy = $xml->video->{"allow-international"}[0] == 'false' ? true : false;
         if ($infoOnly) {
             $infos = array('title' => $title, 'description' => $description, 'length' => $length, 'thumbnail' => $thumbnail, 'needProxy' => $needProxy);
             X_Debug::i("Video info: " . print_r($infos, true));
             return $infos;
         }
         // new focus on smil infos
         //$auth = md5($pid.self::$KEYS_PLAYER);
         //echo "<b>AUTH</b><pre>$auth</pre><br/>";
         //echo "<b>REQUEST</b><pre>http://s.hulu.com/select.ashx?pid=$pid&auth=$auth&v=".self::$KEYS_V."</pre><br/>";
         //$http->setUri("http://s.hulu.com/select.ashx?pid=$pid&auth=$auth&v=".self::$KEYS_V);
         $now = (int) time();
         $parameters = array('video_id' => $pid, 'v' => self::$KEYS_V, 'ts' => (string) $now, 'np' => '1', 'vp' => '1', 'device_id' => '', 'pp' => 'Desktop', 'dp_id' => 'Hulu', 'region' => 'US', 'ep' => '1', 'language' => 'en');
         $paramKeys = array_keys($parameters);
         $sortedParams = $parameters;
         ksort($sortedParams);
         $bcsl = '';
         foreach ($sortedParams as $key => $value) {
             $bcsl .= $key . $value;
         }
         $bcs = hash_hmac('md5', $bcsl, self::$HMAC);
         $smil_file_url = 'http://s.hulu.com/select?' . http_build_query($sortedParams) . "&bcs={$bcs}";
         X_Debug::i("Fetching SMIL file from {{$smil_file_url}}");
         //echo "<b>SMIL FILE URL</b><textarea>".htmlentities($smil_file_url)."</textarea><br/>";
         $http->setUri($smil_file_url);
         $datas = $http->request()->getBody();
         //echo "<b>ENCODED SMIL</b><textarea>".htmlentities($datas)."</textarea><br/>";
         $datas = $this->decodeSmil($datas);
         //echo "<b>DECRYPTED SMIL</b><textarea>".htmlentities($datas)."</textarea><br/>";
         X_Debug::i("Decoded SMIL (50 chars only): \n" . substr($datas, 0, 50) . "...");
         $xml = new SimpleXMLElement($datas);
         //$vids = $xml->body->switch[1]->video[0];
         $vids = $xml->body->switch[1]->video;
         //[0];
         //$ref = $xml->body->switch[1]->ref[0]; // choose the better source... ignored now
         //echo "<b>VIDEOS</b><pre>".print_r($vid, true)."</pre><br/>";
         if ($this->options->get('priority', 'cdn')) {
             $vids = $this->filterCdn($vids, $this->options->get('cdn', 'limelight'));
             $vids = $this->filterCdn($vids, $this->options->get('quality', '400_h264'));
         } else {
             $vids = $this->filterCdn($vids, $this->options->get('quality', '400_h264'));
             $vids = $this->filterCdn($vids, $this->options->get('cdn', 'limelight'));
         }
         $vid = @$vids[0];
         // if no vid available yet, just try to get the first one
         if (!$vid) {
             X_Debug::w('Filter mode failed');
             $vid = $xml->body->switch[1]->video[0];
         }
         if (is_null($vid)) {
             X_Debug::e('No video tag. Video requires HULU Plus or you are not in US');
             X_Debug::i("Video info: " . print_r($vid, true));
             throw new Exception('No video tag. Video requires HULU Plus or you are not in US');
         }
         X_Debug::i("Selected video info: " . print_r($vid, true));
         // ported code: http://code.google.com/p/bluecop-xbmc-repo/source/browse/trunk/plugin.video.hulu/resources/lib/stream_hulu.py?spec=svn157&r=157
         $stream = (string) $vid['stream'];
         $server = (string) $vid['server'];
         $token = (string) $vid['token'];
         $cdn = (string) $vid['cdn'];
         $hostname = "";
         $appName = "";
         $protocol = "";
         $pattern = '/^(?P<protocol>[a-zA-z]+:\\/\\/)(?P<hostname>[^\\/]+)\\/(?P<appname>.*)$/';
         $matches = array();
         if (preg_match($pattern, $server, $matches)) {
             $protocol = $matches['protocol'];
             $hostname = $matches['hostname'];
             $appName = $matches['appname'];
         }
         // rtmp params based on cdn
         switch ($cdn) {
             case 'level3':
                 $appName .= "?sessionid=sessionId&{$token}";
                 $stream = substr($stream, 0, -4);
                 // remove .mp4
                 $server = "{$server}?sessionid=sessionId&{$token}";
                 break;
             case 'limelight':
                 $appName .= "?sessionid=sessionId&{$token}";
                 $stream = substr($stream, 0, -4);
                 // remove .mp4
                 $server = "{$server}?sessionid=sessionId&{$token}";
                 break;
             case 'akamai':
                 $appName .= "?sessionid=sessionId&{$token}";
                 $server = "{$server}?sessionid=sessionId&{$token}";
                 break;
             default:
         }
         $this->_fetched = array('title' => $title, 'description' => $description, 'length' => $length, 'thumbnail' => $thumbnail, 'eid' => $eid, 'pid' => $pid, 'needProxy' => $needProxy, 'stream' => $stream, 'server' => $server, 'token' => $token, 'cdn' => $cdn, 'hostname' => $hostname, 'protocol' => $protocol, 'appName' => $appName, 'playpath' => $stream, 'pageUrl' => self::HULU_PLAYER, 'swfUrl' => self::HULU_PLAYER);
         $this->_fetched['url'] = X_RtmpDump::buildUri(array('rtmp' => $server, 'app' => $appName, 'playpath' => $stream, 'swfUrl' => self::HULU_PLAYER, 'pageUrl' => self::HULU_PLAYER, 'swfVfy' => self::HULU_PLAYER));
         $this->_cachedSearch[$this->_location] = $this->_fetched;
         //X_Debug::i("All info: ".print_r($this->_fetched, true));
         return $this->_fetched;
     }
 }