Exemple #1
0
 public function output_widget($region, $place, $themeobject, $template, $request, $qa_content)
 {
     require_once QA_INCLUDE_DIR . 'db/selects.php';
     $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, (int) qa_opt('tag_cloud_count_tags')));
     $maxcount = reset($populartags);
     // $themeobject->output(sprintf('<h2 style="margin-top: 0; padding-top: 0;">%s</h2>', qa_lang_html('main/popular_tags')));
     // $themeobject->output('<div style="font-size: 10px;">');
     $themeobject->output(sprintf('<div class="panel panel-primary" style="padding: 0;"><div class="panel-heading"><h3 class="panel-title">%s</h3></div>', qa_lang_html('main/popular_tags')));
     $themeobject->output('<div class="panel-body">');
     $maxsize = qa_opt('tag_cloud_font_size');
     $minsize = qa_opt('tag_cloud_minimal_font_size');
     $scale = qa_opt('tag_cloud_size_popular');
     $blockwordspreg = qa_get_block_words_preg();
     foreach ($populartags as $tag => $count) {
         $matches = qa_block_words_match_all($tag, $blockwordspreg);
         if (empty($matches)) {
             if ($scale) {
                 $size = number_format($maxsize * $count / $maxcount, 1);
                 if ($size < $minsize) {
                     $size = $minsize;
                 }
             } else {
                 $size = $maxsize;
             }
             $themeobject->output(sprintf('<a href="%s" style="font-size: %dpx; vertical-align: baseline;">%s</a>', qa_path_html('tag/' . $tag), $size, qa_html($tag)));
         }
     }
     // $themeobject->output('</div>');
     $themeobject->output('</div></div>');
 }
 public function test__qa_block_words_match_all()
 {
     $test1 = qa_block_words_match_all('onion belt', '');
     $wordpreg = qa_block_words_to_preg($this->blockWordString);
     $test2 = qa_block_words_match_all('tried an ocean boat', $wordpreg);
     // matches are returned as array of [offset] => [length]
     $expected = array(0 => 5, 9 => 5, 15 => 4);
     $this->assertEmpty($test1);
     $this->assertEquals($expected, $test2);
 }
Exemple #3
0
 function output_widget($region, $place, $themeobject, $template, $request, $qa_content)
 {
     require_once QA_INCLUDE_DIR . 'qa-db-selects.php';
     $widget_opt = @$themeobject->current_widget['param']['options'];
     if (@$themeobject->current_widget['param']['locations']['show_title']) {
         $themeobject->output('<h3 class="widget-title">' . qa_lang('cleanstrap/tags') . '<a href="' . qa_path_html('tags') . '">' . qa_lang('cleanstrap/view_all') . '</a></h3>');
     }
     $to_show = (int) $widget_opt['cs_tags_count'];
     $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, !empty($to_show) ? $to_show : 20));
     reset($populartags);
     $themeobject->output('<div class="ra-tags-widget clearfix">');
     $blockwordspreg = qa_get_block_words_preg();
     foreach ($populartags as $tag => $count) {
         if (count(qa_block_words_match_all($tag, $blockwordspreg))) {
             continue;
         }
         // skip censored tags
         $themeobject->output('<a href="' . qa_path_html('tag/' . $tag) . '" class="widget-tag">' . qa_html($tag) . '<span>' . $count . '</span></a>');
     }
     $themeobject->output('</div>');
 }
