/** * Updates the specified module from the specified distribution. * The order of operations is as follows: 1) Downloads _files list, * _files.md5 checksum, _update script, and _update.md5 checksum, * and compares them for validity. 2) Backs up the existing module * to _backup/MODULENAME/VERSION/MODULENAME. 3) Parses _files list and * creates any new directories, then downloads each file from the _files * list and verifies it before saving it to disk. Files that have a * special <skipIfUpdate>Yes</skipIfUpdate> tag are skipped. * 4) Runs the _update script by eval()ing it. If at any time the * installation fails, it sets an error message, calls restoreBackup(), * and returns false immediately. * * @access private * @param string $name * @param string $distro * @return boolean * */ function _update($name, $distro) { $_files = $this->getFile($this->distros[$distro]->downloadSite . '/source/' . $name . '/_files'); if (!$_files) { $this->error = 'File list not found!'; return false; } $checksum = $this->getChecksum($this->distros[$distro]->checksumSite . '/checksums/' . $name . '/_files.md5'); if (!$checksum) { $this->error = 'Checksum file not found!'; return false; } if ($checksum != md5($_files)) { $this->error = 'List file and checksum do not match!'; return false; } /* $_update = $this->getFile ($this->distros[$distro]->downloadSite . '/source/' . $name . '/_update'); if (! $_update) { $this->error = 'Install script not found!'; return false; } $checksum = $this->getChecksum ($this->distros[$distro]->checksumSite . '/checksums/' . $name . '/_update.md5'); if (! $checksum) { $this->error = 'Checksum file not found!'; return false; } if ($checksum != md5 ($_update)) { $this->error = 'Update script and checksum do not match!'; return false; } */ // backup the existing module to _backup/modulename/version global $loader; $loader->inc('saf.App.Module'); $loader->inc('saf.XML.Sloppy'); $loader->inc('saf.File.Directory'); $module = new Module($name); if (!is_dir('mod/_backup/' . $name)) { // up to /mod/_backup/MODULENAME chdir('mod/_backup'); mkdir($name, 0775); chdir($name); } else { // up to /mod/_backup/MODULENAME chdir('mod/_backup/' . $name); } if (!is_dir($module->version)) { mkdir($module->version, 0775); } chdir('../..'); // down to /mod if (eregi('^Win', PHP_OS)) { $msg = @exec('xcopy/S/E ' . $name . ' ' . preg_replace('/\\//', '\\', '_backup/' . $name . '/' . $module->version), $arr, $res); if (!$res) { $this->error = 'Backup failed! ' . join(', ', $arr); return false; } } else { $msg = @system('cp -R ' . $name . ' _backup/' . $name . '/' . $module->version, $res); if ($res === false) { $this->error = 'Backup failed! ' . $res; return false; } } // parse _files and create any missing directories $sloppy = new SloppyDOM(); $doc = $sloppy->parse($_files); if (!$doc) { $this->error = $sloppy->error; $this->restoreBackup($name, $module->version); return false; } foreach ($doc->query('/filelist/directories/name') as $dir) { Dir::build($dir->content, 0775); } chdir('..'); // down to / // download and check each file for validity foreach ($doc->query('/filelist/files/file') as $file) { $file = $file->makeObj(); // skip any file that contains a <skipIfUpdate>Yes</skipIfUpdate> tag if ($file->skipIfUpdate) { continue; } if ($file->type == 'binary') { $contents = $this->getFile($file->link, true); } else { $contents = $this->getFile($file->link); } if ($file->md5sum != md5($contents)) { $this->error = 'File ' . $file->name . ' and checksum did not match!'; $this->restoreBackup($name, $module->version); return false; } $fp = fopen('mod/' . $file->directory . '/' . $file->name, 'w'); if (!$fp) { $this->error = 'Could not create file ' . $file->name . '!'; $this->restoreBackup($name, $module->version); return false; } fwrite($fp, $contents); fclose($fp); } // run the _update script //eval ('?//>' . $_update); return true; }
<?php $data = @join('', @file('http://www.simian.ca/apps.xml')); if (!$data) { return; echo '<h1>Not Installed</h1>'; echo '<p>Error: Unable to retrieve tool list.</p>'; return; } loader_import('saf.XML.Sloppy'); $sloppy = new SloppyDOM(); $doc = $sloppy->parse($data); if (!$doc) { echo '<p>Error: ' . $sloppy->error . '</p>'; return; } ob_start(); echo '<h1>' . intl_get('Not Installed') . '</h1>'; echo '<p align="center"><table border="0" cellpadding="10" cellspacing="1" width="100%">'; loader_import('saf.Misc.Alt'); $alt = new Alt('#fff', '#eee'); $count = 0; $shown = false; foreach ($doc->_apps->children as $child) { $item = $child->makeObj(); if (@is_dir(site_docroot() . '/inc/app/' . $item->id)) { continue; } $shown = true; $count++; if ($count == 1) {
/** * Parses an XML document into an INI $struct, which can then * be saved to a file or processed further. * * @param string XML data or file name * @param boolean is the $data a file * @return array hash */ function fromXml($data, $isFile = false) { global $loader; $loader->import('saf.XML.Sloppy'); $sloppy = new SloppyDOM(); if ($isFile) { $data = @join('', @file($data)); } $doc = $sloppy->parse($data); if (!$doc) { $this->error = $sloppy->error; return false; } $struct = array(); foreach ($doc->root->children as $child) { if (count($child->children) > 0) { // 2-d $struct[$child->name] = array(); foreach ($child->children as $item) { $struct[$child->name][$item->name] = $item->content; } } else { // single level $struct[$child->name] = $child->content; } } return $struct; }
/** * Fetches a remote XML document and returns an object structure * parsed by SloppyDOM. Returns false if there is a parsing * error, and sets the $error property with the error message. * $expires can be set to either 'auto' (the default), which * tries to discover the cache duration based on the * syn:updatePeriod and syn:updateFrequency values in the * feed itself, and defaults to 1 hour (3600 seconds) if they * are not present. If $expires is set to a number, that is * used as the number of seconds to cache the feed for. * * @access public * @param string * @param mixed * @return object */ function &fetch($url, $expires = 'auto') { $ps = new PropertySet('rss_fetch', 'source'); $doc = false; $res = $ps->get($url); if ($res) { $doc = unserialize($res); if ($doc->_expires < time()) { $doc = false; } } if (!$doc) { if (extension_loaded('curl')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_MAXREDIRS, 3); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_VERBOSE, 0); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); $rssfeed = curl_exec($ch); if (!$rssfeed) { $this->error = 'RSS source not found: ' . curl_error($ch) . ' (' . curl_errno($ch) . ')'; curl_close($ch); return false; } curl_close($ch); } else { $rssfeed = @file($url); if (!is_array($rssfeed) || count($rssfeed) <= 0) { $this->error = 'RSS source not found'; return false; } $rssfeed = @join('', $rssfeed); } $sloppy = new SloppyDOM(); $doc = $sloppy->parse($rssfeed); if (!$doc) { $this->error = $sloppy->error; return false; } $root = $doc->root->name; $ns = false; foreach (array_keys($doc->root->attributes) as $k) { if ($doc->root->attributes[$k]->value == 'http://purl.org/rss/1.0/modules/syndication/') { $ns = str_replace('xmlns:', '', $doc->root->attributes[$k]->name); } } if (!$ns) { $ns = 'syn'; } // auto tries to auto-discover the cache expiration time if ($expires == 'auto') { $node =& $doc->query($root . '/channel/' . $ns . ':updatePeriod'); if (is_object($node)) { switch ($node->content) { case 'yearly': $node =& $doc->query($root . '/channel/' . $ns . ':updateFrequency'); $expires = $node->content * 31536000; break; case 'monthly': $node =& $doc->query($root . '/channel/' . $ns . ':updateFrequency'); $expires = $node->content * 2592000; break; case 'weekly': $node =& $doc->query($root . '/channel/' . $ns . ':updateFrequency'); $expires = $node->content * 604800; break; case 'daily': $node =& $doc->query($root . '/channel/' . $ns . ':updateFrequency'); $expires = $node->content * 86400; break; case 'hourly': default: $node =& $doc->query($root . '/channel/' . $ns . ':updateFrequency'); $expires = $node->content * 3600; break; } } else { // if all else fails, default to 1 hour $expires = 3600; } // require an expiry time -- can't be none } elseif ($expires <= 0) { $expires = 3600; } $doc->_expires = time() + $expires; $ps->set($url, serialize($doc)); } return $doc; }
* RSS Viewer Example * * This example shows how easy it is to display syndicated content from * another web site. * * Please note: for a more full-featured RSS viewer, please use the box * news/rss/viewer instead of building on this. It already features * automatic caching and other handy features. */ // set our resource to our example rss feed $resource = site_url() . site_prefix() . '/index/example-rss-action'; // retrieve rss feed $rssfeed = join('', file($resource)); // parse the rss feed contents loader_import('saf.XML.Sloppy'); $sloppy = new SloppyDOM(); $doc = $sloppy->parse($rssfeed); if (!$doc) { echo $sloppy->error; return; } $channel = array_shift($doc->query('/rdf:RDF/channel')); $channel = $channel->makeObj(); // build a list of items $items = $doc->query('/rdf:RDF/item'); foreach ($items as $key => $item) { $items[$key] = $item->makeObj(); } $channel->items = $items; page_title($channel->title); echo template_simple('rss_viewer.spt', $channel);
/** * Uses the internal $output array from a previous * call to parse() and returns an XMLDoc object representation * of the document. Sets $error, $err_code, $err_line, etc. * from the SloppyDOM error values and returns false should * an error occur, which it easily could because there's * no guarantee "cleaned up" markup is necessarily correctly * formatted markup. * * @access public * @return object reference * */ function &toXMLDoc() { global $loader; $loader->import('saf.XML.Sloppy'); $sloppy = new SloppyDOM(); $xml = $this->toXML(); $xml = preg_replace('/&([a-zA-Z0-9]+);/s', '<ch:\\1 />', $xml); $doc = $sloppy->parse($xml); if (!$doc) { $this->error = $sloppy->error; $this->err_code = $sloppy->err_code; $this->err_byte = $sloppy->err_byte; $this->err_line = $sloppy->err_line; $this->err_colnum = $sloppy->err_colnum; return false; } return $doc; }
if (empty($parameters['url'])) { return; } else { $url = $parameters['url']; } if (empty($parameters['duration'])) { $duration = $box['Custom']['duration']; } else { $duration = $parameters['duration']; } if ($cache->expired($cache->serialize($url), $duration)) { // re-cache the document $xmldata = @join('', @file($url)); loader_import('saf.XML.Sloppy'); $sloppy = new SloppyDOM(); $doc = $sloppy->parse($xmldata); if (!$doc) { $this->error = $sloppy->error; return; } $cache->file($url, serialize($doc)); } else { // fetch document from cache loader_import('saf.XML.Doc'); $doc = unserialize($cache->show($url)); } // display the document $root = $doc->root->name; //$menu = $doc->makeMenu (); //echo $menu->display ('html', '{title} - {content}'); //return;