/** * Given a `$url` and `$timeout`, this function will use the `Gateway` * class to determine that it is a valid URL and returns successfully * before the `$timeout`. If it does not, an error message will be * returned, otherwise true. * * @since Symphony 2.3 * @param string $url * @param integer $timeout * If not provided, this will default to 6 seconds * @param string $error * If this function returns false, this variable will be populated with the * error message. * @return array|boolean * Returns an array with the 'data' if it is a valid URL, otherwise a string * containing an error message. */ public static function __isValidURL($url, $timeout = 6, &$error) { if (!filter_var($url, FILTER_VALIDATE_URL)) { $error = __('Invalid URL'); return false; } // Check that URL was provided $gateway = new Gateway(); $gateway->init($url); $gateway->setopt('TIMEOUT', $timeout); $data = $gateway->exec(); $info = $gateway->getInfoLast(); // 28 is CURLE_OPERATION_TIMEDOUT if ($info['curl_error'] == 28) { $error = __('Request timed out. %d second limit reached.', array($timeout)); return false; } elseif ($data === false || $info['http_code'] != 200) { $error = __('Failed to load URL, status code %d was returned.', array($info['http_code'])); return false; } return array('data' => $data); }
public function execute(array &$param_pool = null) { $result = new XMLElement($this->dsParamROOTELEMENT); $this->dsParamURL = $this->parseParamURL($this->dsParamURL); if (isset($this->dsParamXPATH)) { $this->dsParamXPATH = $this->__processParametersInString($this->dsParamXPATH, $this->_env); } $stylesheet = new XMLElement('xsl:stylesheet'); $stylesheet->setAttributeArray(array('version' => '1.0', 'xmlns:xsl' => 'http://www.w3.org/1999/XSL/Transform')); $output = new XMLElement('xsl:output'); $output->setAttributeArray(array('method' => 'xml', 'version' => '1.0', 'encoding' => 'utf-8', 'indent' => 'yes', 'omit-xml-declaration' => 'yes')); $stylesheet->appendChild($output); $template = new XMLElement('xsl:template'); $template->setAttribute('match', '/'); $instruction = new XMLElement('xsl:copy-of'); // Namespaces if (isset($this->dsParamFILTERS) && is_array($this->dsParamFILTERS)) { foreach ($this->dsParamFILTERS as $name => $uri) { $instruction->setAttribute('xmlns' . ($name ? ":{$name}" : null), $uri); } } // XPath $instruction->setAttribute('select', $this->dsParamXPATH); $template->appendChild($instruction); $stylesheet->appendChild($template); $stylesheet->setIncludeHeader(true); $xsl = $stylesheet->generate(true); $cache_id = md5($this->dsParamURL . serialize($this->dsParamFILTERS) . $this->dsParamXPATH); $cache = new Cacheable(Symphony::Database()); $cachedData = $cache->read($cache_id); $writeToCache = false; $valid = true; $creation = DateTimeObj::get('c'); $timeout = isset($this->dsParamTIMEOUT) ? (int) max(1, $this->dsParamTIMEOUT) : 6; // Execute if the cache doesn't exist, or if it is old. if (!is_array($cachedData) || empty($cachedData) || time() - $cachedData['creation'] > $this->dsParamCACHE * 60) { if (Mutex::acquire($cache_id, $timeout, TMP)) { $ch = new Gateway(); $ch->init($this->dsParamURL); $ch->setopt('TIMEOUT', $timeout); $ch->setopt('HTTPHEADER', array('Accept: text/xml, */*')); $data = $ch->exec(); $info = $ch->getInfoLast(); Mutex::release($cache_id, TMP); $data = trim($data); $writeToCache = true; // Handle any response that is not a 200, or the content type does not include XML, plain or text if ((int) $info['http_code'] !== 200 || !preg_match('/(xml|plain|text)/i', $info['content_type'])) { $writeToCache = false; $result->setAttribute('valid', 'false'); // 28 is CURLE_OPERATION_TIMEOUTED if ($info['curl_error'] == 28) { $result->appendChild(new XMLElement('error', sprintf('Request timed out. %d second limit reached.', $timeout))); } else { $result->appendChild(new XMLElement('error', sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type']))); } return $result; // Handle where there is `$data` } elseif (strlen($data) > 0) { // If the XML doesn't validate.. if (!General::validateXML($data, $errors, false, new XsltProcess())) { $writeToCache = false; } // If the `$data` is invalid, return a result explaining why if ($writeToCache === false) { $element = new XMLElement('errors'); $result->setAttribute('valid', 'false'); $result->appendChild(new XMLElement('error', __('Data returned is invalid.'))); foreach ($errors as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); return $result; } // If `$data` is empty, set the `force_empty_result` to true. } elseif (strlen($data) == 0) { $this->_force_empty_result = true; } // Failed to acquire a lock } else { $result->appendChild(new XMLElement('error', __('The %s class failed to acquire a lock, check that %s exists and is writable.', array('<code>Mutex</code>', '<code>' . TMP . '</code>')))); } // The cache is good, use it! } else { $data = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } // If `$writeToCache` is set to false, invalidate the old cache if it existed. if (is_array($cachedData) && !empty($cachedData) && $writeToCache === false) { $data = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($data)) { $this->_force_empty_result = true; } } // If `force_empty_result` is false and `$result` is an instance of // XMLElement, build the `$result`. if (!$this->_force_empty_result && is_object($result)) { $proc = new XsltProcess(); $ret = $proc->process($data, $xsl); if ($proc->isErrors()) { $result->setAttribute('valid', 'false'); $error = new XMLElement('error', __('Transformed XML is invalid.')); $result->appendChild($error); $element = new XMLElement('errors'); foreach ($proc->getError() as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); } elseif (strlen(trim($ret)) == 0) { $this->_force_empty_result = true; } else { if ($writeToCache) { $cache->write($cache_id, $data, $this->dsParamCACHE); } $result->setValue(PHP_EOL . str_repeat("\t", 2) . preg_replace('/([\\r\\n]+)/', "\$1\t", $ret)); $result->setAttribute('status', $valid === true ? 'fresh' : 'stale'); $result->setAttribute('creation', $creation); } } return $result; }
$cachedData = $cache->check($cache_id); $writeToCache = false; $valid = true; $creation = DateTimeObj::get('c'); $timeout = isset($this->dsParamTIMEOUT) ? (int) max(1, $this->dsParamTIMEOUT) : 6; if (!is_array($cachedData) || empty($cachedData) || time() - $cachedData['creation'] > $this->dsParamCACHE * 60) { if (Mutex::acquire($cache_id, $timeout, TMP)) { $start = precision_timer(); $ch = new Gateway(); $ch->init(); $ch->setopt('URL', $this->dsParamURL); $ch->setopt('TIMEOUT', $timeout); $xml = $ch->exec(); $writeToCache = true; $end = precision_timer('stop', $start); $info = $ch->getInfoLast(); Mutex::release($cache_id, TMP); $xml = trim($xml); // Handle any response that is not a 200, or the content type does not include xml, plain or text if ((int) $info['http_code'] != 200 || !preg_match('/(xml|plain|text)/i', $info['content_type'])) { $writeToCache = false; if (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); } else { $result->setAttribute('valid', 'false'); if ($end > $timeout) { $result->appendChild(new XMLElement('error', sprintf('Request timed out. %d second limit reached.', $timeout))); } else { $result->appendChild(new XMLElement('error', sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type'])));
/** * Get all HTTP response headers and info as an array of arrays. * * @since 1.17 * * @param string $url * @return array * Contains the headers and the infos */ public static function getHttpHead($url) { // Check if we have a cached result if (isset(self::$_result[$url])) { return self::$_result[$url]; } // create the Gateway object $gateway = new Gateway(); // set our url $gateway->init($url); // set some options $gateway->setopt(CURLOPT_URL, $url); $gateway->setopt(CURLOPT_RETURNTRANSFER, true); $gateway->setopt(CURLOPT_HEADER, true); $gateway->setopt(CURLOPT_NOBODY, true); $gateway->setopt(CURLOPT_FOLLOWLOCATION, true); $gateway->setopt(CURLOPT_MAXREDIRS, Image::CURL_MAXREDIRS); // get the raw head response, ignore errors $head = @$gateway->exec(); // Get all info $result = array('headers' => array(), 'info' => $gateway->getInfoLast()); // Clean up $gateway->flush(); if ($head !== false) { $result['headers'] = self::parseHttpHeaderFields($head); } // Save for subsequent requests self::$_result[$url] = $result; return $result; }
public function render(Register $ParameterOutput) { $result = null; $doc = new XMLDocument(); if (isset($this->parameters()->url)) { $this->parameters()->url = self::replaceParametersInString($this->parameters()->url, $ParameterOutput); } if (isset($this->parameters()->xpath)) { $this->parameters()->xpath = self::replaceParametersInString($this->parameters()->xpath, $ParameterOutput); } $cache_id = md5($this->parameters()->url . serialize($this->parameters()->namespaces) . $this->parameters()->xpath); $cache = Cache::instance(); $cachedData = $cache->read($cache_id); $writeToCache = false; $force_empty_result = false; $valid = true; $result = NULL; $creation = DateTimeObj::get('c'); if (isset($this->parameters()->timeout)) { $timeout = (int) max(1, $this->parameters()->timeout); } if (!is_array($cachedData) || empty($cachedData) || time() - $cachedData['creation'] > $this->parameters()->{'cache-timeout'} * 60) { if (Mutex::acquire($cache_id, $timeout, TMP)) { $start = precision_timer(); $ch = new Gateway(); $ch->init(); $ch->setopt('URL', $this->parameters()->url); $ch->setopt('TIMEOUT', $this->parameters()->timeout); $xml = $ch->exec(); $writeToCache = true; $end = precision_timer('STOP', $start); $info = $ch->getInfoLast(); Mutex::release($cache_id, TMP); $xml = trim($xml); if ((int) $info['http_code'] != 200 || !preg_match('/(xml|plain|text)/i', $info['content_type'])) { $writeToCache = false; if (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); } else { $result = $doc->createElement($this->parameters()->{'root-element'}); $result->setAttribute('valid', 'false'); if ($end > $timeout) { $result->appendChild($doc->createElement('error', sprintf('Request timed out. %d second limit reached.', $timeout))); } else { $result->appendChild($doc->createElement('error', sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type']))); } return $result; } } elseif (strlen($xml) > 0 && !General::validateXML($xml, $errors)) { $writeToCache = false; if (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); } else { $result = $doc->createElement($this->parameters()->{'root-element'}, $doc->createElement('error', __('XML returned is invalid.')), array('valid' => 'false')); return $result; } } elseif (strlen($xml) == 0) { $force_empty_result = true; } } elseif (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($xml)) { $force_empty_result = true; } } else { $force_empty_result = true; } } else { $xml = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } if (!$force_empty_result) { $result = new XMLDocument(); $root = $result->createElement($this->parameters()->{'root-element'}); //XPath Approach, saves Transforming the Document. $xDom = new XMLDocument(); $xDom->loadXML($xml); if ($xDom->hasErrors()) { $root->setAttribute('valid', 'false'); $root->appendChild($result->createElement('error', __('XML returned is invalid.'))); $messages = $result->createElement('messages'); foreach ($xDom->getErrors() as $e) { if (strlen(trim($e->message)) == 0) { continue; } $messages->appendChild($result->createElement('item', General::sanitize($e->message))); } $root->appendChild($messages); } else { if ($writeToCache) { $cache->write($cache_id, $xml); } $xpath = new DOMXPath($xDom); ## Namespaces if (is_array($this->parameters()->namespaces) && !empty($this->parameters()->namespaces)) { foreach ($this->parameters()->namespaces as $index => $namespace) { $xpath->registerNamespace($namespace['name'], $namespace['uri']); } } $xpath_list = $xpath->query($this->parameters()->xpath); foreach ($xpath_list as $node) { if ($node instanceof XMLDocument) { $root->appendChild($result->importNode($node->documentElement, true)); } else { $root->appendChild($result->importNode($node, true)); } } $root->setAttribute('status', $valid === true ? 'fresh' : 'stale'); $root->setAttribute('creation', $creation); } } if (!$root->hasChildNodes() || $force_empty_result) { $this->emptyXMLSet($root); } $result->appendChild($root); return $result; }
public static function getVideoFeed($video_id) { // Fetch document: $gateway = new Gateway(); $gateway->init(); $gateway->setopt('URL', "http://gdata.youtube.com/feeds/api/videos/{$video_id}"); $gateway->setopt('TIMEOUT', 10); $data = $gateway->exec(); $info = $gateway->getInfoLast(); if ($data == "Invalid id" || empty($data) || $info['http_code'] != 200) { return null; } return DOMDocument::loadXML($data); }
public function validate($source = null, $remote = true) { if (!function_exists('handleXMLError')) { function handleXMLError($errno, $errstr, $errfile, $errline, $context) { $context['self']->_errors[] = $errstr; } } set_time_limit(900); set_error_handler('handleXMLError'); $self = $this; // F*****g PHP... $options = $this->options(); $passed = true; if ($remote) { if (!is_null($source)) { $options['source'] = $source; } // Support {$root} $options['source'] = str_replace('{$root}', URL, $options['source']); // Parse timeout, default is 60 $timeout = isset($options['timeout']) ? (int) $options['timeout'] : 60; // Fetch document: $gateway = new Gateway(); $gateway->init(); $gateway->setopt('URL', $options['source']); $gateway->setopt('TIMEOUT', $timeout); $data = $gateway->exec(); $info = $gateway->getInfoLast(); if (empty($data) || $info['http_code'] >= 400) { $this->_errors[] = __('No data to import. URL returned HTTP code %d', array($info['http_code'])); $passed = false; } } else { if (!is_null($source)) { $data = $source; } else { $this->_errors[] = __('No data to import.'); $passed = false; } } if (!is_array($options['fields'])) { $this->_errors[] = __('No field mappings have been set for this XML Importer.'); $passed = false; } if (!$passed) { return self::__ERROR_PREPARING__; } // Load document: $xml = new DOMDocument(); $xml->loadXML($data); restore_error_handler(); $xpath = new DOMXPath($xml); $passed = true; // Register namespaces: if (is_array($options['namespaces'])) { foreach ($options['namespaces'] as $namespace) { $xpath->registerNamespace($namespace['name'], $namespace['uri']); } } // Invalid Markup: if (empty($xml)) { $passed = false; } else { if (($entries = $xpath->query($options['included-elements'])) === false) { $this->_errors[] = __('Root expression <code>%s</code> is invalid.', array(General::sanitize($options['included-elements']))); $passed = false; } else { if (is_null($entries) or $entries->length == 0) { $this->_errors[] = __('No entries to import.'); $passed = false; } else { foreach ($options['fields'] as $mapping) { if ($xpath->evaluate(stripslashes($mapping['xpath'])) !== false) { continue; } $field = FieldManager::fetch($mapping['field']); $this->_errors[] = __('\'%s\' expression <code>%s</code> is invalid.', array($field->get('label'), General::sanitize($mapping['xpath']))); $passed = false; } } } } if (!$passed) { return self::__ERROR_PREPARING__; } // Gather data: foreach ($entries as $index => $entry) { $this->_entries[$index] = array('element' => $entry, 'values' => array(), 'errors' => array(), 'entry' => null); foreach ($options['fields'] as $mapping) { $values = $this->getExpressionValue($xml, $entry, $xpath, $mapping['xpath'], $debug); if (isset($mapping['php']) && $mapping['php'] != '') { $php = stripslashes($mapping['php']); // static helper if (preg_match('/::/', $php)) { foreach ($values as $id => $value) { $values[$id] = call_user_func_array($php, array($value)); } } else { foreach ($values as $id => $value) { $function = preg_replace('/\\$value/', "'" . $value . "'", $php); if (!preg_match('/^return/', $function)) { $function = 'return ' . $function; } if (!preg_match('/;$/', $function)) { $function .= ';'; } $values[$id] = @eval($function); } } } $this->_entries[$index]['values'][$mapping['field']] = $values; } } // Validate: $passed = true; foreach ($this->_entries as &$current) { $entry = EntryManager::create(); $entry->set('section_id', $options['section']); $entry->set('author_id', is_null(Symphony::Engine()->Author()) ? '1' : Symphony::Engine()->Author()->get('id')); $values = array(); // Map values: foreach ($current['values'] as $field_id => $value) { $field = FieldManager::fetch($field_id); if (is_array($value)) { if (count($value) === 1) { $value = current($value); } if (count($value) === 0) { $value = ''; } } // Adjust value? if (method_exists($field, 'prepareImportValue') && method_exists($field, 'getImportModes')) { $modes = $field->getImportModes(); if (is_array($modes) && !empty($modes)) { $mode = current($modes); } $value = $field->prepareImportValue($value, $mode, $entry->get('id')); } else { $type = $field->get('type'); if ($type == 'author') { if ($field->get('allow_multiple_selection') == 'no') { if (is_array($value)) { $value = array(implode('', $value)); } } } else { if ($type == 'datetime') { $value = $value[0]; } else { if (is_array($value)) { $value = implode('', $value); } } } } $values[$field->get('element_name')] = $value; } // Validate: if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($values, $current['errors'])) { $passed = false; } else { if (__ENTRY_OK__ != $entry->setDataFromPost($values, $current['errors'], true, true)) { $passed = false; } } $current['entry'] = $entry; $current['values'] = $values; } if (!$passed) { return self::__ERROR_VALIDATING__; } return self::__OK__; }