Exemple #4
0
function qa_post_html_fields($post, $userid, $cookieid, $usershtml, $dummy, $options = array())
{
    if (qa_to_override(__FUNCTION__)) {
        $args = func_get_args();
        return qa_call_override(__FUNCTION__, $args);
    }
    require_once QA_INCLUDE_DIR . 'app/updates.php';
    if (isset($options['blockwordspreg'])) {
        require_once QA_INCLUDE_DIR . 'util/string.php';
    }
    $fields = array('raw' => $post);
    //	Useful stuff used throughout function
    $postid = $post['postid'];
    $isquestion = $post['basetype'] == 'Q';
    $isanswer = $post['basetype'] == 'A';
    $isbyuser = qa_post_is_by_user($post, $userid, $cookieid);
    $anchor = urlencode(qa_anchor($post['basetype'], $postid));
    $elementid = isset($options['elementid']) ? $options['elementid'] : $anchor;
    $microformats = @$options['microformats'];
    $isselected = @$options['isselected'];
    $favoritedview = @$options['favoritedview'];
    $favoritemap = $favoritedview ? qa_get_favorite_non_qs_map() : array();
    //	High level information
    $fields['hidden'] = @$post['hidden'];
    $fields['tags'] = 'id="' . qa_html($elementid) . '"';
    $fields['classes'] = $isquestion && $favoritedview && @$post['userfavoriteq'] ? 'qa-q-favorited' : '';
    if ($isquestion && isset($post['closedbyid'])) {
        $fields['classes'] = ltrim($fields['classes'] . ' qa-q-closed');
    }
    if ($microformats) {
        $fields['classes'] .= ' hentry ' . ($isquestion ? 'question' : ($isanswer ? $isselected ? 'answer answer-selected' : 'answer' : 'comment'));
    }
    //	Question-specific stuff (title, URL, tags, answer count, category)
    if ($isquestion) {
        if (isset($post['title'])) {
            $fields['url'] = qa_q_path_html($postid, $post['title']);
            if (isset($options['blockwordspreg'])) {
                $post['title'] = qa_block_words_replace($post['title'], $options['blockwordspreg']);
            }
            $fields['title'] = qa_html($post['title']);
            if ($microformats) {
                $fields['title'] = '<span class="entry-title">' . $fields['title'] . '</span>';
            }
            /*if (isset($post['score'])) // useful for setting match thresholds
            		$fields['title'].=' <small>('.$post['score'].')</small>';*/
        }
        if (@$options['tagsview'] && isset($post['tags'])) {
            $fields['q_tags'] = array();
            $tags = qa_tagstring_to_tags($post['tags']);
            foreach ($tags as $tag) {
                if (isset($options['blockwordspreg']) && count(qa_block_words_match_all($tag, $options['blockwordspreg']))) {
                    // skip censored tags
                    continue;
                }
                $fields['q_tags'][] = qa_tag_html($tag, $microformats, @$favoritemap['tag'][qa_strtolower($tag)]);
            }
        }
        if (@$options['answersview'] && isset($post['acount'])) {
            $fields['answers_raw'] = $post['acount'];
            $fields['answers'] = $post['acount'] == 1 ? qa_lang_html_sub_split('main/1_answer', '1', '1') : qa_lang_html_sub_split('main/x_answers', number_format($post['acount']));
            $fields['answer_selected'] = isset($post['selchildid']);
        }
        if (@$options['viewsview'] && isset($post['views'])) {
            $fields['views_raw'] = $post['views'];
            $fields['views'] = $post['views'] == 1 ? qa_lang_html_sub_split('main/1_view', '1', '1') : qa_lang_html_sub_split('main/x_views', number_format($post['views']));
        }
        if (@$options['categoryview'] && isset($post['categoryname']) && isset($post['categorybackpath'])) {
            $favoriteclass = '';
            if (count(@$favoritemap['category'])) {
                if (@$favoritemap['category'][$post['categorybackpath']]) {
                    $favoriteclass = ' qa-cat-favorited';
                } else {
                    foreach ($favoritemap['category'] as $categorybackpath => $dummy) {
                        if (substr('/' . $post['categorybackpath'], -strlen($categorybackpath)) == $categorybackpath) {
                            $favoriteclass = ' qa-cat-parent-favorited';
                        }
                    }
                }
            }
            $fields['where'] = qa_lang_html_sub_split('main/in_category_x', '<a href="' . qa_path_html(@$options['categorypathprefix'] . implode('/', array_reverse(explode('/', $post['categorybackpath'])))) . '" class="qa-category-link' . $favoriteclass . '">' . qa_html($post['categoryname']) . '</a>');
        }
    }
    //	Answer-specific stuff (selection)
    if ($isanswer) {
        $fields['selected'] = $isselected;
        if ($isselected) {
            $fields['select_text'] = qa_lang_html('question/select_text');
        }
    }
    //	Post content
    if (@$options['contentview'] && isset($post['content'])) {
        $viewer = qa_load_viewer($post['content'], $post['format']);
        $fields['content'] = $viewer->get_html($post['content'], $post['format'], array('blockwordspreg' => @$options['blockwordspreg'], 'showurllinks' => @$options['showurllinks'], 'linksnewwindow' => @$options['linksnewwindow']));
        if ($microformats) {
            $fields['content'] = '<div class="entry-content">' . $fields['content'] . '</div>';
        }
        $fields['content'] = '<a name="' . qa_html($postid) . '"></a>' . $fields['content'];
        // this is for backwards compatibility with any existing links using the old style of anchor
        // that contained the post id only (changed to be valid under W3C specifications)
    }
    //	Voting stuff
    if (@$options['voteview']) {
        $voteview = $options['voteview'];
        //	Calculate raw values and pass through
        if (@$options['ovoteview'] && isset($post['opostid'])) {
            $upvotes = (int) @$post['oupvotes'];
            $downvotes = (int) @$post['odownvotes'];
            $fields['vote_opostid'] = true;
            // for voters/flaggers layer
        } else {
            $upvotes = (int) @$post['upvotes'];
            $downvotes = (int) @$post['downvotes'];
        }
        $netvotes = (int) ($upvotes - $downvotes);
        $fields['upvotes_raw'] = $upvotes;
        $fields['downvotes_raw'] = $downvotes;
        $fields['netvotes_raw'] = $netvotes;
        //	Create HTML versions...
        $upvoteshtml = qa_html($upvotes);
        $downvoteshtml = qa_html($downvotes);
        if ($netvotes >= 1) {
            $netvoteshtml = '+' . qa_html($netvotes);
        } elseif ($netvotes <= -1) {
            $netvoteshtml = '&ndash;' . qa_html(-$netvotes);
        } else {
            $netvoteshtml = '0';
        }
        //	...with microformats if appropriate
        if ($microformats) {
            $netvoteshtml .= '<span class="votes-up"><span class="value-title" title="' . $upvoteshtml . '"></span></span>' . '<span class="votes-down"><span class="value-title" title="' . $downvoteshtml . '"></span></span>';
            $upvoteshtml = '<span class="votes-up">' . $upvoteshtml . '</span>';
            $downvoteshtml = '<span class="votes-down">' . $downvoteshtml . '</span>';
        }
        //	Pass information on vote viewing
        //	$voteview will be one of:
        //	updown, updown-disabled-page, updown-disabled-level, updown-uponly-level, updown-disabled-approve, updown-uponly-approve
        //	net, net-disabled-page, net-disabled-level, net-uponly-level, net-disabled-approve, net-uponly-approve
        $fields['vote_view'] = substr($voteview, 0, 6) == 'updown' ? 'updown' : 'net';
        $fields['vote_on_page'] = strpos($voteview, '-disabled-page') ? 'disabled' : 'enabled';
        $fields['upvotes_view'] = $upvotes == 1 ? qa_lang_html_sub_split('main/1_liked', $upvoteshtml, '1') : qa_lang_html_sub_split('main/x_liked', $upvoteshtml);
        $fields['downvotes_view'] = $downvotes == 1 ? qa_lang_html_sub_split('main/1_disliked', $downvoteshtml, '1') : qa_lang_html_sub_split('main/x_disliked', $downvoteshtml);
        $fields['netvotes_view'] = abs($netvotes) == 1 ? qa_lang_html_sub_split('main/1_vote', $netvoteshtml, '1') : qa_lang_html_sub_split('main/x_votes', $netvoteshtml);
        //	Voting buttons
        $fields['vote_tags'] = 'id="voting_' . qa_html($postid) . '"';
        $onclick = 'onclick="return qa_vote_click(this);"';
        if ($fields['hidden']) {
            $fields['vote_state'] = 'disabled';
            $fields['vote_up_tags'] = 'title="' . qa_lang_html($isanswer ? 'main/vote_disabled_hidden_a' : 'main/vote_disabled_hidden_q') . '"';
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif ($isbyuser) {
            $fields['vote_state'] = 'disabled';
            $fields['vote_up_tags'] = 'title="' . qa_lang_html($isanswer ? 'main/vote_disabled_my_a' : 'main/vote_disabled_my_q') . '"';
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif (strpos($voteview, '-disabled-')) {
            $fields['vote_state'] = @$post['uservote'] > 0 ? 'voted_up_disabled' : (@$post['uservote'] < 0 ? 'voted_down_disabled' : 'disabled');
            if (strpos($voteview, '-disabled-page')) {
                $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_q_page_only') . '"';
            } elseif (strpos($voteview, '-disabled-approve')) {
                $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_approve') . '"';
            } else {
                $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_disabled_level') . '"';
            }
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif (@$post['uservote'] > 0) {
            $fields['vote_state'] = 'voted_up';
            $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/voted_up_popup') . '" name="' . qa_html('vote_' . $postid . '_0_' . $elementid) . '" ' . $onclick;
            $fields['vote_down_tags'] = ' ';
        } elseif (@$post['uservote'] < 0) {
            $fields['vote_state'] = 'voted_down';
            $fields['vote_up_tags'] = ' ';
            $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/voted_down_popup') . '" name="' . qa_html('vote_' . $postid . '_0_' . $elementid) . '" ' . $onclick;
        } else {
            $fields['vote_up_tags'] = 'title="' . qa_lang_html('main/vote_up_popup') . '" name="' . qa_html('vote_' . $postid . '_1_' . $elementid) . '" ' . $onclick;
            if (strpos($voteview, '-uponly-level')) {
                $fields['vote_state'] = 'up_only';
                $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_disabled_down') . '"';
            } elseif (strpos($voteview, '-uponly-approve')) {
                $fields['vote_state'] = 'up_only';
                $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_disabled_down_approve') . '"';
            } else {
                $fields['vote_state'] = 'enabled';
                $fields['vote_down_tags'] = 'title="' . qa_lang_html('main/vote_down_popup') . '" name="' . qa_html('vote_' . $postid . '_-1_' . $elementid) . '" ' . $onclick;
            }
        }
    }
    //	Flag count
    if (@$options['flagsview'] && @$post['flagcount']) {
        $fields['flags'] = $post['flagcount'] == 1 ? qa_lang_html_sub_split('main/1_flag', '1', '1') : qa_lang_html_sub_split('main/x_flags', $post['flagcount']);
    }
    //	Created when and by whom
    $fields['meta_order'] = qa_lang_html('main/meta_order');
    // sets ordering of meta elements which can be language-specific
    if (@$options['whatview']) {
        $fields['what'] = qa_lang_html($isquestion ? 'main/asked' : ($isanswer ? 'main/answered' : 'main/commented'));
        if (@$options['whatlink'] && strlen(@$options['q_request'])) {
            $fields['what_url'] = $post['basetype'] == 'Q' ? qa_path_html($options['q_request']) : qa_path_html($options['q_request'], array('show' => $postid), null, null, qa_anchor($post['basetype'], $postid));
        }
    }
    if (isset($post['created']) && @$options['whenview']) {
        $fields['when'] = qa_when_to_html($post['created'], @$options['fulldatedays']);
        if ($microformats) {
            $fields['when']['data'] = '<span class="published"><span class="value-title" title="' . gmdate('Y-m-d\\TH:i:sO', $post['created']) . '">' . $fields['when']['data'] . '</span></span>';
        }
    }
    if (@$options['whoview']) {
        $fields['who'] = qa_who_to_html($isbyuser, @$post['userid'], $usershtml, @$options['ipview'] ? @$post['createip'] : null, $microformats, $post['name']);
        if (isset($post['points'])) {
            if (@$options['pointsview']) {
                $fields['who']['points'] = $post['points'] == 1 ? qa_lang_html_sub_split('main/1_point', '1', '1') : qa_lang_html_sub_split('main/x_points', qa_html(number_format($post['points'])));
            }
            if (isset($options['pointstitle'])) {
                $fields['who']['title'] = qa_get_points_title_html($post['points'], $options['pointstitle']);
            }
        }
        if (isset($post['level'])) {
            $fields['who']['level'] = qa_html(qa_user_level_string($post['level']));
        }
    }
    if (@$options['avatarsize'] > 0) {
        if (QA_FINAL_EXTERNAL_USERS) {
            $fields['avatar'] = qa_get_external_avatar_html($post['userid'], $options['avatarsize'], false);
        } else {
            $fields['avatar'] = qa_get_user_avatar_html(@$post['flags'], @$post['email'], @$post['handle'], @$post['avatarblobid'], @$post['avatarwidth'], @$post['avatarheight'], $options['avatarsize']);
        }
    }
    //	Updated when and by whom
    if (@$options['updateview'] && isset($post['updated']) && ($post['updatetype'] != QA_UPDATE_SELECTED || $isselected) && (!isset($post['created']) || $post['hidden'] && $post['updatetype'] == QA_UPDATE_VISIBLE || isset($post['closedbyid']) && $post['updatetype'] == QA_UPDATE_CLOSED || abs($post['updated'] - $post['created']) > 300 || $post['lastuserid'] != $post['userid'])) {
        switch ($post['updatetype']) {
            case QA_UPDATE_TYPE:
            case QA_UPDATE_PARENT:
                $langstring = 'main/moved';
                break;
            case QA_UPDATE_CATEGORY:
                $langstring = 'main/recategorized';
                break;
            case QA_UPDATE_VISIBLE:
                $langstring = $post['hidden'] ? 'main/hidden' : 'main/reshown';
                break;
            case QA_UPDATE_CLOSED:
                $langstring = isset($post['closedbyid']) ? 'main/closed' : 'main/reopened';
                break;
            case QA_UPDATE_TAGS:
                $langstring = 'main/retagged';
                break;
            case QA_UPDATE_SELECTED:
                $langstring = 'main/selected';
                break;
            default:
                $langstring = 'main/edited';
                break;
        }
        $fields['what_2'] = qa_lang_html($langstring);
        if (@$options['whenview']) {
            $fields['when_2'] = qa_when_to_html($post['updated'], @$options['fulldatedays']);
            if ($microformats) {
                $fields['when_2']['data'] = '<span class="updated"><span class="value-title" title="' . gmdate('Y-m-d\\TH:i:sO', $post['updated']) . '">' . $fields['when_2']['data'] . '</span></span>';
            }
        }
        if (isset($post['lastuserid']) && @$options['whoview']) {
            $fields['who_2'] = qa_who_to_html(isset($userid) && $post['lastuserid'] == $userid, $post['lastuserid'], $usershtml, @$options['ipview'] ? $post['lastip'] : null, false);
        }
    } elseif ($microformats && @$options['whenview']) {
        // quick fix for incorrect microformats (missing 'updated' class)
        $fields['when']['data'] = str_replace('<span class="published">', '<span class="published updated">', $fields['when']['data']);
    }
    //	That's it!
    return $fields;
}
Exemple #5
0
function qa_block_words_replace($string, $wordspreg, $character = '*')
{
    if (qa_to_override(__FUNCTION__)) {
        $args = func_get_args();
        return qa_call_override(__FUNCTION__, $args);
    }
    if (strlen($wordspreg)) {
        $matches = qa_block_words_match_all($string, $wordspreg);
        krsort($matches, SORT_NUMERIC);
        foreach ($matches as $start => $length) {
            // get length again below to deal with multi-byte characters
            $string = substr_replace($string, str_repeat($character, qa_strlen(substr($string, $start, $length))), $start, $length);
        }
    }
    return $string;
}
 function output_widget($region, $place, $themeobject, $template, $request, $qa_content)
 {
     require_once QA_INCLUDE_DIR . 'qa-db-selects.php';
     $populartags = qa_db_single_select(qa_db_popular_tags_selectspec(0, (int) qa_opt('tag_cloud_count_tags')));
     reset($populartags);
     $maxcount = current($populartags);
     $themeobject->output('<h2 style="margin-top:0; padding-top:0;">', qa_lang_html('main/popular_tags'), '</h2>');
     $themeobject->output('<div style="font-size:10px;">');
     $maxsize = qa_opt('tag_cloud_font_size');
     $scale = qa_opt('tag_cloud_size_popular');
     $blockwordspreg = qa_get_block_words_preg();
     foreach ($populartags as $tag => $count) {
         if (count(qa_block_words_match_all($tag, $blockwordspreg))) {
             continue;
         }
         // skip censored tags
         $size = number_format($scale ? $maxsize * $count / $maxcount : $maxsize, 1);
         if ($size >= 5 || !$scale) {
             $themeobject->output('<a href="' . qa_path_html('tag/' . $tag) . '" style="font-size:' . $size . 'px; vertical-align:baseline;">' . qa_html($tag) . '</a>');
         }
     }
     $themeobject->output('</div>');
 }
Exemple #7
0
 function get_html($content, $format, $options)
 {
     if ($format == 'html') {
         $html = qa_sanitize_html($content, @$options['linksnewwindow'], false);
         // sanitize again for display, for extra safety, and due to new window setting
         if (isset($options['blockwordspreg'])) {
             // filtering out blocked words inline within HTML is pretty complex, e.g. p<B>oo</B>p must be caught
             require_once QA_INCLUDE_DIR . 'qa-util-string.php';
             $html = preg_replace('/<\\s*(' . $this->htmllineseparators . ')[^A-Za-z0-9]/i', "\n\\0", $html);
             // tags to single new line
             $html = preg_replace('/<\\s*(' . $this->htmlparagraphseparators . ')[^A-Za-z0-9]/i', "\n\n\\0", $html);
             // tags to double new line
             preg_match_all('/<[^>]*>/', $html, $pregmatches, PREG_OFFSET_CAPTURE);
             // find tag positions and lengths
             $tagmatches = $pregmatches[0];
             $text = preg_replace('/<[^>]*>/', '', $html);
             // effectively strip_tags() but use same regexp as above to ensure consistency
             $blockmatches = qa_block_words_match_all($text, $options['blockwordspreg']);
             // search for blocked words within text
             $nexttagmatch = array_shift($tagmatches);
             $texttohtml = 0;
             $htmlshift = 0;
             foreach ($blockmatches as $textoffset => $textlength) {
                 while (isset($nexttagmatch) && $nexttagmatch[1] <= $textoffset + $texttohtml) {
                     // keep text and html in sync
                     $texttohtml += strlen($nexttagmatch[0]);
                     $nexttagmatch = array_shift($tagmatches);
                 }
                 while (1) {
                     $replacepart = $textlength;
                     if (isset($nexttagmatch)) {
                         $replacepart = min($replacepart, $nexttagmatch[1] - ($textoffset + $texttohtml));
                     }
                     // stop replacing early if we hit an HTML tag
                     $replacelength = qa_strlen(substr($text, $textoffset, $replacepart));
                     // to work with multi-byte characters
                     $html = substr_replace($html, str_repeat('*', $replacelength), $textoffset + $texttohtml + $htmlshift, $replacepart);
                     $htmlshift += $replacelength - $replacepart;
                     // HTML might have moved around if we replaced multi-byte characters
                     if ($replacepart >= $textlength) {
                         break;
                     }
                     // we have replaced everything expected, otherwise more left (due to hitting an HTML tag)
                     $textlength -= $replacepart;
                     $textoffset += $replacepart;
                     $texttohtml += strlen($nexttagmatch[0]);
                     $nexttagmatch = array_shift($tagmatches);
                 }
             }
         }
         if (@$options['showurllinks']) {
             // we need to ensure here that we don't put new links inside existing ones
             require_once QA_INCLUDE_DIR . 'qa-util-string.php';
             $htmlunlinkeds = array_reverse(preg_split('|<[Aa]\\s+[^>]+>.*</[Aa]\\s*>|', $html, -1, PREG_SPLIT_OFFSET_CAPTURE));
             // start from end so we substitute correctly
             foreach ($htmlunlinkeds as $htmlunlinked) {
                 // and that we don't detect links inside HTML, e.g. <IMG SRC="http://...">
                 $thishtmluntaggeds = array_reverse(preg_split('/<[^>]*>/', $htmlunlinked[0], -1, PREG_SPLIT_OFFSET_CAPTURE));
                 // again, start from end
                 foreach ($thishtmluntaggeds as $thishtmluntagged) {
                     $innerhtml = $thishtmluntagged[0];
                     if (is_numeric(strpos($innerhtml, '://'))) {
                         // quick test first
                         $newhtml = qa_html_convert_urls($innerhtml, qa_opt('links_in_new_window'));
                         $html = substr_replace($html, $newhtml, $htmlunlinked[1] + $thishtmluntagged[1], strlen($innerhtml));
                     }
                 }
             }
         }
     } elseif ($format == '') {
         if (isset($options['blockwordspreg'])) {
             require_once QA_INCLUDE_DIR . 'qa-util-string.php';
             $content = qa_block_words_replace($content, $options['blockwordspreg']);
         }
         $html = qa_html($content, true);
         if (@$options['showurllinks']) {
             require_once QA_INCLUDE_DIR . 'qa-app-format.php';
             $html = qa_html_convert_urls($html, qa_opt('links_in_new_window'));
         }
     } else {
         $html = '[no viewer found for format: ' . qa_html($format) . ']';
     }
     // for unknown formats
     return $html;
 }
function qa_block_words_replace($string, $wordspreg, $character = '*')
{
    if (strlen($wordspreg)) {
        $matches = qa_block_words_match_all($string, $wordspreg);
        krsort($matches, SORT_NUMERIC);
        foreach ($matches as $start => $length) {
            // get length again below to deal with multi-byte characters
            $string = substr_replace($string, str_repeat($character, qa_strlen(substr($string, $start, $length))), $start, $length);
        }
    }
    return $string;
}
function qa_post_html_fields($post, $userid, $cookieid, $usershtml, $dummy, $options = array())
{
    if (isset($options['blockwordspreg'])) {
        require_once QA_INCLUDE_DIR . 'qa-util-string.php';
    }
    $fields = array();
    $fields['raw'] = $post;
    //	Useful stuff used throughout function
    $postid = $post['postid'];
    $isquestion = $post['basetype'] == 'Q';
    $isanswer = $post['basetype'] == 'A';
    $isbyuser = qa_post_is_by_user($post, $userid, $cookieid);
    $anchor = urlencode(qa_anchor($post['basetype'], $postid));
    $microformats = @$options['microformats'];
    $isselected = @$options['isselected'];
    //	High level information
    $fields['hidden'] = $post['hidden'];
    $fields['tags'] = 'ID="' . $anchor . '"';
    if ($microformats) {
        $fields['classes'] = 'hentry ' . ($isquestion ? 'question' : ($isanswer ? $isselected ? 'answer answer-selected' : 'answer' : 'comment'));
    }
    //	Question-specific stuff (title, URL, tags, answer count, category)
    if ($isquestion) {
        if (isset($post['title'])) {
            if (isset($options['blockwordspreg'])) {
                $post['title'] = qa_block_words_replace($post['title'], $options['blockwordspreg']);
            }
            $fields['title'] = qa_html($post['title']);
            if ($microformats) {
                $fields['title'] = '<SPAN CLASS="entry-title">' . $fields['title'] . '</SPAN>';
            }
            $fields['url'] = qa_path_html(qa_q_request($postid, $post['title']));
            /*if (isset($post['score'])) // useful for setting match thresholds
            		$fields['title'].=' <SMALL>('.$post['score'].')</SMALL>';*/
        }
        if (@$options['tagsview'] && isset($post['tags'])) {
            $fields['q_tags'] = array();
            $tags = qa_tagstring_to_tags($post['tags']);
            foreach ($tags as $tag) {
                if (isset($options['blockwordspreg']) && count(qa_block_words_match_all($tag, $options['blockwordspreg']))) {
                    // skip censored tags
                    continue;
                }
                $fields['q_tags'][] = qa_tag_html($tag, $microformats);
            }
        }
        if (@$options['answersview'] && isset($post['acount'])) {
            $fields['answers_raw'] = $post['acount'];
            $fields['answers'] = $post['acount'] == 1 ? qa_lang_html_sub_split('main/1_answer', '1', '1') : qa_lang_html_sub_split('main/x_answers', number_format($post['acount']));
            $fields['answer_selected'] = isset($post['selchildid']);
        }
        if (@$options['viewsview'] && isset($post['views'])) {
            $fields['views_raw'] = $post['views'];
            $fields['views'] = $post['views'] == 1 ? qa_lang_html_sub_split('main/1_view', '1', '1') : qa_lang_html_sub_split('main/x_views', number_format($post['views']));
        }
        if (isset($post['categoryname']) && isset($post['categorybackpath'])) {
            $fields['where'] = qa_lang_html_sub_split('main/in_category_x', '<A HREF="' . qa_path_html(@$options['categorypathprefix'] . implode('/', array_reverse(explode('/', $post['categorybackpath'])))) . '" CLASS="qa-category-link">' . qa_html($post['categoryname']) . '</A>');
        }
    }
    //	Answer-specific stuff (selection)
    if ($isanswer) {
        $fields['selected'] = $isselected;
        if ($isselected) {
            $fields['select_text'] = qa_lang_html('question/select_text');
        }
    }
    //	Post content
    if (!empty($post['content'])) {
        $viewer = qa_load_viewer($post['content'], $post['format']);
        $fields['content'] = $viewer->get_html($post['content'], $post['format'], array('blockwordspreg' => @$options['blockwordspreg'], 'showurllinks' => @$options['showurllinks'], 'linksnewwindow' => @$options['linksnewwindow']));
        if ($microformats) {
            $fields['content'] = '<SPAN CLASS="entry-content">' . $fields['content'] . '</SPAN>';
        }
        $fields['content'] = '<A NAME="' . qa_html($postid) . '"></A>' . $fields['content'];
        // this is for backwards compatibility with any existing links using the old style of anchor
        // that contained the post id only (changed to be valid under W3C specifications)
    }
    //	Voting stuff
    if (@$options['voteview']) {
        $voteview = $options['voteview'];
        //	Calculate raw values and pass through
        $upvotes = (int) @$post['upvotes'];
        $downvotes = (int) @$post['downvotes'];
        $netvotes = (int) ($upvotes - $downvotes);
        $fields['upvotes_raw'] = $upvotes;
        $fields['downvotes_raw'] = $downvotes;
        $fields['netvotes_raw'] = $netvotes;
        //	Create HTML versions...
        $upvoteshtml = qa_html($upvotes);
        $downvoteshtml = qa_html($downvotes);
        if ($netvotes >= 1) {
            $netvoteshtml = '+' . qa_html($netvotes);
        } elseif ($netvotes <= -1) {
            $netvoteshtml = '&ndash;' . qa_html(-$netvotes);
        } else {
            $netvoteshtml = '0';
        }
        //	...with microformats if appropriate
        if ($microformats) {
            $netvoteshtml .= '<SPAN CLASS="votes-up"><SPAN CLASS="value-title" TITLE="' . $upvoteshtml . '"></SPAN></SPAN>' . '<SPAN CLASS="votes-down"><SPAN CLASS="value-title" TITLE="' . $downvoteshtml . '"></SPAN></SPAN>';
            $upvoteshtml = '<SPAN CLASS="votes-up">' . $upvoteshtml . '</SPAN>';
            $downvoteshtml = '<SPAN CLASS="votes-down">' . $downvoteshtml . '</SPAN>';
        }
        //	Pass information on vote viewing
        //	$voteview will be one of: updown, net, updown-disabled-level, net-disabled-level, updown-disabled-page, net-disabled-page
        $fields['vote_view'] = substr($voteview, 0, 6) == 'updown' ? 'updown' : 'net';
        $fields['upvotes_view'] = $upvotes == 1 ? qa_lang_html_sub_split('main/1_liked', $upvoteshtml, '1') : qa_lang_html_sub_split('main/x_liked', $upvoteshtml);
        $fields['downvotes_view'] = $downvotes == 1 ? qa_lang_html_sub_split('main/1_disliked', $downvoteshtml, '1') : qa_lang_html_sub_split('main/x_disliked', $downvoteshtml);
        $fields['netvotes_view'] = abs($netvotes) == 1 ? qa_lang_html_sub_split('main/1_vote', $netvoteshtml, '1') : qa_lang_html_sub_split('main/x_votes', $netvoteshtml);
        //	Voting buttons
        $fields['vote_tags'] = 'ID="voting_' . qa_html($postid) . '"';
        $onclick = 'onClick="return qa_vote_click(this);"';
        if ($fields['hidden']) {
            $fields['vote_state'] = 'disabled';
            $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html($isanswer ? 'main/vote_disabled_hidden_a' : 'main/vote_disabled_hidden_q') . '"';
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif ($isbyuser) {
            $fields['vote_state'] = 'disabled';
            $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html($isanswer ? 'main/vote_disabled_my_a' : 'main/vote_disabled_my_q') . '"';
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif (strpos($voteview, '-disabled-')) {
            $fields['vote_state'] = @$post['uservote'] > 0 ? 'voted_up_disabled' : (@$post['uservote'] < 0 ? 'voted_down_disabled' : 'disabled');
            if (strpos($voteview, '-disabled-page')) {
                $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_disabled_q_page_only') . '"';
            } else {
                $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_disabled_level') . '"';
            }
            $fields['vote_down_tags'] = $fields['vote_up_tags'];
        } elseif (@$post['uservote'] > 0) {
            $fields['vote_state'] = 'voted_up';
            $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/voted_up_popup') . '" NAME="' . qa_html('vote_' . $postid . '_0_' . $anchor) . '"' . $onclick;
            $fields['vote_down_tags'] = ' ';
        } elseif (@$post['uservote'] < 0) {
            $fields['vote_state'] = 'voted_down';
            $fields['vote_up_tags'] = ' ';
            $fields['vote_down_tags'] = 'TITLE="' . qa_lang_html('main/voted_down_popup') . '" NAME="' . qa_html('vote_' . $postid . '_0_' . $anchor) . '" ' . $onclick;
        } else {
            $fields['vote_state'] = 'enabled';
            $fields['vote_up_tags'] = 'TITLE="' . qa_lang_html('main/vote_up_popup') . '" NAME="' . qa_html('vote_' . $postid . '_1_' . $anchor) . '" ' . $onclick;
            $fields['vote_down_tags'] = 'TITLE="' . qa_lang_html('main/vote_down_popup') . '" NAME="' . qa_html('vote_' . $postid . '_-1_' . $anchor) . '" ' . $onclick;
        }
    }
    //	Flag count
    if (@$options['flagsview'] && @$post['flagcount']) {
        $fields['flags'] = $post['flagcount'] == 1 ? qa_lang_html_sub_split('main/1_flag', '1', '1') : qa_lang_html_sub_split('main/x_flags', $post['flagcount']);
    }
    //	Created when and by whom
    $fields['meta_order'] = qa_lang_html('main/meta_order');
    // sets ordering of meta elements which can be language-specific
    $fields['what'] = qa_lang_html($isquestion ? 'main/asked' : ($isanswer ? 'main/answered' : 'main/commented'));
    if (@$options['whatlink'] && !$isquestion) {
        $fields['what_url'] = '#' . qa_html(urlencode($anchor));
    }
    if (isset($post['created']) && @$options['whenview']) {
        $whenhtml = qa_html(qa_time_to_string(qa_opt('db_time') - $post['created']));
        if ($microformats) {
            $whenhtml = '<SPAN CLASS="published"><SPAN CLASS="value-title" TITLE="' . gmdate('Y-m-d\\TH:i:sO', $post['created']) . '"></SPAN>' . $whenhtml . '</SPAN>';
        }
        $fields['when'] = qa_lang_html_sub_split('main/x_ago', $whenhtml);
    }
    if (@$options['whoview']) {
        $fields['who'] = qa_who_to_html($isbyuser, @$post['userid'], $usershtml, @$options['ipview'] ? @$post['createip'] : null, $microformats);
        if (isset($post['points'])) {
            if (@$options['pointsview']) {
                $fields['who']['points'] = $post['points'] == 1 ? qa_lang_html_sub_split('main/1_point', '1', '1') : qa_lang_html_sub_split('main/x_points', qa_html(number_format($post['points'])));
            }
            if (isset($options['pointstitle'])) {
                $fields['who']['title'] = qa_get_points_title_html($post['points'], $options['pointstitle']);
            }
        }
        if (isset($post['level'])) {
            $fields['who']['level'] = qa_html(qa_user_level_string($post['level']));
        }
    }
    if (!QA_FINAL_EXTERNAL_USERS && @$options['avatarsize'] > 0) {
        $fields['avatar'] = qa_get_user_avatar_html($post['flags'], $post['email'], $post['handle'], $post['avatarblobid'], $post['avatarwidth'], $post['avatarheight'], $options['avatarsize']);
    }
    //	Updated when and by whom
    if (isset($post['updated']) && (!isset($post['created']) || $post['hidden'] || abs($post['updated'] - $post['created']) > 300 || $post['lastuserid'] != $post['userid'])) {
        if (@$options['whenview']) {
            $whenhtml = qa_html(qa_time_to_string(qa_opt('db_time') - $post['updated']));
            if ($microformats) {
                $whenhtml = '<SPAN CLASS="updated"><SPAN CLASS="value-title" TITLE="' . gmdate('Y-m-d\\TH:i:sO', $post['updated']) . '"></SPAN>' . $whenhtml . '</SPAN>';
            }
            $fields['when_2'] = qa_lang_html_sub_split($fields['hidden'] ? 'question/hidden_x_ago' : 'question/edited_x_ago', $whenhtml);
        } else {
            $fields['when_2']['prefix'] = qa_lang_html($fields['hidden'] ? 'question/hidden' : 'main/edited');
        }
        if ($fields['hidden'] && $post['flagcount'] && !isset($post['lastuserid'])) {
        } else {
            $fields['who_2'] = qa_who_to_html(isset($userid) && $post['lastuserid'] == $userid, $post['lastuserid'], $usershtml, @$options['ipview'] ? $post['lastip'] : null, false);
        }
    }
    //	That's it!
    return $fields;
}
 function get_html($content, $format, $options)
 {
     if ($format == 'html') {
         $html = qa_sanitize_html($content, @$options['linksnewwindow']);
         // sanitize again for display, for extra safety, and due to new window setting
         if (isset($options['blockwordspreg'])) {
             // filtering out blocked words inline within HTML is pretty complex, e.g. p<B>oo</B>p must be caught
             require_once QA_INCLUDE_DIR . 'qa-util-string.php';
             $html = preg_replace('/<\\s*(' . $this->htmllineseparators . ')[^A-Za-z0-9]/i', "\n\\0", $html);
             // tags to single new line
             $html = preg_replace('/<\\s*(' . $this->htmlparagraphseparators . ')[^A-Za-z0-9]/i', "\n\n\\0", $html);
             // tags to double new line
             preg_match_all('/<[^>]*>/', $html, $pregmatches, PREG_OFFSET_CAPTURE);
             // find tag positions and lengths
             $tagmatches = $pregmatches[0];
             $text = preg_replace('/<[^>]*>/', '', $html);
             // effectively strip_tags() but use same regexp as above to ensure consistency
             $blockmatches = qa_block_words_match_all($text, $options['blockwordspreg']);
             // search for blocked words within text
             $nexttagmatch = array_shift($tagmatches);
             $texttohtml = 0;
             $htmlshift = 0;
             foreach ($blockmatches as $textoffset => $textlength) {
                 while (isset($nexttagmatch) && $nexttagmatch[1] <= $textoffset + $texttohtml) {
                     // keep text and html in sync
                     $texttohtml += strlen($nexttagmatch[0]);
                     $nexttagmatch = array_shift($tagmatches);
                 }
                 while (1) {
                     $replacepart = $textlength;
                     if (isset($nexttagmatch)) {
                         $replacepart = min($replacepart, $nexttagmatch[1] - ($textoffset + $texttohtml));
                     }
                     // stop replacing early if we hit an HTML tag
                     $replacelength = qa_strlen(substr($text, $textoffset, $replacepart));
                     // to work with multi-byte characters
                     $html = substr_replace($html, str_repeat('*', $replacelength), $textoffset + $texttohtml + $htmlshift, $replacepart);
                     $htmlshift += $replacelength - $replacepart;
                     // HTML might have moved around if we replaced multi-byte characters
                     if ($replacepart >= $textlength) {
                         break;
                     }
                     // we have replaced everything expected, otherwise more left (due to hitting an HTML tag)
                     $textlength -= $replacepart;
                     $textoffset += $replacepart;
                     $texttohtml += strlen($nexttagmatch[0]);
                     $nexttagmatch = array_shift($tagmatches);
                 }
             }
         }
     } else {
         if (isset($options['blockwordspreg'])) {
             require_once QA_INCLUDE_DIR . 'qa-util-string.php';
             $content = qa_block_words_replace($content, $options['blockwordspreg']);
         }
         $html = qa_html($content, true);
         if (@$options['showurllinks']) {
             require_once QA_INCLUDE_DIR . 'qa-app-format.php';
             $html = qa_html_convert_urls($html, qa_opt('links_in_new_window'));
         }
     }
     return $html;
 }