Example #1
0
 /**
  * Callback to prevent media tags from being auto linkified
  *
  * @access	protected
  * @param	array		Matches from the regular expression
  * @return	string		Converted text
  */
 protected function _denyMediaLinkify_CallBack($matches)
 {
     $_extra = '';
     /* Basic checking */
     if (stristr($matches[1], 'href')) {
         return $matches[0];
     }
     if (strlen($matches[2]) < 12) {
         return $matches[0];
     }
     if (isset($matches[4]) and stristr($matches[4], '</a>')) {
         return $matches[0];
     }
     /* Check for XSS */
     if (!IPSText::xssCheckUrl($matches[2])) {
         return $matches[0];
     }
     if (substr($matches[2], -1) == ',') {
         $matches[2] = rtrim($matches[2], ',');
         $_extra = ',';
     }
     /* Check for ! which is &#xx; at this point */
     if (preg_match('/&#\\d+?;$/', $matches[2], $_m)) {
         $matches[2] = str_replace($_m[0], '', $matches[2]);
         $_extra = $_m[0];
     }
     /* Is this a media URL? */
     if ($this->settings['bbcode_automatic_media']) {
         $media = $this->cache->getCache('mediatag');
         if (is_array($media) and count($media)) {
             foreach ($media as $type => $r) {
                 if (preg_match("#^" . $r['match'] . "\$#is", $matches[2])) {
                     $matches[2] = preg_replace('#(https|http)://#', '\\1--,,--//', $matches[2]);
                 }
             }
         }
     }
     return $matches[1] . $matches[2] . $_extra;
 }
 /**
  * Perform first pass through login handler routine
  *
  * @access	private
  * @return	mixed		Boolean on failure else output/redirect
  */
 private function _doFirstPass()
 {
     //-----------------------------------------
     // Do the same cleaning we do when storing url
     //-----------------------------------------
     $url = trim($this->request['openid_url']);
     $url = rtrim($url, "/");
     if (!strpos($url, 'http://') === 0 and !strpos($url, 'https://') === 0) {
         $url = 'http://' . $url;
     }
     if (!IPSText::xssCheckUrl($url)) {
         $this->auth_errors[] = 'bad_url';
         $this->return_code = 'WRONG_AUTH';
         return false;
     }
     $consumer = $this->_getConsumer();
     if (!is_object($consumer)) {
         return false;
     }
     //-----------------------------------------
     // Store some of the input data..
     //-----------------------------------------
     $id = md5(uniqid(mt_rand(), true));
     $this->DB->delete('openid_temp', "fullurl='" . $url . "'");
     $this->DB->insert('openid_temp', array('id' => $id, 'referrer' => $this->request['referer'], 'cookiedate' => intval($this->request['rememberMe']), 'privacy' => intval($this->request['anonymous']), 'fullurl' => $url));
     //-----------------------------------------
     // Set the URLs
     //-----------------------------------------
     $openid = $url;
     if ($this->is_admin_auth) {
         $process_url = $this->settings['base_url'] . 'app=core&module=login&do=login-complete&firstpass=1&myopenid=' . $id;
     } else {
         $process_url = $this->settings['base_url'] . 'app=core&module=global&section=login&do=process&firstpass=1&myopenid=' . $id;
     }
     $trust_root = strpos($this->settings['base_url'], '.php') !== false ? substr($this->settings['base_url'], 0, strpos($this->settings['base_url'], '.php') + 4) : $this->settings['base_url'];
     $policy_url = $this->openid_config['openid_policy'];
     //-----------------------------------------
     // Begin OpenID Auth
     //-----------------------------------------
     $auth_request = $consumer->begin($openid);
     if (!$auth_request) {
         $this->return_code = 'WRONG_OPENID';
         $this->auth_errors[] = 'bad_request';
         return false;
     }
     //-----------------------------------------
     // Set required, optional, policy attribs
     //-----------------------------------------
     $sreg_request = Auth_OpenID_SRegRequest::build(explode(',', $this->openid_config['args_req']), explode(',', $this->openid_config['args_opt']), $policy_url);
     if ($sreg_request) {
         $auth_request->addExtension($sreg_request);
     }
     //-----------------------------------------
     // Redirect user
     //-----------------------------------------
     $redirect_url = $auth_request->redirectURL($trust_root, $process_url);
     if ($this->request['module'] == 'ajax') {
         require_once IPS_KERNEL_PATH . 'classAjax.php';
         $ajax = new classAjax();
         $ajax->returnJsonArray(array('url' => $redirect_url));
     }
     // If the redirect URL can't be built, try HTML inline
     if (!Auth_OpenID::isFailure($redirect_url)) {
         header("Location: " . $redirect_url);
         exit;
     } else {
         $form_id = 'openid_message';
         $form_html = $auth_request->formMarkup($trust_root, $process_url, false, array('id' => $form_id));
         // Display an error if the form markup couldn't be generated;
         if (Auth_OpenID::isFailure($form_html)) {
             $this->return_code = 'WRONG_AUTH';
             $this->auth_errors[] = 'bad_request';
             return false;
         } else {
             $page_contents = array("<html><head><title>", "OpenID transaction in progress", "</title></head>", "<body onload='document.getElementById(\"" . $form_id . "\").submit()'>", $form_html, "</body></html>");
             print implode("\n", $page_contents);
             exit;
         }
     }
 }
