which is * released under the GPL license. * * The lastest version of MagpieRSS can be obtained from: * http://magpierss.sourceforge.net */ function fetch_rss($url) { $url = apply_filters('fetch_rss_url', $url); $feeder = new WP_Feeder(); $feed = $feeder->get($url); $magpie = $feed->to_magpie(); return $magpie; } class WP_Feeder { var $url, $http_client, $last_fetch, $wp_object_cache, $cache; var $redirects = 0; var $max_redirects = 3; var $cache_redirects = true; function WP_Feeder () { global $wp_object_cache; if ( $wp_object_cache->cache_enabled ) { $this->wp_object_cache = true; } else { $this->wp_object_cache = false; $this->cache = new RSSCache(); } } function get ($url) { $cached = false; $feed = $this->cache_get($url); if ( is_object($feed) ) { $cached = true; } else { unset($feed); $this->fetch($url); $feed = new WP_Feed($this->http_client); } // Handle redirects if ( $feed->status >= 300 && $feed->status < 400 && $this->redirects < $this->max_redirects ) { ++$this->redirects; if ( $this->cache_redirects && !$cached ) $this->cache_set($url, $feed); return $this->get($feed->redirect_location); } if ( !$cached ) $this->cache_set($url, $feed); return $feed; } function fetch ($url) { $this->last_fetch = $url; $parts = parse_url($url); $url = ($parts['path'] ? $parts['path'] : '/') . ($parts['query'] ? '?'.$parts['query'] : ''); $this->http_client = new HttpClient('', 80); $this->http_client->handle_redirects = false; $this->http_client->host = $parts['host']; $this->http_client->port = $parts['port'] ? $parts['port'] : 80; $this->http_client->user_agent = 'WordPress ' . $GLOBALS['wp_version'] . ' Feed Client'; $this->http_client->get($url); } function cache_get ($url) { if ( $this->wp_object_cache ) return unserialize(wp_cache_get($url, 'rss')); return $this->cache->get($url); } function cache_set ($url, $object) { if ( $this->wp_object_cache ) return wp_cache_set($url, serialize($object), 'rss', 3600); return $this->cache->set($url, $object); } } class RSSCache { var $BASE_CACHE = 'wp-content/cache'; // where the cache files are stored var $MAX_AGE = 43200; // when are files stale, default twelve hours var $ERROR = ''; // accumulate error messages function RSSCache ($base='', $age='') { if ( $base ) { $this->BASE_CACHE = $base; } if ( $age ) { $this->MAX_AGE = $age; } } function set ($url, $rss) { global $wpdb; $cache_option = 'rss_' . $this->file_name( $url ); $cache_timestamp = 'rss_' . $this->file_name( $url ) . '_ts'; if ( !$wpdb->get_var("SELECT option_name FROM $wpdb->options WHERE option_name = '$cache_option'") ) add_option($cache_option, '', '', 'no'); if ( !$wpdb->get_var("SELECT option_name FROM $wpdb->options WHERE option_name = '$cache_timestamp'") ) add_option($cache_timestamp, '', '', 'no'); update_option($cache_option, $rss); update_option($cache_timestamp, time() ); return $cache_option; } function get ($url) { $this->ERROR = ""; $cache_option = 'rss_' . $this->file_name( $url ); if ( ! get_option( $cache_option ) ) { $this->debug( "Cache doesn't contain: $url (cache option: $cache_option)" ); return 0; } $rss = get_option( $cache_option ); return $rss; } function check_cache ( $url ) { $this->ERROR = ""; $cache_option = $this->file_name( $url ); $cache_timestamp = 'rss_' . $this->file_name( $url ) . '_ts'; if ( $mtime = get_option($cache_timestamp) ) { // find how long ago the file was added to the cache // and whether that is longer then MAX_AGE $age = time() - $mtime; if ( $this->MAX_AGE > $age ) { // object exists and is current return 'HIT'; } else { // object exists but is old return 'STALE'; } } else { // object does not exist return 'MISS'; } } function serialize ( $rss ) { return serialize( $rss ); } function unserialize ( $data ) { return unserialize( $data ); } function file_name ($url) { return md5( $url ); } function error ($errormsg, $lvl=E_USER_WARNING) { // append PHP's error message if track_errors enabled if ( isset($php_errormsg) ) { $errormsg .= " ($php_errormsg)"; } $this->ERROR = $errormsg; if ( MAGPIE_DEBUG ) { trigger_error( $errormsg, $lvl); } else { error_log( $errormsg, 0); } } function debug ($debugmsg, $lvl=E_USER_NOTICE) { if ( MAGPIE_DEBUG ) { $this->error("MagpieRSS [debug] $debugmsg", $lvl); } } } class WP_Feed { var $status; var $raw_xml; var $last_updated; var $tree; var $items; var $children; var $parser; var $feed_type; var $feed_version; var $stack = array(); function WP_Feed ($source) { # if PHP xml isn't compiled in, die # if (!function_exists('xml_parser_create')) { $this->error( "Failed to load PHP's XML Extension. " . "http://www.php.net/manual/en/ref.xml.php", E_USER_ERROR ); } // Handle overloaded arg (string or HttpClient object) if ( is_object($source) ) { if ( $source->status >= 200 && $source->status < 300) { $this->etag = $source->headers['etag']; $this->last_modified = $source->headers['last-modified']; $source = $source->content; } else { $this->scour(); $this->status = $source->status; $this->redirect_location = $source->headers->location; $this->bathe(); return; } } list($parser, $source) = $this->create_parser($source, 'UTF-8', null, true); if (!is_resource($parser)) { $this->error( "Failed to create an instance of PHP's XML parser. " . "http://www.php.net/manual/en/ref.xml.php", E_USER_ERROR ); } $this->parser = $parser; # pass in parser, and a reference to this object # setup handlers # xml_set_object($this->parser, $this); xml_set_element_handler($this->parser, 'start_element', 'end_element'); xml_set_character_data_handler( $this->parser, 'cdata'); $status = xml_parse( $this->parser, $source ); if (! $status ) { $errorcode = xml_get_error_code( $this->parser ); if ( $errorcode != XML_ERROR_NONE ) { $xml_error = xml_error_string( $errorcode ); $error_line = xml_get_current_line_number($this->parser); $error_col = xml_get_current_column_number($this->parser); $errormsg = "$xml_error at line $error_line, column $error_col"; $this->error( $errormsg ); } } // SUPER SLOPPY FEED DISCOVERY!! TO-DO: AXE THIS CRAP!! if ( !is_object($this->feed) || !method_exists($this->feed, 'to_xml') ) { if ( preg_match_all('/]*href=([^ >]+)[^>]+>/i', $source, $matches) ) { $types = array('rss', 'atom'); foreach ( $types as $type ) foreach ( $matches[0] as $key => $link ) if ( preg_match('/rel=.alternate./', $link) && preg_match("/type=[^ >]*{$type}[^ >]*/", $link) ) break 2; $this->scour(); $this->redirect_location = 'http://xml.wordpress.com/get/' . trim($matches[1][$key], '\'"'); $this->status = 301; return; } else { $this->scour(); $this->status = 404; return; } } else { $this->status = 200; } xml_parser_free( $this->parser ); unset($this->parser); $this->bathe(); } function to_xml() { if ( is_object($this->feed) && method_exists($this->feed, 'to_xml') ) return $this->feed->to_xml(); return false; } // Called internally by xml_parse(). We create an object and call its start_element method. function start_element($p, $element, &$attrs) { $el = $element;// = strtolower($element); // $attrs = array_change_key_case($attrs, CASE_LOWER); // If there is an extended class for this element, use it. $class = 'element'; $maybe_class = $test_class = strtolower(str_replace(':', '_', $el)); if ( class_exists($maybe_class) ) { for ($classes[] = $test_class; $test_class = get_parent_class ($test_class); $classes[] = $test_class); if ( in_array($class, $classes) ) $class = $maybe_class; } // Instantiate an object for this element. $object = new $class(); // Tell the element to start itself. $object->start_element($p, $element, $attrs, $this); } function cdata ($p, $data) { $this->stack[0]->cdata($p, $data, $this); } function end_element ($p, $el) { $this->stack[0]->end_element($p, $el, $this); } function create_parser($source, $out_enc, $in_enc, $detect) { if ( substr(phpversion(),0,1) == 5) { $parser = $this->php5_create_parser($in_enc, $detect); } else { list($parser, $source) = $this->php4_create_parser($source, $in_enc, $detect); } if ($out_enc) { $this->encoding = $out_enc; xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $out_enc); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); } return array($parser, $source); } function php5_create_parser($in_enc, $detect) { // by default php5 does a fine job of detecting input encodings if(!$detect && $in_enc) { return xml_parser_create($in_enc); } else { return xml_parser_create(''); } } /** * Instaniate an XML parser under PHP4 * * Unfortunately PHP4's support for character encodings * and especially XML and character encodings sucks. As * long as the documents you parse only contain characters * from the ISO-8859-1 character set (a superset of ASCII, * and a subset of UTF-8) you're fine. However once you * step out of that comfy little world things get mad, bad, * and dangerous to know. * * The following code is based on SJM's work with FoF * @see http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss * */ function php4_create_parser($source, $in_enc, $detect) { if ( !$detect ) { return array(xml_parser_create($in_enc), $source); } if (!$in_enc) { if (preg_match('//m', $source, $m)) { $in_enc = strtoupper($m[1]); $this->source_encoding = $in_enc; } else { $in_enc = 'UTF-8'; } } if ($this->known_encoding($in_enc)) { return array(xml_parser_create($in_enc), $source); } // the dectected encoding is not one of the simple encodings PHP knows // attempt to use the iconv extension to // cast the XML to a known encoding // @see http://php.net/iconv if (function_exists('iconv')) { $encoded_source = iconv($in_enc,'UTF-8', $source); if ($encoded_source) { return array(xml_parser_create('UTF-8'), $encoded_source); } } // iconv didn't work, try mb_convert_encoding // @see http://php.net/mbstring if(function_exists('mb_convert_encoding')) { $encoded_source = mb_convert_encoding($source, 'UTF-8', $in_enc ); if ($encoded_source) { return array(xml_parser_create('UTF-8'), $encoded_source); } } // else $this->error("Feed is in an unsupported character encoding. ($in_enc) " . "You may see strange artifacts, and mangled characters.", E_USER_NOTICE); return array(xml_parser_create(), $source); } function known_encoding($enc) { $enc = strtoupper($enc); if ( in_array($enc, array('UTF-8', 'US-ASCII', 'ISO-8859-1')) ) { return $enc; } else { return false; } } function error ($errormsg, $lvl=E_USER_WARNING) { // append PHP's error message if track_errors enabled if ( isset($php_errormsg) ) { $errormsg .= " ($php_errormsg)"; } if ( MAGPIE_DEBUG ) { // trigger_error( $errormsg, $lvl); } else { error_log( $errormsg, 0); } $notices = E_USER_NOTICE|E_NOTICE; if ( $lvl&$notices ) { $this->WARNING = $errormsg; } else { $this->ERROR = $errormsg; } } // Remove empty and |^_.*| object vars function bathe() { foreach ( get_object_vars($this) as $key => $data ) if ( empty($this->$key) || substr($key, 0, 1) == '_' ) unset($this->$key); } // Remove ALL object vars function scour() { foreach ( get_object_vars($this) as $key => $data ) unset($this->$key); } function to_magpie() { $magpie = new stdClass(); foreach ( $this as $var => $value ) { if ( $var == 'feed' ) { continue; } else { $magpie->$var = $this->$var; } } $magpie->items = array(); if ( is_object($this->feed) && method_exists($this->feed, 'to_magpie') ) { $feed = $this->feed->to_magpie(); if ( is_array($feed) ) { foreach ( $this->feed->to_magpie() as $var => $val ) { if ( $var == 'items' ) $magpie->items = $val; else $magpie->channel["$var"] = $val; } } } return $magpie; } } class element { function element() { } function start_element($p, $el, $attr, &$mag) { $this->name = $el; $this->attributes = $attr; array_unshift($mag->stack, $this); } function cdata($p, $data, &$mag) { if ( empty($this->children) ) $this->appendText($data); } function end_element($p, $el, &$mag) { array_shift($mag->stack); $this->bathe(); if ( is_object($mag->stack[0]) ) $mag->stack[0]->appendChild($this); } function wrap_cdata() { if ( strpos($this->innerText, '<') ) { $spacer = (substr($this->innerText, -1) == ']') ? ' ' : ''; $this->innerText = str_replace(']]>', ']]>', $this->innerText); $this->innerText = 'innerText . $spacer . ']]>'; } } function appendText($text) { $this->innerText .= $text; } function appendChild($object) { $this->children[] = & $object; } // Add self to array function to_array(&$array) { $self = get_object_vars($this); unset($self['children']); foreach ( $this->children as $child ) $child->to_array($self); $array[$this->name] = $self; } // Return self as XML function to_xml($indent = "\t", $generation = 0) { $self = "<$this->name"; $self .= $this->attributes ? ' '.string_attributes($this->attributes) : ''; if ( empty($this->innerText) && empty($this->children) ) $self .= " />\n"; else { $self .= ">"; if ( $this->children ) { $self .= "\n"; foreach ( $this->children as $child ) $self .= $child->to_xml($indent, $generation + 1); $self .= $indent ? $this->indent('', $indent, $generation) : ''; } else { $self .= $this->innerText; } $self .= "name>\n"; } return $indent ? $this->indent($self, $indent, $generation) : $self; } function indent($string, $indent, $generation) { for ( $i = ''; strlen($i) < $generation; $i .= $indent ) ; return $i . $string; } /** * Gets the innerText of the first matching element in the vars * @param string Provide any number of strings to try * @return mixed */ function getChildText() { foreach ( func_get_args() as $name ) foreach ( $this->children as $element ) if ( $element->name == $name ) return $element->innerText; return false; } /** * Gets a ref to the first matching element * @param string Provide any number of strings to try * @return object */ function &getChildElement() { foreach ( func_get_args() as $name ) foreach ( $this->children as $key => $element ) if ( $element->name == $name ) return $this->children[$key]; return false; } function getAttribute($name) { if ( is_array($this->attributes) ) foreach ( $this->attributes as $attr => $value ) if ( $attr == $name ) return $value; return null; } function bathe() { foreach ( get_object_vars($this) as $var => $value ) if ( empty($this->$var) ) unset($this->$var); } function to_magpie() { if ( strlen(trim($this->innerText)) > 0 ) return $this->innerText; if ( is_array($this->attributes) ) $e = $this->attributes; if ( is_array($this->children) && count($this->children) > 0 ) foreach ( $this->children as $k => $c ) $e[$k] = $this->children[$k]->to_magpie(); return $e; } } // Base Atom class class feed extends element { function end_element($p, $el, &$mag) { $mag->feed = $this; $mag->is_feed = true; $mag->last_modified = $this->last_modified(); $mag->stack = array(); } function last_modified() { $time = parse_w3cdtf($this->getChildText('modified')); return gmdate('D, d M Y H:i:s T', $time); } function to_magpie() { foreach ( $this->children as $k => $c ) { if ( $this->children[$k]->name == 'entry' ) $magpie['items'][] = $this->children[$k]->to_magpie(); else $magpie[$this->children[$k]->name] = $this->children[$k]->innerText; } return $magpie; } } // RSS base class class rss extends feed { function last_modified() { $channel =& $this->getChildElement('channel'); $date = $channel->getChildText('pubDate', 'lastBuildDate'); return gmdate('D, d M Y H:i:s T', strtotime($date)); } function to_magpie() { return $this->children[0]->to_magpie(); } } class rdf_rdf extends feed { function to_magpie() { $magpie = array(); foreach ( $this->children as $k => $child ) { if ( $this->children[$k]->name == 'item' ) $magpie['items'][] = $this->children[$k]->to_magpie(); elseif ( method_exists($this->children[$k], 'to_magpie') ) $magpie[$this->children[$k]->name] = $this->children[$k]->to_magpie(); else $magpie[$this->children[$k]->name] = $this->children[$k]->innerText; } if ( is_array($magpie['channel']) ) $magpie = array_merge($magpie['channel'], $magpie); return $magpie; } } class channel extends element { function to_magpie() { foreach ( $this->children as $k => $c ) { if ( $this->children[$k]->name == 'item' ) $magpie['items'][] = $this->children[$k]->to_magpie(); else $magpie[$this->children[$k]->name] = $this->children[$k]->innerText; } return $magpie; } } // Atom article class class entry extends element { function to_magpie() { foreach ( $this->children as $k => $v ) { if ( is_object($this->children[$k]) ) $value = $this->children[$k]->to_magpie(); else $value = $this->children[$k]->innerText; $name = $this->children[$k]->name; $norms = array( 'dc:subject' => 'categories', 'summary' => 'description', ); $name = str_replace(array_keys($norms), array_values($norms), $name); switch ( $name ) { // The ones that needs to be dereferenced case 'author': $magpie[$name] = $value[0]; break; // The ones that can be multiple case 'categories': $magpie[$name][] = $value; break; default: $magpie[$name] = $value; } } return $magpie; } function to_array(&$array) { $self = get_object_vars($this); unset($self['children']); foreach ( $this->children as $child ) $child->to_array($self); $array['items'][] = $self; } } // RSS article class class item extends entry { function to_magpie() { foreach ( $this->children as $k => $v ) { if ( is_object($this->children[$k]) ) $value = $this->children[$k]->to_magpie(); else $value = $this->children[$k]->innerText; $name = $this->children[$k]->name; $norms = array( 'category' => 'categories', 'content:encoded' => 'content', 'dc:creator' => 'author', 'wfw:commentRss' => 'comments', 'wfw:commentRSS' => 'comments', 'pubDate' => 'pubdate', ); $name = str_replace(array_keys($norms), array_values($norms), $name); switch ( $name ) { // The ones that needs to be dereferenced case 'taxo:topics': $magpie[$name] = $value[0]; break; // The ones that can be multiple case 'categories': $magpie[$name][] = $value; break; default: $magpie[$name] = $value; } } return $magpie; } } class category extends element { function to_array(&$array) { $self = get_object_vars($this); unset($self['children']); foreach ( $this->children as $child ) $child->to_array($self); $array['categories'][] = $self; } } class link extends element { function end_element($p, $el, &$mag) { if ( $href = $this->getAttribute('href') ) $this->innerText = $href; parent::end_element($p, $el, $mag); } } /* Version 0.9, 6th April 2003 - Simon Willison ( http://simon.incutio.com/ ) Manual: http://scripts.incutio.com/httpclient/ */ if ( !class_exists('HttpClient') ) : class HttpClient { // Request vars var $host; var $port; var $path; var $method; var $postdata = ''; var $cookies = array(); var $referer; var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*'; var $accept_encoding = 'gzip'; var $accept_language = 'en-us'; var $user_agent = 'Incutio HttpClient v0.9'; // Options var $timeout = 20; var $use_gzip = true; var $no_cache = false; var $persist_cookies = true; // If true, received cookies are placed in the $this->cookies array ready for the next request // Note: This currently ignores the cookie path (and time) completely. Time is not important, // but path could possibly lead to security problems. var $persist_referers = true; // For each request, sends path of last request as referer var $debug = false; var $handle_redirects = true; // Auaomtically redirect if Location or URI header is found var $max_redirects = 5; var $headers_only = false; // If true, stops receiving once headers have been read. // Basic authorization variables var $username; var $password; // Response vars var $status; var $headers = array(); var $content = ''; var $errormsg; // Tracker variables var $redirect_count = 0; var $cookie_host = ''; function HttpClient($host, $port=80) { $this->host = $host; $this->port = $port; } function get($path, $data = false) { $this->path = $path; $this->method = 'GET'; if ($data) { $this->path .= '?'.$this->buildQueryString($data); } return $this->doRequest(); } function post($path, $data) { $this->path = $path; $this->method = 'POST'; $this->postdata = $this->buildQueryString($data); return $this->doRequest(); } function buildQueryString($data) { $querystring = ''; if (is_array($data)) { // Change data in to postable data foreach ($data as $key => $val) { if (is_array($val)) { foreach ($val as $val2) { $querystring .= urlencode($key).'='.urlencode($val2).'&'; } } else { $querystring .= urlencode($key).'='.urlencode($val).'&'; } } $querystring = substr($querystring, 0, -1); // Eliminate unnecessary & } else { $querystring = $data; } return $querystring; } function doRequest() { // Performs the actual HTTP request, returning true or false depending on outcome if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) { // Set error message switch($errno) { case -3: $this->errormsg = 'Socket creation failed (-3)'; case -4: $this->errormsg = 'DNS lookup failure (-4)'; case -5: $this->errormsg = 'Connection refused or timed out (-5)'; default: $this->errormsg = 'Connection failed ('.$errno.')'; $this->errormsg .= ' '.$errstr; $this->debug($this->errormsg); } return false; } socket_set_timeout($fp, $this->timeout); $request = $this->buildRequest(); $this->debug('Request', $request); fwrite($fp, $request); // Reset all the variables that should not persist between requests $this->headers = array(); $this->content = ''; $this->errormsg = ''; // Set a couple of flags $inHeaders = true; // Now start reading back the response $line = fgets($fp, 4096); // Deal with first line of returned data if (!preg_match('/HTTP\/(\\d\\.\\d)\\s*(\\d+)\\s*(.*)/', $line, $m)) { $this->errormsg = "Status code line invalid: ".htmlentities($line); $this->debug($this->errormsg); return false; } $http_version = $m[1]; // not used $this->status = $m[2]; $status_string = $m[3]; // not used $this->debug(trim($line)); while (!feof($fp)) { $line = fgets($fp, 4096); if ($inHeaders) { if (trim($line) == '') { $inHeaders = false; $this->debug('Received Headers', $this->headers); if ($this->headers_only) { break; // Skip the rest of the input } continue; } if (!preg_match('/([^:]+):\\s*(.*)/', $line, $m)) { // Skip to the next header continue; } $key = strtolower(trim($m[1])); $val = trim($m[2]); // Deal with the possibility of multiple headers of same name if (isset($this->headers[$key])) { if (is_array($this->headers[$key])) { $this->headers[$key][] = $val; } else { $this->headers[$key] = array($this->headers[$key], $val); } } else { $this->headers[$key] = $val; } continue; } // We're not in the headers, so append the line to the contents $this->content .= $line; } fclose($fp); // If data is compressed, uncompress it if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') { $this->debug('Content is gzip encoded, unzipping it'); $this->content = substr($this->content, 10); // See http://www.php.net/manual/en/function.gzencode.php $this->content = gzinflate($this->content); } // If $persist_cookies, deal with any cookies if ($this->persist_cookies && isset($this->headers['set-cookie']) && $this->host == $this->cookie_host) { $cookies = $this->headers['set-cookie']; if (!is_array($cookies)) { $cookies = array($cookies); } foreach ($cookies as $cookie) { if (preg_match('/([^=]+)=([^;]+);/', $cookie, $m)) { $this->cookies[$m[1]] = $m[2]; } } // Record domain of cookies for security reasons $this->cookie_host = $this->host; } // If $persist_referers, set the referer ready for the next request if ($this->persist_referers) { $this->debug('Persisting referer: '.$this->getRequestURL()); $this->referer = $this->getRequestURL(); } // Finally, if handle_redirects and a redirect is sent, do that if ($this->handle_redirects) { if (++$this->redirect_count >= $this->max_redirects) { $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')'; $this->debug($this->errormsg); $this->redirect_count = 0; return false; } $location = isset($this->headers['location']) ? $this->headers['location'] : ''; $uri = isset($this->headers['uri']) ? $this->headers['uri'] : ''; if ($location || $uri) { $url = parse_url($location.$uri); // This will FAIL if redirect is to a different site return $this->get($url['path']); } } return true; } function buildRequest() { $headers = array(); $headers[] = "{$this->method} {$this->path} HTTP/1.0"; // Using 1.1 leads to all manner of problems, such as "chunked" encoding $headers[] = "Host: {$this->host}"; $headers[] = "User-Agent: {$this->user_agent}"; $headers[] = "Accept: {$this->accept}"; if ($this->use_gzip) { $headers[] = "Accept-encoding: {$this->accept_encoding}"; } $headers[] = "Accept-language: {$this->accept_language}"; if ($this->referer) { $headers[] = "Referer: {$this->referer}"; } if ($this->no_cache) { $headers[] = "Pragma: no-cache"; $headers[] = "Cache-control: no-cache"; } // Cookies if ($this->cookies) { $cookie = 'Cookie: '; foreach ($this->cookies as $key => $value) { $cookie .= "$key=$value; "; } $headers[] = $cookie; } // Basic authentication if ($this->username && $this->password) { $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password); } // If this is a POST, set the content type and length if ($this->postdata) { $headers[] = 'Content-Type: application/x-www-form-urlencoded'; $headers[] = 'Content-Length: '.strlen($this->postdata); } $request = implode("\r\n", $headers)."\r\n\r\n".$this->postdata; return $request; } function getStatus() { return $this->status; } function getContent() { return $this->content; } function getHeaders() { return $this->headers; } function getHeader($header) { $header = strtolower($header); if (isset($this->headers[$header])) { return $this->headers[$header]; } else { return false; } } function getError() { return $this->errormsg; } function getCookies() { return $this->cookies; } function getRequestURL() { $url = 'http://'.$this->host; if ($this->port != 80) { $url .= ':'.$this->port; } $url .= $this->path; return $url; } // Setter methods function setUserAgent($string) { $this->user_agent = $string; } function setAuthorization($username, $password) { $this->username = $username; $this->password = $password; } function setCookies($array) { $this->cookies = $array; } // Option setting methods function useGzip($boolean) { $this->use_gzip = $boolean; } function setPersistCookies($boolean) { $this->persist_cookies = $boolean; } function setPersistReferers($boolean) { $this->persist_referers = $boolean; } function setHandleRedirects($boolean) { $this->handle_redirects = $boolean; } function setMaxRedirects($num) { $this->max_redirects = $num; } function setHeadersOnly($boolean) { $this->headers_only = $boolean; } function setDebug($boolean) { $this->debug = $boolean; } // "Quick" static methods function quickGet($url) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; if (isset($bits['query'])) { $path .= '?'.$bits['query']; } $client = new HttpClient($host, $port); if (!$client->get($path)) { return false; } else { return $client->getContent(); } } function quickPost($url, $data) { $bits = parse_url($url); $host = $bits['host']; $port = isset($bits['port']) ? $bits['port'] : 80; $path = isset($bits['path']) ? $bits['path'] : '/'; $client = new HttpClient($host, $port); if (!$client->post($path, $data)) { return false; } else { return $client->getContent(); } } function debug($msg, $object = false) { if ($this->debug) { print '
HttpClient Debug: '.$msg; if ($object) { ob_start(); print_r($object); $content = htmlentities(ob_get_contents()); ob_end_clean(); print '
'.$content.'
'; } print '
'; } } } endif; function string_attributes($attrs) { return join(' ', array_map(create_function('$k,$v', 'return "$k=\"".htmlspecialchars($v)."\"";'), array_keys($attrs), array_values($attrs) ) ); } if ( !function_exists('parse_w3cdtf') ) : function parse_w3cdtf ( $date_str ) { # regex to match wc3dtf $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/"; if ( preg_match( $pat, $date_str, $match ) ) { list( $year, $month, $day, $hours, $minutes, $seconds) = array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[7]); # calc epoch for current date assuming GMT $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year); $offset = 0; if ( $match[10] == 'Z' ) { # zulu time, aka GMT } else { list( $tz_mod, $tz_hour, $tz_min ) = array( $match[8], $match[9], $match[10]); # zero out the variables if ( ! $tz_hour ) { $tz_hour = 0; } if ( ! $tz_min ) { $tz_min = 0; } $offset_secs = (($tz_hour*60)+$tz_min)*60; # is timezone ahead of GMT? then subtract offset # if ( $tz_mod == '+' ) { $offset_secs = $offset_secs * -1; } $offset = $offset_secs; } $epoch = $epoch + $offset; return $epoch; } else { return -1; } } endif; ?>