128, 'disable_bbcode' => 64, 'disable_smileys' => 32, ); /** * Checks if specific option is set for post * * @param string $option_name * @param Array $options * @return bool */ function GetPostOption($option_name, $options) { if (!isset($this->postOptionBits[$option_name])) { return false; } $option_bit = $this->postOptionBits[$option_name]; return ($options & $option_bit) == $option_bit; } /** * Sets given option bit (by name) to post options * * @param string $option_name * @param int $option_value * @param Array $options * @return bool */ function SetPostOption($option_name, $option_value, &$options) { if (!isset($this->postOptionBits[$option_name])) { return false; } $option_bit = $this->postOptionBits[$option_name]; if ($option_value) { $options |= $option_bit; } else { $options = $options &~ $option_bit; } return true; } /** * Returns post options map to virtual field names * * @return Array */ function getOptionsMap() { $options_map = Array ( 'show_sig' => 'ShowSignatures', 'disable_smileys' => 'DisableSmileys', 'disable_bbcode' => 'DisableBBCodes', ); return $options_map; } /** * @return void * @param int $date * @desc Set any field to category & all it's parent categories */ function PropagateCategoryField($category_id, $field_name, $field_value) { $id_field = $this->Application->getUnitOption('c', 'IDField'); $table_name = $this->Application->getUnitOption('c', 'TableName'); $sql = 'SELECT ParentPath FROM ' . $table_name . ' WHERE ' . $id_field . ' = ' . $category_id; $parent_path = $this->Conn->GetOne($sql); $parent_categories = explode('|', substr($parent_path, 1, -1)); if ( !$parent_categories ) { return; } $fields_hash = Array ($field_name => $field_value); $this->Conn->doUpdate($fields_hash, $table_name, $id_field . ' IN (' . implode(',', $parent_categories) . ')'); } /** * Sets today posts count & today date for topic * * @param kCatDBItem $object * @param int $post_date * @param int $increment_by * @return bool */ function updateTodayPostsCount(&$object, $post_date, $increment_by = 1) { $date_now = adodb_date('Y-m-d'); if (adodb_date('Y-m-d', $post_date) != $date_now) { return true; } // last post update date was today or not $today_posts = ($date_now == $object->GetDBField('TodayDate')) ? $object->GetDBField('TodayPosts') : 0; $object->SetDBField('TodayDate', $date_now); $object->SetDBField('TodayPosts', $today_posts + $increment_by); return $object->Update(); } function updatePostCount($topic_id, $increment = 1) { $id_field = $this->Application->getUnitOption('bb', 'IDField'); $table_name = $this->Application->getUnitOption('bb', 'TableName'); // helps in case, when 2 (or more) users tries to post in same topic at same time $sql = 'UPDATE '.$table_name.' SET Posts = Posts '.($increment > 0 ? '+' : '-').' '.abs($increment).' WHERE '.$id_field.' = '.$topic_id; $this->Conn->Query($sql); // returns new value $sql = 'SELECT Posts FROM '.$table_name.' WHERE '.$id_field.' = '.$topic_id; return $this->Conn->GetOne($sql); } /** * Replaces all special formatting in post before displaing it to user * * @param string $post_body * @param int $post_options bit array of post options * @param Array $sub_blocks block names for rendering smileys & bbcodes * @return string */ function parsePostBody($post_body, $post_options, $sub_blocks) { // 1. escape all html sequences $post_body = htmlspecialchars($post_body, ENT_NOQUOTES); // don't touch quotes in bbcode attribute values // 2. replace censored words $post_body = $this->CensorText($post_body); // 3. replace bb codes if (!$this->GetPostOption('disable_bbcode', $post_options)) { $post_body = $this->replaceBBCodes($post_body, $sub_blocks['bbcode']); } // 4. replace smileys if (!$this->GetPostOption('disable_smileys', $post_options)) { $post_body = $this->replaceSmileys($post_body, $sub_blocks['smileys']); } // 5. add enters (because we don't use HTML in post body) $post_body = nl2br($post_body); // 6. replace quoted text return $this->replacePostQuote($post_body, $sub_blocks['quote']); } function replacePostQuote($text, $render_as) { if (preg_match('/\[quote id=([\d]+)\](.*)\[\/quote\]/s', $text, $regs)) { $post = $this->Application->recallObject('bb-post.-item', null, Array ('skip_autoload' => true)); /* @var $post kDBItem */ $post->Load($regs[1]); $block_params = Array ('name' => $render_as, 'PrefixSpecial' => 'bb-post.-item', 'Prefix' => 'bb-post', 'Special' => '-item', 'strip_nl' => 2); $parsed_quote = $this->Application->ParseBlock($block_params); return str_replace($regs[0], $parsed_quote, $text); } return $text; } /** * Replaces bad words with good words (censorship process) * * @param string $text * @return string */ function CensorText($text) { static $censor_words = null; if (!isset($censor_words)) { $sql = 'SELECT Replacement, BadWord FROM '.TABLE_PREFIX.'Censorship'; $censor_words = $this->Conn->GetCol($sql, 'BadWord'); } foreach ($censor_words as $replace_from => $replace_to) { $text = str_replace($replace_from, $replace_to, $text); } return $text; } function replaceSmileys($text, $smiley_element) { static $smileys = null; if (!isset($smileys)) { $sql = 'SELECT em.EmotionImage, em.KeyStroke FROM '.TABLE_PREFIX.'Emoticon em WHERE em.Enabled = 1 ORDER BY CHAR_LENGTH(em.KeyStroke) DESC'; $smileys = $this->Conn->GetCol($sql, 'KeyStroke'); } $block_params = Array ('name' => $smiley_element, 'smiley_url' => '#SMILEY_URL#'); $smiley_mask = trim($this->Application->ParseBlock($block_params)); $base_url = rtrim($this->Application->BaseURL(),'/'); foreach ($smileys as $key_stoke => $image_url) { if (strpos($text, $key_stoke) === false) { continue; } $smiley_html = str_replace('#SMILEY_URL#', $base_url.SMILEYS_PATH.$image_url, $smiley_mask); $text = str_replace($key_stoke, $smiley_html, $text); } return $text; } /** * Sort params by name and then by length * * @param string $a * @param string $b * @return int * @access private */ function CmpParams($a, $b) { list ($a, ) = explode(':', $a); list ($b, ) = explode(':', $b); $a_len = strlen($a); $b_len = strlen($b); if ($a_len == $b_len) return 0; return $a_len > $b_len ? -1 : 1; } function replaceBBCodes($text, $bbcode_element) { // convert phpbb bbcodes to in-bulletin bbcodes $text = $this->preformatBBCodes($text); $tags_defs = explode(';', $this->Application->ConfigValue('BBTags')); // 'b:;i:;u:;ul:type|align;font:color|face|size;url:href;img:src|border'; usort($tags_defs, Array (&$this, 'CmpParams')); foreach($tags_defs as $tag) { list ($tag_name, $tag_params) = explode(':', $tag); $tag_params = $tag_params ? array_flip(explode('|', $tag_params)) : 0; $text = preg_replace('/\['.$tag_name.'(.*)\](.*)\[\/'.$tag_name.' *\]/Uise','$this->checkBBCodeAttribs("'.$tag_name.'",\'$1\',\'$2\',$tag_params);', $text); } // additional processing for [url], [*], [img] bbcode $text = preg_replace('/(.*)<\/url>/Usi','$1',$text); $text = preg_replace('/(.*)<\/font>/Usi','$1',$text); // skip empty fonts $text = str_replace( Array('','[*]'), Array('','
  • '), $text); // bbcode [code]xxx[/code] processing $text = preg_replace('/\[code\](.*)\[\/code\]/Uise', "\$this->replaceCodeBBCode('$1', '".$bbcode_element."')", $text); return $text; } /** * Convert phpbb url bbcode to valid in-bulletin's format * * @param string $text * @return string */ function preformatBBCodes($text) { // 1. urls $text = preg_replace('/\[url=(.*)\](.*)\[\/url\]/Ui','[url href="$1"]$2[/url]',$text); $text = preg_replace('/\[url\](.*)\[\/url\]/Ui','[url href="$1"]$1[/url]',$text); // 2. images $text = preg_replace('/\[img\](.*)\[\/img\]/Ui','[img src="$1" border="0"][/img]',$text); // 3. color $text = preg_replace('/\[color=(.*)\](.*)\[\/color\]/Ui','[font color="$1"]$2[/font]',$text); // 4. size $text = preg_replace('/\[size=(.*)\](.*)\[\/size\]/Ui','[font size="$1"]$2[/font]',$text); // 5. lists $text = preg_replace('/\[list(.*)\](.*)\[\/list\]/Uis','[ul]$2[/ul]',$text); // 6. email to link $text = preg_replace('/\[email\](.*)\[\/email\]/Ui','[url href="mailto:$1"]$1[/url]',$text); //7. b tag $text = preg_replace('/\[(b|i|u):(.*)\](.*)\[\/(b|i|u):(.*)\]/Ui','[$1]$3[/$4]',$text); //8. code tag $text = preg_replace('/\[code:(.*)\](.*)\[\/code:(.*)\]/Uis','[code]$2[/code]',$text); return $text; } /** * Removes not allowed params from tag and returns result * * @param string $BBCode bbcode to check * @param string $TagParams params string entered by user * @param string $TextInside text between opening and closing bbcode tag * @param string $ParamsAllowed list of allowed parameter names ("|" separated) * @return string */ function checkBBCodeAttribs($BBCode, $TagParams, $TextInside, $ParamsAllowed) { // unescape escaped quotes in tag $TagParams = str_replace('\"', '"', $TagParams); $TextInside = str_replace('\"', '"', $TextInside); $params_extracted = preg_match_all('/ +([^=]*)=["\']?([^ "\']*)["\']?/is', $TagParams, $extracted_params, PREG_SET_ORDER); if ($ParamsAllowed && $params_extracted) { $ret = Array(); foreach ($extracted_params as $param) { $param_name = strtolower(trim( $param[1] )); $param_value = trim($param[2]); // 1. prevent hacking if ($BBCode == 'url' && $param_name == 'href') { if (strpos(strtolower($param_value), 'script:') !== false) { // script tag found in "href" parameter of "url" bbcode (equals to hacking) -> remove bbcode return $TextInside; } } // 2. leave only allowed params & remove all not allowed if (isset($ParamsAllowed[$param_name])) { $ret[] = $param_name.'="'.$param_value.'"'; } } $ret = count($ret) ? ' '.implode(' ', $ret) : ''; return '<'.$BBCode.$ret.'>'.$TextInside.''; } return '<'.$BBCode.'>'.$TextInside.''; } function highlightCode($code, $strip_tabs = 0) { if ($strip_tabs) { $code = preg_replace('/(\t){'.$strip_tabs.'}(.*)/', '\\2', $code); } $code = str_replace( Array('\\', '/') , Array('_no_match_string_', '_n_m_s_'), $code); $code = highlight_string('', true); $code = str_replace( Array('_no_match_string_', '_n_m_s_'), Array('\\', '/'), $code); $code = preg_replace('/<\?(.*)php(.*)\?>/Us', '\\2', $code); $code = preg_replace('/([\r\n]+)/si', '', $code); $code = preg_replace('/([\r\n]+)<\/font>([\r\n]+)<\/code>/si', '', $code); return $code; } /** * Replaces [code]php code[/code] bbcode in post * * @param string $input_string code line to highlight * @param string $bbcode_element block name used for bbcode descoration * @return string */ function replaceCodeBBCode($input_string, $bbcode_element) { static $bbcode_mask = null; if (!isset($bbcode_mask)) { $block_params = Array ('name' => $bbcode_element, 'bb_code' => '#BB_CODE#'); $bbcode_mask = trim($this->Application->ParseBlock($block_params)); } $input_string = trim( str_replace('\"','"', htmlspecialchars_decode($input_string)) ); $input_string = $this->highlightCode($input_string); $input_string = preg_replace("/\r
    /s", "\r", $input_string); // undo nl2br added in highlighting $input_string = str_replace('#BB_CODE#', $input_string, $bbcode_mask); return $input_string; } /** * Returns subscription manager by name * * @param string $name * @param array $arguments * @return kSubscriptionManager * @throws InvalidArgumentException */ public function getSubscriptionManager($name, $arguments = Array ()) { if ( $name != 'CategoryTopics' && $name != 'TopicPosts' ) { throw new InvalidArgumentException('Unknown subscription manager "' . $name . '"'); } $manager = $this->Application->makeClass('kSubscriptionManager'); /* @var $manager kSubscriptionManager */ $fields_hash = Array (); $user_id = isset($arguments[1]) ? $arguments[1] : $this->Application->RecallVar('user_id'); switch ( $name ) { case 'CategoryTopics': $category_id = isset($arguments[0]) ? $arguments[0] : $this->Application->GetVar('m_cat_id'); $fields_hash = Array ( 'EmailEventId' => $manager->getEmailEventId('TOPIC.ADD.SUB'), 'UserId' => $user_id, 'CategoryId' => $category_id, ); break; case 'TopicPosts': $fields_hash = Array ( 'EmailEventId' => $manager->getEmailEventId('POST.ADD.SUB'), 'UserId' => $user_id, 'ParentItemId' => $arguments[0], ); break; } $manager->add($fields_hash); return $manager; } }