function adinj_activate_hook()
{
    $ops = adinj_options();
    if (empty($ops)) {
        // 1st Install.
        adinj_install_db();
    } else {
        // Upgrade check.
        adinj_upgrade_db_if_necessary();
    }
}
function adinj_content_hook($content)
{
    if (is_feed()) {
        return $content;
    }
    // TODO feed specific ads
    if (!in_the_loop()) {
        return $content;
    }
    // Don't insert ads into meta description tags
    $ops = adinj_options();
    if (empty($ops)) {
        return $content;
    }
    $debug_on = adinj_debug_on();
    $debug = "";
    if ($debug_on) {
        echo "<!--adinj Ad Injection debug mode on-->";
    }
    adinj_upgrade_db_if_necessary();
    global $adinj_total_random_ads_used, $adinj_total_top_ads_used, $adinj_total_bottom_ads_used;
    if (!is_archive() && (is_page() || is_single())) {
        // On single page the_content may be called more than once - e.g. for
        // description meta tag and for content.
        $adinj_total_top_ads_used = 0;
        $adinj_total_random_ads_used = 0;
        $adinj_total_bottom_ads_used = 0;
    }
    $reason = adinj_ads_completely_disabled_from_page('in-content', $content);
    if ($reason !== false) {
        return adinj($content, $reason);
    }
    if ($debug_on && adinj_direct_mode()) {
        $showads = adshow_show_adverts();
        if ($showads !== true) {
            $debug .= "\nNOADS: ad blocked at run time reason={$showads}";
        }
    }
    $topad = adinj_ad_code_top();
    if (empty($topad)) {
        if ($debug_on) {
            $debug .= "\nNo top ad defined in any of the ad code boxes";
        }
    }
    $randomad = adinj_ad_code_random();
    if (empty($randomad)) {
        if ($debug_on) {
            $debug .= "\nNo random ad defined in any of the ad code boxes";
        }
    }
    $bottomad = adinj_ad_code_bottom();
    if (empty($bottomad)) {
        if ($debug_on) {
            $debug .= "\nNo bottom ad defined in any of the ad code boxes";
        }
    }
    if (empty($topad) && empty($randomad) && empty($bottomad)) {
        return adinj($content, "None of top, random or bottom ads are defined.");
    }
    $ad_include = "";
    if (adinj_mfunc_mode()) {
        $ad_include = adinj_ad_code_include();
    }
    # Ad sandwich mode
    if (is_page() || is_single()) {
        if (stripos($content, "<!--adsandwich-->") !== false) {
            return adinj($ad_include . $topad . $content . $bottomad, "Ads=sandwich" . $debug);
        }
        if (stripos($content, "<!--adfooter-->") !== false) {
            return adinj($content . $ad_include . $bottomad, "Ads=footer" . $debug);
        }
    }
    # Get content length for ad placement settings
    $rawlength = strlen($content);
    $length = 0;
    if ($ops['content_length_unit'] == 'all') {
        $length = $rawlength;
    } else {
        if ($ops['content_length_unit'] == 'viewable') {
            $length = strlen(strip_tags($content));
        } else {
            $length = str_word_count_utf8(strip_tags($content));
        }
    }
    # Record original paragraph positions
    $original_paragraph_positions = array();
    $prevpos = -1;
    while (($prevpos = stripos($content, ADINJ_PARA, $prevpos + 1)) !== false) {
        $valid = true;
        if (adinj_ticked('exclude_ads_from_block_tags')) {
            $next_blockquote_open = adinj_stripos($content, '<blockquote', $prevpos);
            $next_blockquote_close = adinj_stripos($content, '</blockquote>', $prevpos);
            $next_pre_open = adinj_stripos($content, '<pre', $prevpos);
            $next_pre_close = adinj_stripos($content, '</pre>', $prevpos);
            $valid = ($next_blockquote_open == $next_blockquote_close || $next_blockquote_open > $prevpos && $next_blockquote_open <= $next_blockquote_close) && ($next_pre_open == $next_pre_close || $next_pre_open > $prevpos && $next_pre_open <= $next_pre_close);
            if (!$valid) {
                continue;
            }
        }
        if (adinj_ticked('exclude_ads_from_div_tags')) {
            $next_open = adinj_stripos($content, '<div', $prevpos);
            $next_close = adinj_stripos($content, '</div>', $prevpos);
            $valid = $next_open == $next_close || $next_open > $prevpos && $next_open <= $next_close;
            if (!$valid) {
                continue;
            }
        }
        if (adinj_ticked('exclude_ads_from_list_tags')) {
            $next_open = adinj_stripos($content, '<ol', $prevpos);
            $next_close = adinj_stripos($content, '</ol>', $prevpos);
            $valid = $next_open == $next_close || $next_open > $prevpos && $next_open <= $next_close;
            if (!$valid) {
                continue;
            }
        }
        if (adinj_ticked('exclude_ads_from_list_tags')) {
            $next_open = adinj_stripos($content, '<ul', $prevpos);
            $next_close = adinj_stripos($content, '</ul>', $prevpos);
            $valid = $next_open == $next_close || $next_open > $prevpos && $next_open <= $next_close;
            if (!$valid) {
                continue;
            }
        }
        if (adinj_ticked('exclude_ads_from_form_tags')) {
            $next_open = adinj_stripos($content, '<form', $prevpos);
            $next_close = adinj_stripos($content, '</form>', $prevpos);
            $valid = $next_open == $next_close || $next_open > $prevpos && $next_open <= $next_close;
            if (!$valid) {
                continue;
            }
        }
        if (adinj_ticked('exclude_ads_from_table_tags')) {
            $next_open = adinj_stripos($content, '<table', $prevpos);
            $next_close = adinj_stripos($content, '</table>', $prevpos);
            $valid = $next_open == $next_close || $next_open > $prevpos && $next_open <= $next_close;
            if (!$valid) {
                continue;
            }
        }
        if ($valid) {
            $next_exclude_open = adinj_stripos($content, '<!--adinj_exclude_start-->', $prevpos);
            $next_exclude_close = adinj_stripos($content, '<!--adinj_exclude_end-->', $prevpos);
            if ($next_exclude_open == $next_exclude_close || $next_exclude_open > $prevpos && $next_exclude_open <= $next_exclude_close) {
                $original_paragraph_positions[] = $prevpos + strlen(ADINJ_PARA);
            }
        }
    }
    $paracount = count($original_paragraph_positions);
    if ($debug_on) {
        $debug .= "\nContent length={$length} (" . $ops['content_length_unit'] . ") Raw character length={$rawlength} Paragraph count={$paracount}";
    }
    if ($paracount == 0) {
        if ($debug_on) {
            $debug .= "\nWarning: No paragraph (&lt;/p&gt;) tags found.\n\n\tYour theme or one of your plugins may have changed the priority of the wpautop\n\n\tfilter so it is getting run later than expected (after Ad Injection has run).\n\n\tYou can try modifying the priority setting of Ad Injection's wp_content filter\n\n\tfrom the settings screen.\n\n\tTry 100, or if that fails 200!";
        }
    }
    # Positions to insert ads
    $top_ad_paragraph = -1;
    $random_ad_paragraphs = array();
    $bottom_ad_paragraph = -1;
    $fixed_top = stripos($content, "<!--topad-->");
    $fixed_random = stripos($content, "<!--randomad-->");
    $fixed_bottom = stripos($content, "<!--bottomad-->");
    # Find top ad position
    if ($fixed_top === false) {
        if (adinj_num_top_ads_to_insert($length, $debug) > 0) {
            $top_ad_paragraph = adinj_get_paragraph('top', $content, $original_paragraph_positions, $debug);
        }
    }
    if ($debug_on) {
        $debug .= "\nTop ad paragraph: {$top_ad_paragraph}";
    }
    # Find bottom ad position
    if ($fixed_bottom === false) {
        if (adinj_num_bottom_ads_to_insert($length, $debug) > 0) {
            $bottom_ad_paragraph = adinj_get_paragraph('bottom', $content, $original_paragraph_positions, $debug);
        }
        if ($bottom_ad_paragraph !== -1) {
            $bottom_ad_paragraph = $paracount - $bottom_ad_paragraph;
        }
    }
    if ($debug_on) {
        $debug .= "\nBottom ad paragraph: {$bottom_ad_paragraph}";
    }
    # Find random ad positions
    if ($fixed_random === false) {
        $random_ad_paragraphs = adinj_get_random_paragraphs($content, $length, $original_paragraph_positions, $debug);
        $random_ads_to_insert_count = sizeof($random_ad_paragraphs);
        if ($random_ads_to_insert_count == 0) {
            if ($debug_on) {
                $debug .= "\nWarning: No random ad injection positions";
            }
        }
    }
    # Insert the adverts into the content. Scan through the paragraph list in reverse order.
    $adpos = count($random_ad_paragraphs);
    $bottomadsetting = $ops['bottom_ad_position'];
    for ($i = $paracount; $i > 0; --$i) {
        if ($i === $bottom_ad_paragraph && $bottomadsetting != 0) {
            $content = substr_replace($content, $bottomad, $original_paragraph_positions[$i - 1], 0);
            ++$adinj_total_bottom_ads_used;
        }
        for ($j = $adpos - 1; $j >= 0; --$j) {
            $rnd = $random_ad_paragraphs[$j];
            if ($i == $rnd) {
                if (adinj_ticked('rnd_reselect_ad_per_position_in_post')) {
                    $randomad = adinj_ad_code_random();
                }
                $content = substr_replace($content, $randomad, $original_paragraph_positions[$rnd - 1], 0);
                ++$adinj_total_random_ads_used;
                --$adpos;
            } else {
                break;
            }
        }
        if ($i === $top_ad_paragraph) {
            $content = substr_replace($content, $topad, $original_paragraph_positions[$i - 1], 0);
            ++$adinj_total_top_ads_used;
        }
    }
    if ($top_ad_paragraph === 0) {
        // default is special case
        $content = $topad . $content;
        ++$adinj_total_top_ads_used;
    }
    if ($bottom_ad_paragraph !== -1 && $bottomadsetting == 0) {
        // default is special case as themes can't be trusted to close the final paragraph
        $content = $content . $bottomad;
        ++$adinj_total_bottom_ads_used;
    }
    if ($fixed_top) {
        adinj_insert_fixed_ad($content, $topad, 'top', $adinj_total_top_ads_used, $debug);
    }
    if ($fixed_random) {
        adinj_insert_fixed_ad($content, $randomad, 'random', $adinj_total_random_ads_used, $debug);
    }
    if ($fixed_bottom) {
        adinj_insert_fixed_ad($content, $bottomad, 'bottom', $adinj_total_bottom_ads_used, $debug);
    }
    $content = $ad_include . $content;
    return adinj($content, "Ad Injection in-content injections complete!" . $debug);
}