/** * Converts WYSIWYG editor HTML back to BB code * * @param string $messageTextHtml HTML to convert * @param XenForo_Input $input * @param integer $htmlCharacterLimit Max length of HTML before processing; defaults to 4 * message length option * * @return string BB code input */ public function convertEditorHtmlToBbCode($messageTextHtml, XenForo_Input $input, $htmlCharacterLimit = -1) { if ($htmlCharacterLimit < 0) { $htmlCharacterLimit = 4 * XenForo_Application::get('options')->messageMaxLength; // quadruple the limit as HTML can be a lot more verbose } if ($htmlCharacterLimit && utf8_strlen($messageTextHtml) > $htmlCharacterLimit) { throw new XenForo_Exception(new XenForo_Phrase('submitted_message_is_too_long_to_be_processed'), true); } $options = array(); $requestPaths = XenForo_Application::get('requestPaths'); $options['baseUrl'] = $requestPaths['fullBasePath']; $relativeResolver = $input->filterSingle('_xfRelativeResolver', XenForo_Input::STRING); if ($relativeResolver && isset($_SERVER['HTTP_USER_AGENT'])) { if (preg_match('#Firefox/([0-9]+)\\.([0-9]+)\\.([0-9]+)#i', $_SERVER['HTTP_USER_AGENT'], $match)) { // FF versions sometime before 3.6.12 have an issue with respecting the base tag of the editor, // 3.6.8 is a known version that has problems $useResolver = $match[1] <= 3 && $match[2] <= 6 && $match[3] <= 8; } else { $useResolver = false; } if ($useResolver) { // take off query string and then up to the last directory $relativeResolver = preg_replace('/\\?.*$/', '', $relativeResolver); $relativeResolver = preg_replace('#/[^/]+$#', '', $relativeResolver); $options['baseUrl'] = $relativeResolver; } } $rendered = XenForo_Html_Renderer_BbCode::renderFromHtml($messageTextHtml, $options); return trim(XenForo_Input::cleanString($rendered)); }
/** * Attempts to read HTML that has been selected from XenForo messages, * and turn it back into its source BB code. * * @param $html * * @return string */ public function getBbCodeFromSelectionHtml($html) { // attempt to parse the selected HTML into BB code $html = trim(strip_tags($html, '<b><i><u><a><img><span><ul><ol><li><pre><code><br>')); // handle PHP/CODE/HTML output and turn it back into BB code $html = preg_replace_callback('/<(pre|code) data-type="(\\w+)">(.*)<\\/\\1>/siU', array($this, '_bbCodeTagsHtmlToBbCode'), $html); $html = XenForo_Html_Renderer_BbCode::renderFromHtml($html); return trim(XenForo_Input::cleanString($html)); }
/** * Fetches a remote image, stores it in the file system and records it in the database * * @param string $url * @param array|null $image * * @return array */ protected function _fetchAndCacheImage($url, array $image = null) { $urlHash = md5($url); $time = XenForo_Application::$time; if (!$image || empty($image['image_id'])) { $image = array('url' => $url, 'url_hash' => $urlHash, 'fetch_date' => $time, 'file_size' => 0, 'file_name' => '', 'mime_type' => '', 'views' => 0, 'first_request_date' => $time, 'last_request_date' => $time, 'pruned' => 1, 'failed_date' => 0, 'fail_count' => 0); } $image['is_processing'] = time(); // intentionally time() as we might have slept $db = $this->_getDb(); if (empty($image['image_id'])) { try { $db->insert('xf_image_proxy', $image); $image['image_id'] = $db->lastInsertId(); } catch (Exception $e) { $image['image_id'] = 0; $image['is_processing'] = 0; $image['failed_date'] = time(); $image['fail_count'] = 1; return $image; } } else { $db->query("\n\t\t\t\tUPDATE xf_image_proxy\n\t\t\t\tSET is_processing = ?\n\t\t\t\tWHERE image_id = ?\n\t\t\t", array($image['is_processing'], $image['image_id'])); } $results = $this->_fetchImageForProxy($url); $requestFailed = $results['failed']; $streamFile = $results['tempFile']; $fileName = $results['fileName']; $mimeType = $results['mimeType']; $fileSize = $results['fileSize']; if (!$requestFailed) { $filePath = $this->getImagePath($image); $dirName = dirname($filePath); @unlink($filePath); if (XenForo_Helper_File::createDirectory($dirName, true) && XenForo_Helper_File::safeRename($streamFile, $filePath)) { // ensure the filename fits -- if it's too long, take off from the beginning to keep extension if (!preg_match('/./u', $fileName)) { $fileName = preg_replace('/[\\x80-\\xFF]/', '?', $fileName); } $fileName = XenForo_Input::cleanString($fileName); $length = utf8_strlen($fileName); if ($length > 250) { $fileName = utf8_substr($fileName, $length - 250); } $data = array('fetch_date' => time(), 'file_size' => $fileSize, 'file_name' => $fileName, 'mime_type' => $mimeType, 'pruned' => 0, 'is_processing' => 0, 'failed_date' => 0, 'fail_count' => 0); $image = array_merge($image, $data); $db->update('xf_image_proxy', $data, 'image_id = ' . $db->quote($image['image_id'])); } } @unlink($streamFile); if ($requestFailed) { $data = array('is_processing' => 0, 'failed_date' => time(), 'fail_count' => $image['fail_count'] + 1); $image = array_merge($image, $data); $db->update('xf_image_proxy', $data, 'image_id = ' . $db->quote($image['image_id'])); } return $image; }
protected function _postRender($text) { $text = preg_replace('#\\[img\\]\\[url\\]([^\\[]+)\\[/url\\]\\[/img\\]#i', '[IMG]$1[/IMG]', $text); do { $newText = preg_replace('#\\[/(b|i|u|s|left|center|right|indent)\\]([\\r\\n]*)\\[\\1\\]#i', '\\2', $text); if ($newText === null || $newText == $text) { break; } $text = $newText; } while (true); do { $newText = preg_replace('#(\\[(font|color|size|url|email)=[^\\]]*\\])((?:(?>[^\\[]+?)|\\[(?!\\2))*)\\[/\\2\\]([\\r\\n]*)\\1#siU', '\\1\\3\\4', $text); if ($newText === null || $newText == $text) { break; } $text = $newText; } while (true); $text = XenForo_Input::cleanString($text); return trim($text); }
/** * Decodes HTML entities in a string. Note that non-breaking spaces are treated as normal spaces. * * @param string $string * * @return string Decoded string */ public function decodeEntities($string) { return XenForo_Input::cleanString(html_entity_decode($string, ENT_COMPAT, 'utf-8')); }
protected function _getUrlTitle($url) { $requestUrl = $url; $requestUrl = preg_replace('/#.*$/', '', $requestUrl); if (preg_match_all('/[^A-Za-z0-9._~:\\/?#\\[\\]@!$&\'()*+,;=%-]/', $requestUrl, $matches)) { foreach ($matches[0] as $match) { $requestUrl = str_replace($match[0], '%' . strtoupper(dechex(ord($match[0]))), $requestUrl); } } $requestUrl = preg_replace('/%(?![a-fA-F0-9]{2})/', '%25', $requestUrl); // ensure the URL is valid and isn't trying to load something locally $parts = @parse_url($requestUrl); if (!$parts || empty($parts['scheme']) || !preg_match('/^https?$/i', $parts['scheme']) || empty($parts['host']) || preg_match('#^(127\\.|192\\.168\\.|10\\.|172\\.(1[6789]|2|3[01])|169\\.254\\.|0\\.0\\.0\\.0)#', $parts['host']) || preg_match('#^localhost(\\.localdomain)?$#i', $parts['host'])) { return false; } $urlHash = md5($url); XenForo_HttpStream::register(); XenForo_HttpStream::setMaxSize(50 * 1024); // 50KB $streamUri = 'xf-http://' . $urlHash . '-' . uniqid(); $this->_streamFile = XenForo_HttpStream::getTempFile($streamUri); try { $response = XenForo_Helper_Http::getClient($requestUrl, array('output_stream' => $streamUri, 'timeout' => 3, 'httpversion' => Zend_Http_Client::HTTP_0))->setHeaders('Accept-encoding', 'identity')->setHeaders('Accept', 'text/html,*/*;q=0.8')->request('GET'); if (!$response->isSuccessful()) { return false; } $headers = $response->getHeaders(); if (!$headers) { return false; } $charset = false; if (isset($headers['Content-type'])) { $parts = explode(';', is_array($headers['Content-type']) ? end($headers['Content-type']) : $headers['Content-type'], 2); $type = trim($parts[0]); if ($type != 'text/html') { return false; } if (isset($parts[1]) && preg_match('/charset=([-a-z0-9_]+)/i', trim($parts[1]), $match)) { $charset = $match[1]; } } try { $body = $response->getBody(); } catch (Exception $e) { // some servers may ignore our request for no gzip and this can fail $body = ''; } $title = ''; if (preg_match('#<meta[^>]+property="(og:|twitter:)title"[^>]*content="([^">]+)"#siU', $body, $match)) { $title = isset($match[2]) ? $match[2] : ''; } if (!$title && preg_match('#<title[^>]*>(.*)</title>#siU', $body, $match)) { $title = $match[1]; } if (!$title) { return false; } if (!$charset) { preg_match('/charset=([^;"\\s]+|"[^;"]+")/i', $body, $contentTypeMatch); if (isset($contentTypeMatch[1])) { $charset = trim($contentTypeMatch[1], " \t\n\r\v\""); } if (!$charset) { $charset = 'windows-1252'; } } $title = XenForo_Input::cleanString($this->_toUtf8($title, $charset, true)); if (defined('ENT_HTML5')) { $title = html_entity_decode($title, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } else { $title = html_entity_decode($title, ENT_QUOTES, 'UTF-8'); } $title = utf8_unhtml($title); $title = str_replace("\n", ' ', trim($title)); if (!strlen($title)) { return false; } $formatter = $this->_getBbCodeFilterer(); $parser = $this->_getBbCodeParser(); $parser->render($title); if ($formatter->getSmilieTally() || $formatter->getTotalTagTally()) { $title = "[PLAIN]{$title}[/PLAIN]"; } return $title; } catch (Zend_Http_Client_Exception $e) { } catch (Zend_Uri_Exception $e) { } catch (Exception $e) { XenForo_Error::logException($e, false, "Error linking URL '{$url}': "); } return false; }