Example #3
0
 /**
  * Callback to auto-parse urls
  *
  * @access	protected
  * @param	array		Matches from the regular expression
  * @return	string		Converted text
  */
 protected function _autoParseUrls($matches)
 {
     $_extra = '';
     /* Basic checking */
     if (stristr($matches[1], 'href')) {
         return $matches[0];
     }
     if (strlen($matches[2]) < 12) {
         return $matches[0];
     }
     if (isset($matches[4]) and stristr($matches[4], '</a>')) {
         return $matches[0];
     }
     /* Check for XSS */
     if (!IPSText::xssCheckUrl($matches[2])) {
         return $matches[0];
     }
     if (substr($matches[2], -1) == ',') {
         $matches[2] = rtrim($matches[2], ',');
         $_extra = ',';
     }
     if (substr($matches[2], -15) == '~~~~~_____~~~~~') {
         $matches[2] = substr($matches[2], 0, -15);
         $_extra = '~~~~~_____~~~~~';
     }
     /* Check for ! which is &#xx; at this point */
     if (preg_match('/&#\\d+?;$/', $matches[2], $_m)) {
         $matches[2] = str_replace($_m[0], '', $matches[2]);
         $_extra = $_m[0];
     }
     /* Is this a media URL? */
     if ($this->settings['bbcode_automatic_media'] and isset($this->_bbcodes['display']['media']) and ($this->_bbcodes['display']['media']['bbcode_sections'] == 'all' or in_array($this->parsing_section, explode(',', $this->_bbcodes['display']['media']['bbcode_sections'])))) {
         $media = $this->cache->getCache('mediatag');
         /* Already converted? */
         if (in_array($matches[2], $this->_mediaUrlConverted)) {
             return $matches[0];
         }
         if (is_array($media) and count($media)) {
             foreach ($media as $type => $r) {
                 if (preg_match("#^" . $r['match'] . "\$#is", $matches[2])) {
                     $this->cache->updateCacheWithoutSaving('_tmp_autoparse_media', 1);
                     $_result = $this->parseBbcode($matches[1] . '[media]' . $matches[2] . '[/media]' . $_extra, 'display', 'media');
                     $this->cache->updateCacheWithoutSaving('_tmp_autoparse_media', 0);
                     return $_result;
                 }
             }
         }
     }
     /* It's not media - so we'll use [url] - check we're allowed first */
     if (!isset($this->_bbcodes['display']['url']) or $this->_bbcodes['display']['url']['bbcode_sections'] != 'all' and !in_array($this->parsing_section, explode(',', $this->_bbcodes['display']['url']['bbcode_sections']))) {
         // We're not allowed to use [url] here
         return $matches[0];
     }
     /* Ensure bbcode is stripped for the actual URL */
     /* @link http://community.invisionpower.com/tracker/issue-22580-bbcode-breaks-link-add-bold-formatting-to-part-of-link/ */
     if (preg_match('#\\[\\w#', $matches[2])) {
         $wFormatting = $matches[2];
         $matches[2] = $this->stripAllTags($matches[2]);
         return $this->parseBbcode($matches[1] . '[url="' . $matches[2] . '"]' . $wFormatting . '[/url]' . $_extra, 'display', 'url');
     } else {
         /* Is option enforced? */
         if (empty($this->_bbcodes['display']['url']['bbcode_optional_option'])) {
             return $this->parseBbcode($matches[1] . '[url="' . $matches[2] . '"]' . $matches[2] . '[/url]' . $_extra, 'display', 'url');
         } else {
             return $this->parseBbcode($matches[1] . '[url]' . $matches[2] . '[/url]' . $_extra, 'display', 'url');
         }
     }
 }
 /**
  * Saves the member's avatar
  *
  * @param		INT			Member's ID to save
  * @param		string		Upload field name [Default is "upload_avatar"]
  * @param		string		Avatar URL Field [Default is "avatar_url"]
  * @param		string		Gallery Avatar Directory Field [Default is "avatar_gallery"]
  * @param		string		Gallery Avatar Image Field [Default is "avatar_image"]
  * @author		Brandon Farber, Stolen By Matt 'Haxor' Mecham
  * <code>
  * Excepton Codes:
  * NO_MEMBER_ID:				A valid member ID was not passed.
  * NO_PERMISSION:				You do not have permission to change the avatar
  * UPLOAD_NO_IMAGE:				Nothing to upload
  * UPLOAD_INVALID_FILE_EXT:		Incorrect file extension (not an image)
  * UPLOAD_TOO_LARGE:			Upload is larger than allowed
  * UPLOAD_CANT_BE_MOVED:		Upload cannot be moved into the uploads directory
  * UPLOAD_NOT_IMAGE:			Upload is not an image, despite what the file extension says!
  * NO_AVATAR_TO_SAVE:			Nothing to save!
  * </code>
  */
 public function saveNewAvatar($member_id, $uploadFieldName = 'upload_avatar', $urlFieldName = 'avatar_url', $galleryFieldName = 'avatar_gallery', $avatarGalleryImage = 'avatar_image', $gravatarFieldName = 'gravatar_email')
 {
     //-----------------------------------------
     // INIT
     //-----------------------------------------
     $avatar = array();
     list($p_width, $p_height) = explode("x", strtolower($this->settings['avatar_dims']));
     if (!$member_id) {
         throw new Exception("NO_MEMBER_ID");
     }
     $member = IPSMember::load($member_id, 'extendedProfile,groups');
     if (!$member['member_id']) {
         throw new Exception("NO_MEMBER_ID");
     }
     //-----------------------------------------
     // Allowed to upload pics for administrators?
     //-----------------------------------------
     if (IPS_AREA != 'public') {
         if ($member['g_access_cp'] and !$this->registry->getClass('class_permissions')->checkPermission('member_photo_admin', 'members', 'members')) {
             throw new Exception("NO_PERMISSION");
         }
     }
     //-----------------------------------------
     // Upload?
     //-----------------------------------------
     if ($_FILES[$uploadFieldName]['name'] != "" and $_FILES[$uploadFieldName]['name'] != "none") {
         $this->settings['upload_dir'] = str_replace('&#46;', '.', $this->settings['upload_dir']);
         $real_name = 'av-' . $member_id;
         require_once IPS_KERNEL_PATH . 'classUpload.php';
         $upload = new classUpload();
         $upload->out_file_name = $real_name;
         $upload->out_file_dir = $this->settings['upload_dir'];
         $upload->max_file_size = $this->settings['avup_size_max'] * 1024 * 8;
         // Allow xtra for compression
         $upload->upload_form_field = $uploadFieldName;
         //-----------------------------------------
         // Populate allowed extensions
         //-----------------------------------------
         if (is_array($this->cache->getCache('attachtypes')) and count($this->cache->getCache('attachtypes'))) {
             foreach ($this->cache->getCache('attachtypes') as $data) {
                 if ($data['atype_photo']) {
                     if ($data['atype_extension'] == 'swf' and $this->settings['disable_flash']) {
                         continue;
                     }
                     $upload->allowed_file_ext[] = $data['atype_extension'];
                 }
             }
         }
         //-----------------------------------------
         // Upload...
         //-----------------------------------------
         $upload->process();
         //-----------------------------------------
         // Error?
         //-----------------------------------------
         if ($upload->error_no) {
             switch ($upload->error_no) {
                 case 1:
                     // No upload
                     throw new Exception("UPLOAD_NO_IMAGE");
                     break;
                 case 2:
                     // Invalid file ext
                     throw new Exception("UPLOAD_INVALID_FILE_EXT");
                     break;
                 case 3:
                     // Too big...
                     throw new Exception("UPLOAD_TOO_LARGE");
                     break;
                 case 4:
                     // Cannot move uploaded file
                     throw new Exception("UPLOAD_CANT_BE_MOVED");
                     break;
                 case 5:
                     // Possible XSS attack (image isn't an image)
                     throw new Exception("UPLOAD_NOT_IMAGE");
                     break;
             }
         }
         $real_name = $upload->parsed_file_name;
         $im = array();
         if (!$this->settings['disable_ipbsize'] and $upload->file_extension != '.swf') {
             $imageDimensions = getimagesize($this->settings['upload_dir'] . '/' . $real_name);
             if ($imageDimensions[0] > $p_width or $imageDimensions[1] > $p_height) {
                 require_once IPS_KERNEL_PATH . "classImage.php";
                 require_once IPS_KERNEL_PATH . "classImageGd.php";
                 $image = new classImageGd();
                 $image->init(array('image_path' => $this->settings['upload_dir'], 'image_file' => $real_name));
                 $return = $image->resizeImage($p_width, $p_height);
                 $image->writeImage($this->settings['upload_dir'] . '/' . $real_name);
                 $im['img_width'] = $return['newWidth'] ? $return['newWidth'] : $image->cur_dimensions['width'];
                 $im['img_height'] = $return['newHeight'] ? $return['newHeight'] : $image->cur_dimensions['height'];
             } else {
                 $im['img_width'] = $imageDimensions[0];
                 $im['img_height'] = $imageDimensions[1];
             }
         } else {
             $w = intval($this->request['man_width']) ? intval($this->request['man_width']) : $p_width;
             $h = intval($this->request['man_height']) ? intval($this->request['man_height']) : $p_height;
             $im['img_width'] = $w > $p_width ? $p_width : $w;
             $im['img_height'] = $h > $p_height ? $p_height : $h;
         }
         //-----------------------------------------
         // Set the "real" avatar..
         //-----------------------------------------
         $avatar['avatar_location'] = $real_name;
         $avatar['avatar_size'] = $im['img_width'] . 'x' . $im['img_height'];
         $avatar['avatar_type'] = 'upload';
     } else {
         if ($this->request[$urlFieldName] and IPSText::xssCheckUrl($this->request[$urlFieldName]) === true) {
             $ext = explode(",", $this->settings['avatar_ext']);
             $checked = 0;
             $av_ext = preg_replace("/^.*\\.(\\S+)\$/", "\\1", $this->request[$urlFieldName]);
             foreach ($ext as $v) {
                 if (strtolower($v) == strtolower($av_ext)) {
                     if ($v == 'swf' and $this->settings['disable_flash']) {
                         throw new Exception("INVALID_FILE_EXT");
                     }
                     $checked = 1;
                     break;
                 }
             }
             if ($checked != 1) {
                 throw new Exception("INVALID_FILE_EXT");
             }
             if (!$this->settings['disable_ipbsize']) {
                 if (!($img_size = @getimagesize($this->request[$urlFieldName]))) {
                     $img_size[0] = $p_width;
                     $img_size[1] = $p_height;
                 }
                 $im = IPSLib::scaleImage(array('max_width' => $p_width, 'max_height' => $p_height, 'cur_width' => $img_size[0], 'cur_height' => $img_size[1]));
             } else {
                 $w = intval($this->request['man_width']) ? intval($this->request['man_width']) : $p_width;
                 $h = intval($this->request['man_height']) ? intval($this->request['man_height']) : $p_height;
                 $im['img_width'] = $w > $p_width ? $p_width : $w;
                 $im['img_height'] = $h > $p_height ? $p_height : $h;
             }
             $avatar['avatar_location'] = trim($this->request[$urlFieldName]);
             $avatar['avatar_size'] = $im['img_width'] . 'x' . $im['img_height'];
             $avatar['avatar_type'] = 'url';
         } else {
             if (isset($this->request[$galleryFieldName]) and $this->request[$avatarGalleryImage]) {
                 $directory = '';
                 if ($this->request[$galleryFieldName]) {
                     $directory = preg_replace("/[^\\s\\w_-]/", "", urldecode($this->request[$galleryFieldName]));
                     if ($directory) {
                         $directory .= '/';
                     }
                 }
                 $filename = preg_replace("/[^\\s\\w\\._\\-\\[\\]\\(\\)]/", "", urldecode($this->request[$avatarGalleryImage]));
                 if (file_exists(DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_avatars/' . $directory . $filename)) {
                     $avatar['avatar_location'] = $directory . $filename;
                     $avatar['avatar_size'] = '';
                     $avatar['avatar_type'] = 'local';
                 }
             } else {
                 if ($this->request[$gravatarFieldName] && $this->request[$gravatarFieldName] && $this->settings['allow_gravatars']) {
                     $avatar['avatar_location'] = strtolower($this->request[$gravatarFieldName]);
                     $avatar['avatar_type'] = 'gravatar';
                 }
             }
         }
     }
     //-----------------------------------------
     // No avatar image?
     //-----------------------------------------
     if (!count($avatar)) {
         throw new Exception("NO_AVATAR_TO_SAVE");
     } else {
         if ($avatar['avatar_type'] != 'upload') {
             foreach (array('swf', 'jpg', 'jpeg', 'gif', 'png') as $ext) {
                 if (@file_exists($this->settings['upload_dir'] . "/av-" . $member_id . "." . $ext)) {
                     @unlink($this->settings['upload_dir'] . "/av-" . $member_id . "." . $ext);
                 }
             }
         }
     }
     //-----------------------------------------
     // Store and redirect
     //-----------------------------------------
     IPSMember::save($member_id, array('extendedProfile' => $avatar));
     return TRUE;
 }
Example #5
0
 /**
  * Build the actual output to show
  *
  * @access	protected
  * @param	array		$content	Image URL to link to
  * @param	string		$option		[Optional] Dimension options (width,height)
  * @return	string					Content to replace bbcode with
  */
 protected function _buildOutput($content, $option = '')
 {
     //-----------------------------------------
     // Too many media files?
     //-----------------------------------------
     $existing = $this->cache->getCache('_tmp_bbcode_media', false);
     $existing = intval($existing) + 1;
     if ($this->settings['max_media_files']) {
         if ($existing > $this->settings['max_media_files']) {
             $this->error = 'too_many_media';
             $classToLoad = IPSLib::loadLibrary('', 'bbcode_plugin_url');
             $_urlBbcode = new $classToLoad($this->registry);
             return $_urlBbcode->run('[url]' . $content . '[/url]');
         }
     }
     $this->cache->updateCacheWithoutSaving('_tmp_bbcode_media', $existing);
     //-----------------------------------------
     // XSS check
     //-----------------------------------------
     $content = preg_replace('#(https|http|ftp)&\\#(058|58);//#', '\\1://', $content);
     if (!IPSText::xssCheckUrl($content)) {
         return $content;
     }
     //-----------------------------------------
     // Loop through media tags and extract
     //-----------------------------------------
     $media = $this->cache->getCache('mediatag');
     $original = $content;
     if (is_array($media) and count($media)) {
         foreach ($media as $type => $r) {
             if (preg_match("#^" . $r['match'] . "\$#is", $content)) {
                 $content = preg_replace("#^" . $r['match'] . "\$#is", $r['replace'], $content);
                 if ($option) {
                     list($width, $height) = explode(',', str_replace(array('"', "'", '&#39;', '&quot;'), '', $option));
                     if ($width and $height) {
                         if ($width > $this->settings['max_w_flash']) {
                             $this->error = 'flash_too_big';
                             return $original;
                         }
                         if ($height > $this->settings['max_h_flash']) {
                             $this->error = 'flash_too_big';
                             return $original;
                         }
                         $content = str_replace('{width}', "width='{$width}'", $content);
                         $content = str_replace('{height}', "height='{$height}'", $content);
                     }
                 } else {
                     $content = str_replace('{width}', "", $content);
                     $content = str_replace('{height}', "", $content);
                 }
                 $content = str_replace('{base_url}', $this->settings['board_url'] . '/index.php?', $content);
                 $content = str_replace('{board_url}', $this->settings['board_url'], $content);
                 $content = str_replace('{image_url}', $this->settings['img_url'], $content);
                 preg_match('/\\{text\\.(.+?)\\}/i', $content, $matches);
                 if (is_array($matches) and count($matches)) {
                     $content = str_replace($matches[0], $this->lang->words[$matches[1]], $content);
                 }
             }
         }
     }
     return $content;
 }
 /**
  * Build the actual output to show
  *
  * @access	protected
  * @param	array		$content	Display text
  * @param	string		$option		URL to link to
  * @return	string					Content to replace bbcode with
  */
 protected function _buildOutput($content, $option)
 {
     // This is problematic if url contains a ' or "
     // $option = str_replace( array( '"', "'", '&#39;', '&quot;' ), '', $option );
     //-----------------------------------------
     // Remove " and ' from beginning + end
     //-----------------------------------------
     if (substr($option, 0, 5) == '&#39;') {
         $option = substr($option, 5);
     } else {
         if (substr($option, 0, 6) == '&quot;') {
             $option = substr($option, 6);
         } else {
             if (substr($option, 0, 1) == "'") {
                 $option = substr($option, 1);
             } else {
                 if (substr($option, 0, 1) == '"') {
                     $option = substr($option, 1);
                 }
             }
         }
     }
     if (substr($option, -5) == '&#39;') {
         $option = substr($option, 0, -5);
     } else {
         if (substr($option, -6) == '&quot;') {
             $option = substr($option, 0, -6);
         } else {
             if (substr($option, -1) == "'") {
                 $option = substr($option, 0, -1);
             } else {
                 if (substr($option, -1) == '"') {
                     $option = substr($option, 0, -1);
                 }
             }
         }
     }
     //-----------------------------------------
     // Some security checking
     //-----------------------------------------
     if (IPSText::xssCheckUrl($option) !== TRUE) {
         return $content;
     }
     /* Check for mangled or embedded URLs */
     if (stristr($option, '[attachment') or stristr($option, '[quote') or stristr($option, '[url') or stristr($option, '[/url') or stristr($content, '[url') or stristr($content, '[/url')) {
         return $content;
     }
     //-----------------------------------------
     // Fix quotes in urls
     //-----------------------------------------
     $option = str_replace(array('&#39;', "'"), '%27', $option);
     $option = str_replace(array('&quot;', '"'), '%22', $option);
     foreach ($this->cache->getCache('bbcode') as $bbcode) {
         $_tags = $this->_retrieveTags();
         foreach ($_tags as $tag) {
             if (strpos($option, '[' . $tag) !== false) {
                 return $content;
             }
         }
     }
     //-----------------------------------------
     // URL filtering?
     //-----------------------------------------
     if ($this->settings['ipb_use_url_filter']) {
         $list_type = $this->settings['ipb_url_filter_option'] == "black" ? "blacklist" : "whitelist";
         if ($this->settings['ipb_url_' . $list_type]) {
             $list_values = array();
             $list_values = explode("\n", str_replace("\r", "", $this->settings['ipb_url_' . $list_type]));
             if ($list_type == "whitelist") {
                 $list_values[] = "http://{$_SERVER['HTTP_HOST']}/*";
             }
             if (count($list_values)) {
                 $good_url = 0;
                 foreach ($list_values as $my_url) {
                     if (!trim($my_url)) {
                         continue;
                     }
                     $my_url = preg_quote($my_url, '/');
                     $my_url = str_replace('\\*', "(.*?)", $my_url);
                     if ($list_type == "blacklist") {
                         if (preg_match('/' . $my_url . '/i', $option)) {
                             $this->warning = 'domain_not_allowed';
                             return $content;
                         }
                     } else {
                         if (preg_match('/' . $my_url . '/i', $option)) {
                             $good_url = 1;
                         }
                     }
                 }
                 if (!$good_url and $list_type == "whitelist") {
                     $this->warning = 'domain_not_allowed';
                     return $content;
                 }
             }
         }
     }
     //-----------------------------------------
     // Let's remove any nested links..
     //-----------------------------------------
     $content = preg_replace('/<a href=\'(.+?)\'(.*?)>(.+?)<\\/a>/is', "\\3", $content);
     //-----------------------------------------
     // Need to "truncate" the "content" to ~35
     // EDIT: but only if it's the same as content
     //-----------------------------------------
     /* Changes here @link http://community.invisionpower.com/tracker/issue-36082-long-links-on-mobile-extend-width/ */
     if (empty($this->settings['__noTruncateUrl']) and IPSText::mbstrlen($content) > 38 and (substr($content, 0, 7) == 'http://' or substr($content, 0, 8) == 'https://')) {
         $content = htmlspecialchars(IPSText::mbsubstr(html_entity_decode(urldecode($content)), 0, 20)) . '...' . htmlspecialchars(IPSText::mbsubstr(html_entity_decode(urldecode($content)), -15));
     }
     //-----------------------------------------
     // Adding rel='nofollow'?
     //-----------------------------------------
     $rels = array();
     $rel = '';
     $_title = '';
     /* Fetch actual host for better matching */
     $data = @parse_url($option);
     if ($this->settings['posts_add_nofollow']) {
         if (!stristr($data['host'], $_SERVER['HTTP_HOST'])) {
             $rels[] = "nofollow";
         }
     }
     if ($this->settings['links_external']) {
         if (!stristr($data['host'], $_SERVER['HTTP_HOST'])) {
             /* Look a little closer */
             $rels[] = "external";
             $_title = $this->lang->words['bbc_external_link'];
         }
     }
     if (count($rels)) {
         $rel = " rel='" . implode(' ', $rels) . "'";
     }
     return "<a href='{$option}' class='bbc_url' title='{$_title}'{$rel}>{$content}</a>";
 }
 /**
  * Build the actual output to show
  *
  * @access	private
  * @param	array		$content	Display text
  * @param	string		$option		URL to link to
  * @return	string					Content to replace bbcode with
  */
 private function _buildOutput($content, $option)
 {
     // This is problematic if url contains a ' or "
     // $option = str_replace( array( '"', "'", '&#39;', '&quot;' ), '', $option );
     //-----------------------------------------
     // Remove " and ' from beginning + end
     //-----------------------------------------
     if (substr($option, 0, 5) == '&#39;') {
         $option = substr($option, 5);
     } else {
         if (substr($option, 0, 6) == '&quot;') {
             $option = substr($option, 6);
         } else {
             if (substr($option, 0, 1) == "'") {
                 $option = substr($option, 1);
             } else {
                 if (substr($option, 0, 1) == '"') {
                     $option = substr($option, 1);
                 }
             }
         }
     }
     if (substr($option, -5) == '&#39;') {
         $option = substr($option, 0, -5);
     } else {
         if (substr($option, -6) == '&quot;') {
             $option = substr($option, 0, -6);
         } else {
             if (substr($option, -1) == "'") {
                 $option = substr($option, 0, -1);
             } else {
                 if (substr($option, -1) == '"') {
                     $option = substr($option, 0, -1);
                 }
             }
         }
     }
     //-----------------------------------------
     // Some security checking
     //-----------------------------------------
     if (IPSText::xssCheckUrl($option) !== TRUE) {
         return $content;
     }
     //-----------------------------------------
     // Fix quotes in urls
     //-----------------------------------------
     $option = str_replace(array('&#39;', "'"), '%27', $option);
     $option = str_replace(array('&quot;', '"'), '%22', $option);
     foreach ($this->cache->getCache('bbcode') as $bbcode) {
         $_tags = $this->_retrieveTags();
         foreach ($_tags as $tag) {
             if (strpos($option, '[' . $tag) !== false) {
                 return $content;
             }
         }
     }
     //-----------------------------------------
     // URL filtering?
     //-----------------------------------------
     if ($this->settings['ipb_use_url_filter']) {
         $list_type = $this->settings['ipb_url_filter_option'] == "black" ? "blacklist" : "whitelist";
         if ($this->settings['ipb_url_' . $list_type]) {
             $list_values = array();
             $list_values = explode("\n", str_replace("\r", "", $this->settings['ipb_url_' . $list_type]));
             if ($list_type == "whitelist") {
                 $list_values[] = "http://{$_SERVER['HTTP_HOST']}/*";
             }
             if (count($list_values)) {
                 $good_url = 0;
                 foreach ($list_values as $my_url) {
                     if (!trim($my_url)) {
                         continue;
                     }
                     $my_url = preg_quote($my_url, '/');
                     $my_url = str_replace("\\*", "(.*?)", $my_url);
                     if ($list_type == "blacklist") {
                         if (preg_match('/' . $my_url . '/i', $option)) {
                             $this->error = 'domain_not_allowed';
                             return $content;
                         }
                     } else {
                         if (preg_match('/' . $my_url . '/i', $option)) {
                             $good_url = 1;
                         }
                     }
                 }
                 if (!$good_url and $list_type == "whitelist") {
                     $this->error = 'domain_not_allowed';
                     return $content;
                 }
             }
         }
     }
     //-----------------------------------------
     // Let's remove any nested links..
     //-----------------------------------------
     $content = preg_replace("/<a href='(.+?)'(.*?)>(.+?)<\\/a>/is", "\\3", $content);
     //-----------------------------------------
     // Need to "truncate" the "content" to ~35
     // EDIT: but only if it's the same as content
     //-----------------------------------------
     if (empty($this->settings['__noTruncateUrl']) and $content == $option and IPSText::mbstrlen($content) > 38) {
         $content = htmlspecialchars(substr(html_entity_decode($content), 0, 20)) . '...' . htmlspecialchars(substr(html_entity_decode($content), -15));
     }
     //-----------------------------------------
     // Adding rel='nofollow'?
     //-----------------------------------------
     $rels = array();
     $rel = '';
     if ($this->settings['posts_add_nofollow']) {
         $rels[] = "nofollow";
     }
     if ($this->settings['links_external']) {
         $rels[] = "external";
     }
     if (count($rels)) {
         $rel = " rel='" . implode(' ', $rels) . "'";
     }
     return "<a href='{$option}' class='bbc_url' title='{$this->lang->words['bbc_external_link']}'{$rel}>{$content}</a>";
 }