Beispiel #1
0
function phorum_check_cache($is_install = FALSE)
{
    global $PHORUM;
    $dir = $PHORUM['CACHECONFIG']['directory'];
    // Some general solution descriptions.
    $solution_1 = "Change the Cache Directory setting in\n                   include/config/cache.php.";
    $solution_2 = "Change the Cache Directory setting in\n                   include/config/cache.php or give your webserver more\n                   permissions for the current cache directory.";
    // Check if the cache directory exists.
    if (!file_exists($dir) || !is_dir($dir)) {
        return array($is_install ? PHORUM_SANITY_WARN : PHORUM_SANITY_CRIT, "The system is unable to find the cache\n         directory \"" . htmlspecialchars($dir) . "\" on\n         your system.", $solution_1);
    }
    $dummy_file = "{$dir}/sanity_check_dummy_file";
    // Check if we can create files in the cache directory.
    $fp = @fopen($dummy_file, "w");
    if (!$fp) {
        return array($is_install ? PHORUM_SANITY_WARN : PHORUM_SANITY_CRIT, "The system is unable to write files\n         to your cache directory \"" . htmlspecialchars($dir) . "\".\n         The system error was:<br/><br/>" . htmlspecialchars($php_errormsg) . ".", $solution_2);
    }
    if (!fclose($fp)) {
        return array($is_install ? PHORUM_SANITY_WARN : PHORUM_SANITY_CRIT, "The system is able to write a file to your cache\n         directory \"" . htmlspecialchars($dir) . "\",\n         however closing the file failed.", "Failure to close a file mostly indicates that the disk\n         on which the file is written is full. So check if your\n         server doesn't have any full disk and free some space\n         if this is the case.");
    }
    // Some very unusual thing might happen. On Windows2000 we have seen
    // that the webserver can write a message to the cache directory,
    // but that it cannot read it afterwards. Probably due to
    // specific NTFS file permission settings. So here we have to make
    // sure that we can open the file that we just wrote.
    $checkfp = fopen($dummy_file, "r");
    if (!$checkfp) {
        return array($is_install ? PHORUM_SANITY_WARN : PHORUM_SANITY_CRIT, "The system was able to write a file to your cache directory\n         \"" . htmlspecialchars($dir) . "\", but afterwards the created\n         file could not be read by the webserver. This is probably\n         caused by the file permissions on your cache directory.", $solution_2);
    }
    fclose($checkfp);
    unlink($dummy_file);
    $dummy_dir = "{$dir}/sanity_check_dummy_dir";
    // Check if we can create directories in the cache directory.
    if (!@mkdir($dummy_dir)) {
        return array($is_install ? PHORUM_SANITY_WARN : PHORUM_SANITY_CRIT, "The system is unable to create directories\n         in your cache directory \"" . htmlspecialchars($dir) . "\".\n         The system error was:<br/><br/>" . htmlspecialchars($php_errormsg) . ".", $solution_2);
    }
    rmdir($dummy_dir);
    // All seems OK. Do a final system check where we check
    // the caching system like the Phorum system will do.
    phorum_api_cache_put('sanity_checks', 'dummy', 'dummy');
    $entry = phorum_api_cache_get('sanity_checks', 'dummy');
    phorum_api_cache_remove('sanity_checks', 'dummy');
    if ($entry != 'dummy') {
        return array(PHORUM_SANITY_WARN, "There might be a problem in Phorum's caching system.\n         Storing and retrieving a dummy key failed. If you\n         experience problems with your Phorum installation,\n         it might be because of this.", "As a work around, you can disable the caching facilities\n         in the admin interface (note: this will not remove this\n         warning; it will only keep you out of troubles by making\n         sure that the caching system is not used). Please contact\n         the Phorum developers to find out what the problem is.");
    }
    return array(PHORUM_SANITY_OK, NULL, NULL);
}
Beispiel #2
0
// Retrieve the message replied to or the message being edited.
if ($mode != "post") {
    // Check read access on the forum that we're handling.
    if (!phorum_check_read_common()) {
        exit;
    }
    // Load the message from the database. If the message
    // can't be retrieved, then return to the message list.
    $dbmessage = null;
    if ($PHORUM['cache_messages']) {
        $dbmessage = phorum_api_cache_get('message', $PHORUM["forum_id"] . "-" . $message_id);
    }
    if ($dbmessage == null) {
        $dbmessage = $PHORUM['DB']->get_message($message_id);
        if ($PHORUM['cache_messages']) {
            phorum_api_cache_put('message', $PHORUM["forum_id"] . "-" . $message_id, $dbmessage);
        }
    }
    if (!$dbmessage) {
        phorum_api_redirect(PHORUM_LIST_URL);
    }
}
// Set message data for replying to posts.
if ($mode == "reply" || $mode == "quote") {
    // Set thread and parent information.
    $message["parent_id"] = $dbmessage["message_id"];
    $message["thread"] = $dbmessage["thread"];
    // Create Re: subject prefix.
    if (substr($dbmessage["subject"], 0, 4) != "Re: ") {
        $dbmessage["subject"] = "Re: " . $dbmessage["subject"];
    }
Beispiel #3
0
function phorum_write_language_file($lang, $CURRENT)
{
    // Sort array keys.
    ksort($CURRENT['DATA']['LANG']);
    ksort($CURRENT['STORE']['DEPRECATED']);
    $langfile = "<?php\n" . "\n" . $CURRENT['STORE']['keep_comment'] . "\n" . "\n" . "// ============================================================\n" . "// General settings\n" . "// ============================================================\n" . "\n" . "// The language name as it is presented in the interface.\n" . "\$language = " . urldecode($CURRENT['STORE']['language']) . ";\n" . "\n" . "// Uncomment this to hide this language from the user-select-box.\n" . ($CURRENT['STORE']['language_hide'] ? '' : '//') . "\$language_hide = 1;\n" . "\n" . "// Date formatting. Check the PHP-docs for the syntax of these\n" . "// entries (http://www.php.net/strftime). One tip: do not use\n" . "// %T for showing the time zone, as users can change their time zone.\n" . "\$PHORUM['long_date_time'] = " . urldecode($CURRENT['long_date_time']) . ";\n" . "\$PHORUM['short_date_time'] = " . urldecode($CURRENT['short_date_time']) . ";\n" . "\$PHORUM['long_date'] = " . urldecode($CURRENT['long_date']) . ";\n" . "\$PHORUM['short_date'] = " . urldecode($CURRENT['short_date']) . ";\n" . "\n" . "// The locale setting for enabling localized times/dates. Take a look\n" . "// at http://www.w3.org/WAI/ER/IG/ert/iso639.htm for the needed string.\n" . "\$PHORUM['locale'] = " . urldecode($CURRENT['locale']) . ";\n" . "\n" . "// Numeric separators used to format numbers.\n" . "\$PHORUM['thous_sep'] = " . urldecode($CURRENT['thous_sep']) . ";\n" . "\$PHORUM['dec_sep'] = " . urldecode($CURRENT['dec_sep']) . ";\n" . "\n" . "// The charset to use for displaying special characters.\n" . "\$PHORUM['DATA']['CHARSET'] = " . urldecode($CURRENT['DATA']['CHARSET']) . ";\n" . "\n" . "// The charset to use for htmlspecialchars() calls. PHP does\n" . "// not implement all available charsets, which might result in\n" . "// warning messages if an unsupported charset is used.\n" . "//\n" . "// See http://www.php.net/htmlspecialchars for info on charset\n" . "// compatibility. If the charset that you specified above is\n" . "// compatible with htmlspecialchars(), then you can leave this\n" . "// variable empty. Otherwise, specify a compatible character\n" . "// set (ISO-8859-1 is usually a good choice for this).\n" . "\$PHORUM['DATA']['HCHARSET'] = " . urldecode($CURRENT['DATA']['HCHARSET']) . ";\n" . "\n" . "// The encoding used for outgoing mail messages.\n" . "\$PHORUM['DATA']['MAILENCODING'] = " . urldecode($CURRENT['DATA']['MAILENCODING']) . ";\n" . "\n" . "// Some languages need additional meta tags to set encoding, etc.\n" . "\$PHORUM['DATA']['LANG_META'] = " . urldecode($CURRENT['DATA']['LANG_META']) . ";\n" . "\n" . "// ============================================================\n" . "// Language translation strings\n" . "// ============================================================\n" . "\n" . "\$PHORUM['DATA']['LANG'] = array(\n";
    // Add active language data to the array.
    foreach ($CURRENT['DATA']['LANG'] as $key => $val) {
        if ($key == 'TIME') {
            continue;
        }
        if (isset($CURRENT['STORE']['DEPRECATED'][$key])) {
            continue;
        }
        $langfile .= "    '{$key}' => " . urldecode($val) . ",\n";
    }
    // Add deprecated language data to the array.
    if (count($CURRENT['STORE']['DEPRECATED'])) {
        $langfile .= "\n" . "    // ============================================================\n" . "    // DEPRECATED:\n" . "    // These are all language strings which are not used anymore.\n" . "    // You might want to keep them to make this language file work\n" . "    // for versions of Phorum prior to version " . PHORUM . "\n" . "    // ============================================================\n" . "\n";
        foreach ($CURRENT['STORE']['DEPRECATED'] as $key => $dummy) {
            $langfile .= "    '{$key}' => " . urldecode($CURRENT['DATA']['LANG'][$key]) . ",\n";
        }
    }
    $langfile .= ");\n" . "\n" . "// ============================================================\n" . "// Timezone description strings\n" . "// ============================================================\n" . "\n" . "\$PHORUM['DATA']['LANG']['TIME'] = array(\n";
    foreach ($CURRENT['DATA']['LANG']['TIME'] as $key => $val) {
        $pre = sprintf("    %6s", "'{$key}'");
        $langfile .= "{$pre} => " . urldecode($val) . ",\n";
    }
    $langfile .= ");\n" . "\n" . "?>\n";
    phorum_api_cache_put('updated_language', $lang, $langfile);
}
Beispiel #4
0
/**
 * Retrieve newflags data for a forum for the active Phorum user.
 *
 * This is mainly an internal helper function, which normally is
 * called from other Phorum core code. There should be no need for
 * you to call it from other code.
 *
 * @param mixed $forum
 *     Either a forum_id or a forum data array, containing at least the fields
 *     forum_id and cache_version.
 *
 * @return mixed
 *     The newflags data array for the forum or NULL if no newflags
 *     are available for that forum.
 */
function phorum_api_newflags_by_forum($forum)
{
    global $PHORUM;
    // No newflags for anonymous users.
    if (!$PHORUM['user']['user_id']) {
        return NULL;
    }
    // If a forum_id was provided as the argument, then load the forum info.
    if (!is_array($forum)) {
        settype($forum, 'int');
        $forums = $PHORUM['DB']->get_forums($forum);
        if (empty($forums)) {
            trigger_error('phorum_api_newflags_by_forum(): unknown forum_id ' . $forum);
        }
        $forum = $forums[$forum];
    }
    // Check the input data.
    if (!is_array($forum) || !isset($forum['forum_id']) || !isset($forum['cache_version'])) {
        trigger_error('phorum_api_newflags_by_forum(): illegal argument; no forum info ' . 'or either one of "forum_id" or "cache_version" is ' . 'missing in the data.');
        return NULL;
    }
    $forum_id = (int) $forum['forum_id'];
    $cache_version = $forum['cache_version'];
    // Initialize call time newflags info cache.
    if (!isset($PHORUM['user']['newflags'])) {
        $PHORUM['user']['newflags'] = array();
    }
    // First, try to retrieve a cached version of the newflags.
    if (!isset($PHORUM['user']['newflags'][$forum_id])) {
        $PHORUM['user']['newflags'][$forum_id] = NULL;
        if ($PHORUM['cache_newflags']) {
            $cachekey = $forum_id . '-' . $PHORUM['user']['user_id'];
            $PHORUM['user']['newflags'][$forum_id] = phorum_api_cache_get('newflags', $cachekey, $cache_version);
        }
    }
    // No cached data found? Then retrieve the newflags from the database.
    if ($PHORUM['user']['newflags'][$forum_id] === NULL) {
        $PHORUM['user']['newflags'][$forum_id] = $PHORUM['DB']->newflag_get_flags($forum_id);
        if ($PHORUM['cache_newflags']) {
            phorum_api_cache_put('newflags', $cachekey, $PHORUM['user']['newflags'][$forum_id], 86400, $cache_version);
        }
    }
    return $PHORUM['user']['newflags'][$forum_id];
}
Beispiel #5
0
     *     The filter hook will not be run for every request to
     *     css.php, but only in case the CSS code has
     *     to be refreshed.
     *
     * [input]
     *     The generated CSS code.
     *
     * [output]
     *     The filtered CSS code.
     */
    if (isset($PHORUM['hooks']['css_filter'])) {
        $content = phorum_api_hook('css_filter', $content);
    }
    if (!empty($PHORUM['cache_css'])) {
        $cache_time = time();
        phorum_api_cache_put('css', $cache_key, array($cache_time, $content), 86400);
    }
}
// Find the modification time for the cache file.
$last_modified = $cache_time;
// Check if a If-Modified-Since header is in the request. If yes, then
// check if the CSS code has changed, based on the filemtime() data from
// above. If nothing changed, then we return a 304 header, to tell the
// browser to use the cached data.
phorum_api_output_last_modify_time($last_modified);
// Send the CSS to the browser.
header("Content-Type: text/css");
echo $content;
// Exit here explicitly for not giving back control to portable and
// embedded Phorum setups.
exit(0);
Beispiel #6
0
/**
 * Collect the data that is used for the feed and pass this information
 * on to the requested output adapter.
 *
 * @param string $adapter
 *     The output adapter to use. The adapters that are available are:
 *     - rss
 *     - atom
 *     - html
 *     - js
 *
 * @param integer $source_type
 *     The type of source. This is one of:
 *     - {@link PHORUM_FEED_VROOT}
 *     - {@link PHORUM_FEED_FORUM}
 *     - {@link PHORUM_FEED_THREAD}
 *
 * @param integer $id
 *     This parameter has a different meaning for each $source_type:
 *     - For {@link PHORUM_FEED_VROOT}: the forum_id of the (v)root.
 *     - For {@link PHORUM_FEED_FORUM}: the forum_id of the forum.
 *     - For {@link PHORUM_FEED_THREAD}: the message_id of the thread.
 *
 * @param integer $count
 *     The number of messages to include in the feed.
 *
 * @param boolean $replies
 *     TRUE to include reply messages in the feed, FALSE otherwise.
 *     This parameter is forced to TRUE for {@link PHORUM_FEED_THREAD}.
 */
function phorum_api_feed($adapter, $source_type, $id, $count, $replies)
{
    global $PHORUM;
    settype($id, 'int');
    settype($count, 'int');
    settype($source_type, 'int');
    $replies = $replies ? 1 : 0;
    $adapter = basename($adapter);
    if (!preg_match('/^[a-z][\\w_]*$/', $adapter)) {
        trigger_error('phorum_api_feed(): Illegal feed adapter name ' . '"' . htmlspecialchars($adapter) . '" used', E_USER_ERROR);
    }
    if (!file_exists(PHORUM_PATH . '/include/api/feed/' . $adapter . '.php')) {
        trigger_error('phorum_api_feed(): Unknown feed adapter ' . '"' . htmlspecialchars($adapter) . '" used', E_USER_ERROR);
    }
    // ----------------------------------------------------------------------
    // Prepare the data for the requested feed type
    // ----------------------------------------------------------------------
    // Prepare data for handling a vroot feed.
    if ($source_type === PHORUM_FEED_VROOT) {
        $forums = phorum_api_forums_by_vroot($id);
        $thread_id = NULL;
        $forum_ids = array_keys($forums);
        $cache_part = implode(',', array_keys($forums));
    } elseif ($source_type === PHORUM_FEED_FORUM) {
        if ($PHORUM['forum_id'] == $id) {
            $forum = $PHORUM;
            // contains all required data already
        } else {
            $forum = phorum_api_forums_by_forum_id($id);
            if (empty($forum)) {
                trigger_error("phorum_api_feed(): Forum for forum_id \"{$id}\" not found.", E_USER_ERROR);
            }
        }
        $forums = array($id => $forum);
        $thread_id = NULL;
        $forum_ids = array_keys($forums);
        $cache_part = $forum['forum_id'];
    } elseif ($source_type === PHORUM_FEED_THREAD) {
        // When a feed for a thread is requested, we always include the
        // reply messages for that thread in the feed.
        $replies = 1;
        // Retrieve the thread starter message.
        $thread = $PHORUM['DB']->get_message($id);
        if (empty($thread)) {
            trigger_error("phorum_api_feed(): Thread for message_id \"{$id}\" not found.", E_USER_ERROR);
        }
        if (!empty($thread['parent_id'])) {
            trigger_error("phorum_api_feed(): Message for message_id \"{$id}\" is not " . "the start message of a thread.", E_USER_ERROR);
        }
        $thread_id = $id;
        $forum_ids = NULL;
        $cache_part = $id;
    } else {
        trigger_error("phorum_api_feed(): Illegal value \"{$source_type}\" used " . "for parameter \$source_type.", E_USER_ERROR);
    }
    // ----------------------------------------------------------------------
    // Retrieve the data for the requested feed
    // ----------------------------------------------------------------------
    $data = NULL;
    $content_type = NULL;
    // Try to retrieve the data from cache.
    if (!empty($PHORUM['cache_rss'])) {
        // Build the cache key that uniquely identifies the requested feed.
        $cache_key = $PHORUM['user']['user_id'] . '|' . $adapter . '|' . $source_type . '|' . $cache_part . '|' . $replies . '|' . $count;
        $cache = phorum_api_cache_get('feed', $cache_key);
        if (!empty($cache)) {
            list($data, $content_type) = $cache;
        }
    }
    // No data from cache. Load the recent threads / messages
    // directly from the database and generate the feed data.
    if (empty($data)) {
        // ----------------------------------------------------------------
        // Retrieve the messages to show
        // ----------------------------------------------------------------
        $messages = $PHORUM['DB']->get_recent_messages($count, 0, $forum_ids, $thread_id, $replies ? LIST_RECENT_MESSAGES : LIST_RECENT_THREADS);
        // Temporarily, remove the user list from the messages array.
        $users = $messages['users'];
        unset($messages['users']);
        // Apply the "read" hook(s) to the messages.
        if (isset($PHORUM['hooks']['read'])) {
            $messages = phorum_api_hook('read', $messages);
        }
        // Apply formatting to the messages.
        $messages = phorum_api_format_messages($messages);
        // Put the array of users back in the messages array.
        $messages['users'] = $users;
        // ----------------------------------------------------------------
        // Setup the feed URL, title and description based on
        // the type of feed that was requested.
        // ----------------------------------------------------------------
        if ($source_type === PHORUM_FEED_VROOT) {
            $feed_url = phorum_api_url(PHORUM_INDEX_URL);
            $feed_title = strip_tags($PHORUM['DATA']['TITLE']);
            $feed_description = !empty($PHORUM['description']) ? $PHORUM['description'] : '';
        }
        if ($source_type === PHORUM_FEED_FORUM) {
            $feed_url = phorum_api_url(PHORUM_LIST_URL);
            /**
             * @todo The formatting of the forum base feed data should
             *       be based on the data in $forum and not the common.php
             *       $PHORUM contents. This is left as is for now, because
             *       the wrong data will only be shown for threads that
             *       were moved to a different forum.
             */
            $feed_title = strip_tags($PHORUM['DATA']['TITLE'] . ' - ' . $PHORUM['DATA']['NAME']);
            $feed_description = strip_tags($PHORUM['DATA']['DESCRIPTION']);
        }
        if ($source_type === PHORUM_FEED_THREAD) {
            // Retrieve the information for the forum to which the thread
            // belongs. Normally, this should be in $PHORUM already, but
            // let's make sure that the caller is using the correct forum id
            // in the URL here (since the thread might have been moved to
            // a different forum).
            $forum_id = $thread['forum_id'];
            if ($PHORUM['forum_id'] == $forum_id) {
                $forum = $PHORUM;
                // contains all required data already
            } else {
                $forum = phorum_api_forums_by_forum_id($forum_id);
                if (empty($forum)) {
                    trigger_error("phorum_api_feed(): Forum for forum_id \"{$id}\" not found.", E_USER_ERROR);
                }
            }
            $forums = array($forum_id => $forum);
            $feed_url = phorum_api_url(PHORUM_FOREIGN_READ_URL, $thread['forum_id'], $thread_id, $thread_id);
            $feed_title = strip_tags($thread['subject']);
            $feed_description = strip_tags($thread['body']);
        }
        // ----------------------------------------------------------------
        // All data has been collected. Now the feed is generated.
        // ----------------------------------------------------------------
        require_once PHORUM_PATH . '/include/api/feed/' . $adapter . '.php';
        $adapter_function = 'phorum_api_feed_' . $adapter;
        list($data, $content_type) = $adapter_function($messages, $forums, $feed_url, $feed_title, $feed_description, $replies);
        // Store the feed data in the cache for future use.
        if (!empty($PHORUM['cache_rss'])) {
            phorum_api_cache_put('feed', $cache_key, array($data, $content_type, 600));
        }
    }
    // ----------------------------------------------------------------------
    // Output the feed data to the client
    // ----------------------------------------------------------------------
    header("Content-Type: {$content_type}");
    print $data;
    /*
     * [hook]
     *     feed_sent
     *
     * [description]
     *     This hook is called whenever the feed has been sent to the client
     *     (regardless of the cache setting). This can be used to add internal
     *     server side tracking code.
     *
     * [category]
     *     Feed
     *
     * [when]
     *     Feed sent to the client
     *
     * [input]
     *     None
     *
     * [output]
     *     None
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_feed_after () 
     *     {
     *       # E.g. do server side tracking
     *       @file_get_contents('your tracking service');
     *     }
     *     </hookcode>
     */
    phorum_api_hook('feed_sent');
    // Exit explicitly here, for not giving back control to portable and
    // embedded Phorum setups.
    exit(0);
}
Beispiel #7
0
/**
 * @deprecated Replaced by {@link phorum_api_cache_put()}.
 */
function phorum_cache_put($type, $key, $data, $ttl = PHORUM_CACHE_DEFAULT_TTL, $version = NULL)
{
    return phorum_api_cache_put($type, $key, $data, $ttl, $version);
}
Beispiel #8
0
    $data['datestamp'] = phorum_api_format_date($PHORUM["short_date_time"], $data["modifystamp"]);
    $data['raw_lastpost'] = $data['modifystamp'];
    $data['lastpost'] = phorum_api_format_date($PHORUM["short_date_time"], $data["modifystamp"]);
    $data["URL"]["READ"] = phorum_api_url(PHORUM_FOREIGN_READ_URL, $data["forum_id"], $data["thread"]);
    $data["URL"]["NEWPOST"] = phorum_api_url(PHORUM_FOREIGN_READ_URL, $data["forum_id"], $data["thread"], "gotonewpost");
    // Check if there are new messages for the current thread.
    if (!isset($PHORUM['user']['newinfo'][$data["forum_id"]])) {
        $PHORUM['user']['newinfo'][$data["forum_id"]] = null;
        if ($PHORUM['cache_newflags']) {
            $newflagkey = $data["forum_id"] . "-" . $PHORUM['user']['user_id'];
            $PHORUM['user']['newinfo'][$data["forum_id"]] = phorum_api_cache_get('newflags', $newflagkey, $forums[$data["forum_id"]]['cache_version']);
        }
        if ($PHORUM['user']['newinfo'][$data["forum_id"]] == null) {
            $PHORUM['user']['newinfo'][$data["forum_id"]] = $PHORUM['DB']->newflag_get_flags($data["forum_id"]);
            if ($PHORUM['cache_newflags']) {
                phorum_api_cache_put('newflags', $newflagkey, $PHORUM['user']['newinfo'][$data["forum_id"]], 86400, $forums[$data["forum_id"]]['cache_version']);
            }
        }
    }
    $new = array();
    foreach ($data["meta"]["message_ids"] as $mid) {
        if (!isset($PHORUM['user']['newinfo'][$data["forum_id"]][$mid]) && $mid > $PHORUM['user']['newinfo'][$data["forum_id"]]['min_id']) {
            $new[] = $mid;
        }
    }
    if (count($new)) {
        $data["new"] = $PHORUM["DATA"]["LANG"]["newflag"];
    }
    $subscr_array_final[] = $data;
}
// Additional formatting for the recent author data.
Beispiel #9
0
/**
 * Check the cache functionality
 *
 * @return NULL|string
 *     This function returns NULL if no problems are found or a string
 *     describing the problem when one is found.
 */
function phorum_api_cache_check()
{
    $retval = phorum_api_cache_get('check', 'connection');
    // only retry the cache check if last check was more than 1 hour ago
    $data = time();
    if ($retval === NULL || $retval < $data - 3600) {
        phorum_api_cache_put('check', 'connection', $data, 7200);
        $gotten_data = phorum_api_cache_get('check', 'connection');
        if ($gotten_data !== $data) {
            return "Data that was put in the file cache could not be " . "retrieved successfully afterwards.";
        }
    }
    return NULL;
}
Beispiel #10
0
/**
 * Update the meta data for a thread.
 *
 * The fields that are put in the thread starter data are:
 *
 * - threadviewcount: the sum of all view counts per message
 * - thread_count: the number of messages in the thread
 * - message_ids: an array of message_ids for all visible messages in a thread
 * - message_ids_moderator: an array of all message_ids in a thread
 * - modifystamp: time when the last visible message was posted in a thread
 * - recent_message_id: message_id of the most recent message
 * - recent_user_id: user_id of the author of the most recent message
 * - recent_author: the name of the author of the most recent message
 *
 * @param integer $thread_id
 *     The message_id of the thread starter message.
 */
function phorum_api_thread_update_metadata($thread_id)
{
    global $PHORUM;
    // Retrieve all messages for the thread from the database.
    $messages = $PHORUM['DB']->get_messages($thread_id, 0, 1, 1, FALSE);
    // We do not need the returned user info.
    unset($messages['users']);
    // Retrieve the thread starter message. If the starter message does
    // not exist, then we go back empty handed. This could happen when
    // a full thread is deleted from the database, in which case the
    // starter message is gone as well (when only one or more replies
    // are deleted, then this function is called to update the thread's
    // meta data).
    if (!isset($messages[$thread_id])) {
        return;
    }
    $thread = $messages[$thread_id];
    // Initialize the data that we will save at the end of this function.
    // This array will be filled during this function. The meta data is
    // added already, because we have to merge new data with the
    // existing data.
    $save = array('meta' => $thread['meta']);
    // For cleaning up pre-5.2 data. The recent_post meta data field
    // contents were moved to real fields in the messages table.
    unset($save['meta']['recent_post']);
    // Compute the threadviewcount, based on the individual message views.
    // This can be especially useful for updating the view counters after
    // enabling the view_count_per_thread option.
    // Additionally create a list of messages that are visible. These are
    // the messages that normal users can see. Admins and moderators
    // will always see all messages for a thread.
    $threadviewcount = 0;
    $visible_messages = array();
    foreach ($messages as $id => $message) {
        $threadviewcount += $message['viewcount'];
        if ($message['status'] > 0) {
            $visible_messages[$message['message_id']] = $message;
        }
    }
    $save['threadviewcount'] = $threadviewcount;
    // Determine the thread count.
    $thread_count = count($visible_messages);
    $save['thread_count'] = $thread_count;
    // Create a list of message_ids.
    $message_ids = array_keys($visible_messages);
    sort($message_ids, SORT_NUMERIC);
    $save['meta']['message_ids'] = $message_ids;
    // Create a list of message_ids for admin and moderator users.
    $message_ids_moderator = array_keys($messages);
    sort($message_ids_moderator, SORT_NUMERIC);
    $save['meta']['message_ids_moderator'] = $message_ids_moderator;
    // Find the most recent_message in the thread and keep track
    // of the time when that message was posted.
    $recent_message_id = 0;
    $modifystamp = $thread['datestamp'];
    foreach ($visible_messages as $message_id => $message) {
        if ($message['datestamp'] > $modifystamp || $message['datestamp'] == $modifystamp && $message_id > $recent_message_id) {
            $modifystamp = $message['datestamp'];
            $recent_message_id = $message_id;
        }
    }
    // Update the thread's modifystamp according to the most recent
    // message's post time.
    $save['modifystamp'] = $modifystamp;
    // Retrieve the data for the most recent message.
    // If we have no recent message (happens if all messages are hidden)
    // then we take the thread starter message as the most recent message.
    $recent_message = $recent_message_id ? $visible_messages[$recent_message_id] : $thread;
    // Update the thread's recent message data.
    $save['recent_message_id'] = $recent_message['message_id'];
    $save['recent_user_id'] = $recent_message['user_id'];
    $save['recent_author'] = $recent_message['author'];
    if (!empty($PHORUM['cache_messages'])) {
        // Cache the message index.
        // We can simply store the data here again. There is no need to
        // invalidate the cache, because this function is the only function
        // that fills the message index cache and it is called in any place
        // where we change something that is related to the thread.
        phorum_api_cache_put('message_index', $thread['forum_id'] . "-{$thread_id}-1", $message_ids);
        phorum_api_cache_put('message_index', $thread['forum_id'] . "-{$thread_id}-0", $message_ids_moderator);
        // We do invalidate the thread starter message though, because
        // filling the cache will be done from another part of the system.
        phorum_api_cache_remove('message', $thread['forum_id'] . '-' . $thread_id);
    }
    $PHORUM['DB']->update_message($thread_id, $save);
}
Beispiel #11
0
                    }
                }
            }
            if (isset($row['recent_message_id'])) {
                // should always be true
                // building the recent message link
                if ($pages > 1) {
                    $rows[$key]["URL"]["LAST_POST"] = str_replace(array('%thread_id%', '%message_id%', '%page_num%'), array($row['thread'], $row['recent_message_id'], $pages), $recent_page_url_template);
                } else {
                    $rows[$key]["URL"]["LAST_POST"] = str_replace(array('%thread_id%', '%message_id%'), array($row['thread'], $row['recent_message_id']), $recent_url_template);
                }
            }
        }
    }
    if ($PHORUM['cache_messages'] && (!$PHORUM['DATA']['LOGGEDIN'] || $PHORUM['use_cookies']) && !$PHORUM['count_views']) {
        phorum_api_cache_put('message_list', $cache_key, $rows);
    }
}
if ($PHORUM["count_views"] == 2) {
    // viewcount as column
    $PHORUM["DATA"]["VIEWCOUNT_COLUMN"] = true;
}
if ($PHORUM['DATA']['LOGGEDIN']) {
    // used later if user is moderator
    if ($PHORUM["DATA"]["MODERATOR"]) {
        $delete_url_template = phorum_api_url(PHORUM_MODERATION_URL, PHORUM_DELETE_MESSAGE, '%message_id%', 'ref_message_id=%message_id%');
        $delete_thread_url_template = phorum_api_url(PHORUM_MODERATION_URL, PHORUM_DELETE_TREE, '%message_id%', 'ref_message_id=%message_id%');
        $move_thread_url_template = phorum_api_url(PHORUM_MODERATION_URL, PHORUM_MOVE_THREAD, '%message_id%', 'ref_message_id=%message_id%');
        $merge_thread_url_template = phorum_api_url(PHORUM_MODERATION_URL, PHORUM_MERGE_THREAD, '%message_id%', 'ref_message_id=%message_id%');
        if (isset($row['pages_moderators'])) {
            $recent_page_url_template = phorum_api_url(PHORUM_READ_URL, '%thread_id%', '%message_id%', 'ref_message_id=%message_id%', 'page=%page_num%');
Beispiel #12
0
/**
 * Retrieve data for Phorum users.
 *
 * @param mixed $user_id
 *     Either a single user_id or an array of user_ids.
 *
 * @param boolean $detailed
 *     If this parameter is TRUE (default is FALSE), then the user's
 *     groups and permissions are included in the user data.
 *
 * @param boolean $use_write_server
 *     This parameter is for internal use only. It is used to flag that
 *     the database layer has to run the query against the master database
 *     server (known as the "write server"; only applicable if the database
 *     system is setup as a replicated master/slave environment). When you
 *     are using this API call in your own code, then you most probably do
 *     not need to use this parameter.
 *
 * @param boolean $raw_data
 *     This parameter is for internal use only.
 *     When this parameter is TRUE (default is FALSE), then custom fields
 *     that are configured with html_disabled will not be HTML encoded in
 *     the return data.
 *
 * @return mixed
 *     If the $user_id parameter is a single user_id, then either an array
 *     containing user data is returned or NULL if the user was not found.
 *     If the $user_id parameter is an array of user_ids, then an array
 *     of user data arrays is returned, indexed by the user_id.
 *     Users for user_ids that are not found are not included in the
 *     returned array.
 */
function phorum_api_user_get($user_id, $detailed = FALSE, $use_write_server = FALSE, $raw_data = FALSE)
{
    global $PHORUM;
    if (!is_array($user_id)) {
        $user_ids = array($user_id);
    } else {
        $user_ids = $user_id;
    }
    // Prepare the return data array. For each requested user_id,
    // a slot is prepared in this array. Also, turn the user id array
    // into an array that has the user_id as both the key and value.
    $users = array();
    $new_user_ids = array();
    foreach ($user_ids as $id) {
        $users[$id] = NULL;
        $new_user_ids[$id] = $id;
    }
    $user_ids = $new_user_ids;
    // First, try to retrieve user data from the user cache,
    // if user caching is enabled.
    if (!empty($PHORUM['cache_users'])) {
        $cached_users = phorum_api_cache_get('user', $user_ids);
        if (is_array($cached_users)) {
            foreach ($cached_users as $id => $user) {
                $users[$user['user_id']] = $user;
                unset($user_ids[$id]);
            }
            // We need to retrieve the data for some dynamic fields
            // from the database.
            $dynamic_data = $PHORUM['DB']->user_get_fields(array_keys($cached_users), array('date_last_active', 'last_active_forum', 'posts'));
            // Store the results in the users array.
            foreach ($dynamic_data as $d_user_id => $data) {
                $users[$d_user_id] = array_merge($users[$d_user_id], $data);
            }
        }
    }
    // Retrieve user data for the users for which no data was
    // retrieved from the cache.
    if (count($user_ids)) {
        $db_users = $PHORUM['DB']->user_get($user_ids, $detailed, $use_write_server);
        // Retrieve and apply the custom fields for users.
        if (!empty($PHORUM['CUSTOM_FIELDS'][PHORUM_CUSTOM_FIELD_USER])) {
            $db_users = phorum_api_custom_field_apply(PHORUM_CUSTOM_FIELD_USER, $db_users, $raw_data);
        }
        foreach ($db_users as $id => $user) {
            // Merge the group and forum permissions into a final
            // permission value per forum. Forum permissions that are
            // assigned to a user directly override any group based
            // permission.
            if (!$user['admin']) {
                if (!empty($user['group_permissions'])) {
                    foreach ($user['group_permissions'] as $fid => $perm) {
                        if (!isset($user['permissions'][$fid])) {
                            $user['permissions'][$fid] = $perm;
                        } else {
                            $user['permissions'][$fid] |= $perm;
                        }
                    }
                }
                if (!empty($user['forum_permissions'])) {
                    foreach ($user['forum_permissions'] as $fid => $perm) {
                        $user['permissions'][$fid] = $perm;
                    }
                }
            }
            // If detailed information was requested, we store the data in
            // the cache. For non-detailed information, we do not cache the
            // data, because there is not much to gain there by caching.
            if ($detailed && !empty($PHORUM['cache_users'])) {
                phorum_api_cache_put('user', $id, $user);
            }
            // Store the results in the users array.
            $users[$id] = $user;
        }
    }
    // Remove the users for which we did not find data from the array.
    foreach ($users as $id => $user) {
        if ($user === NULL) {
            unset($users[$id]);
        }
    }
    /**
     * [hook]
     *     user_get
     *
     * [description]
     *     This hook can be used to handle the data that was retrieved
     *     from the database for a user. Modules can add and modify the
     *     user data.<sbr/>
     *     <sbr/>
     *     In combination with the <hook>user_save</hook> hook, this hook
     *     could also be used to store and retrieve some of the Phorum
     *     user fields in some external system
     *
     * [category]
     *     User data handling
     *
     * [when]
     *     Just after user data has been retrieved from the database.
     *
     * [input]
     *     This hook receives two arguments.<sbr/>
     *     The first argument contains an array of users.
     *     Each item in this array is an array containing data for
     *     a single user, which can be updated.<sbr/>
     *     The second argument contains a boolean that indicates whether
     *     detailed information (i.e. including group info) is retrieved.
     *
     * [output]
     *     The array that was used as the first argument for the hook call,
     *     possibly with some updated users in it.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_user_get($user, $detailed)
     *     {
     *         // Let's asume that our usernames are based on the
     *         // system users on a UNIX system. We could merge some
     *         // info from the password file with the Phorum info here.
     *
     *         // First try to lookup the password file entry.
     *         // Return if this lookup fails.
     *         $pw = posix_getpwnam($user['username']);
     *         if (empty($pw)) return $user;
     *
     *         // On a lot of systems, the "gecos" field contains
     *         // the real name for the user.
     *         $user['real_name'] = $pw["gecos"] != ''
     *                            ? $pw["gecos"]
     *                            : $user["real_name"];
     *
     *         // If a custom profile field "shell" was created, then
     *         // we could also put the user's shell in the data.
     *         $user['shell'] = $pw['shell'];
     *
     *         return $user;
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM['hooks']['user_get'])) {
        $users = phorum_api_hook('user_get', $users, $detailed);
    }
    // A backward compatibility hook. The advised hook for modifying
    // loaded user data is "user_get" from above.
    if (isset($PHORUM["hooks"]["read_user_info"])) {
        $users = phorum_api_hook("read_user_info", $users);
    }
    // Return the results.
    if (is_array($user_id)) {
        return $users;
    } else {
        return isset($users[$user_id]) ? $users[$user_id] : NULL;
    }
}
Beispiel #13
0
/**
 * Retrieve all or a specific ban list for the current forum.
 *
 * The id of the current forum is taken from $PHORUM['forum_id'].
 *
 * @param integer|NULL $type
 *     The type of ban list to return. If $type is NULL (default), then all
 *     ban lists are returned. The available types are identified by
 *     the following constants:
 *     - {@link PHORUM_BAD_IPS}
 *     - {@link PHORUM_BAD_NAMES}
 *     - {@link PHORUM_BAD_EMAILS}
 *     - {@link PHORUM_BAD_WORDS}
 *     - {@link PHORUM_BAD_USERID}
 *     - {@link PHORUM_BAD_SPAM_WORDS}
 *
 * @return array
 *     The array of ban list items.
 */
function phorum_api_ban_list($type = NULL)
{
    global $PHORUM;
    static $loaded_banlists = array();
    // Check if we have the banlists for the current forum in
    // our request cache.
    if (!isset($loaded_banlists[$PHORUM['forum_id']])) {
        // Try to retrieve the ban lists from cache.
        $banlists = NULL;
        if (!empty($PHORUM['cache_banlists']) && !empty($PHORUM['banlist_version'])) {
            $banlists = phorum_api_cache_get('banlist', $PHORUM['forum_id'], $PHORUM['banlist_version']);
        }
        // No ban lists available in the cache.
        if ($banlists === NULL) {
            // Retrieve them from the database.
            $banlists = $PHORUM['DB']->get_banlists();
            // Nothing in the db either? Then use an empty array.
            if (empty($banlists)) {
                $banlists = array();
            }
            // Make sure that we have a ban list array for each type.
            foreach (array(PHORUM_BAD_IPS, PHORUM_BAD_NAMES, PHORUM_BAD_EMAILS, PHORUM_BAD_WORDS, PHORUM_BAD_USERID, PHORUM_BAD_SPAM_WORDS) as $t) {
                if (empty($banlists[$t])) {
                    $banlists[$t] = array();
                }
            }
            // Cache the ban lists.
            if (!empty($PHORUM['cache_banlists']) && !empty($PHORUM['banlist_version'])) {
                phorum_api_cache_put('banlist', $PHORUM['forum_id'], $banlists, 7200, $PHORUM['banlist_version']);
            }
        }
        // Cache the ban list during the request.
        $loaded_banlists[$PHORUM['forum_id']] = $banlists;
    }
    // Return a single ban list.
    if ($type !== NULL) {
        if (empty($loaded_banlists[$PHORUM['forum_id']][$type])) {
            return array();
        } else {
            return $loaded_banlists[$PHORUM['forum_id']][$type];
        }
    }
    // Return all ban lists.
    return $loaded_banlists[$PHORUM['forum_id']];
}
Beispiel #14
0
/**
 * Check the cache functionality
 *
 * @return NULL|string
 *     This function returns NULL if no problems are found or a string
 *     describing the problem when one is found.
 */
function phorum_api_cache_check()
{
    if (!function_exists('apc_fetch')) {
        return "The function apc_fetch() is not available. " . "The PHP installation does not have the APC module enabled.";
    }
    $retval = phorum_api_cache_get('check', 'connection');
    // only retry the cache check if last check was more than 1 hour ago
    $data = time();
    if ($retval === NULL || $retval < $data - 3600) {
        phorum_api_cache_put('check', 'connection', $data, 7200);
        $gotten_data = phorum_api_cache_get('check', 'connection');
        if ($gotten_data !== $data) {
            return "Data that was put in the APC cache could not be " . "retrieved successfully afterwards.";
        }
    }
    return NULL;
}
Beispiel #15
0
function phorum_setup_announcements()
{
    global $PHORUM;
    // This variable will be used to store the formatted announcements.
    $PHORUM['DATA']['MOD_ANNOUNCEMENTS'] = '';
    // Check if we are on a page on which the announcements have to be shown.
    if (phorum_page == 'index') {
        // Hide the announcements, unless enabled for "index".
        $hide = empty($PHORUM["mod_announcements"]["pages"]["index"]);
        // Show announcements for the root page if "home" is enabled.
        if ($PHORUM['vroot'] == $PHORUM['forum_id'] && !empty($PHORUM["mod_announcements"]["pages"]["home"])) {
            $hide = FALSE;
        }
        if ($hide) {
            return;
        }
    } else {
        if (empty($PHORUM["mod_announcements"]["pages"][phorum_page])) {
            return;
        }
    }
    // Check if we are on a page on which the announcements have to be shown.
    if (!empty($PHORUM["mod_announcements"]["pages"]["home"])) {
        if ($PHORUM['vroot'] != $PHORUM['forum_id'] || phorum_page != 'index') {
            return;
        }
    } else {
        if (empty($PHORUM["mod_announcements"]["pages"][phorum_page])) {
            return;
        }
    }
    // Check if we need to show announcements.
    $ann_forum_id = NULL;
    // Inside a vroot, where we have a vroot configuration for the forum
    // to use for announcements and the current forum is not that
    // announcement forum.
    if ($PHORUM['vroot'] > 0 && !empty($PHORUM["mod_announcements"]["vroot"][$PHORUM['vroot']]) && $PHORUM["forum_id"] != $PHORUM["mod_announcements"]["vroot"][$PHORUM['vroot']]) {
        $ann_forum_id = $PHORUM["mod_announcements"]["vroot"][$PHORUM['vroot']];
        // Inside the top level folder, where we have a forum that is configured
        // to be used for announcements and the current forum is not that
        // announcement forum.
    } elseif ($PHORUM['vroot'] == 0 && !empty($PHORUM["mod_announcements"]["forum_id"]) && $PHORUM["forum_id"] != $PHORUM["mod_announcements"]["forum_id"]) {
        $ann_forum_id = $PHORUM["mod_announcements"]["forum_id"];
    }
    // If no announcement forum_id is found, no announcements
    // have to be shown.
    if ($ann_forum_id === NULL) {
        return;
    }
    // Retrieve the last number of posts from the announcement forum.
    $messages = $PHORUM['DB']->get_recent_messages($PHORUM["mod_announcements"]["number_to_show"], 0, $ann_forum_id, 0, true);
    unset($messages["users"]);
    // No announcements to show? Then we are done.
    if (count($messages) == 0) {
        return;
    }
    // Read the newflags information for authenticated users.
    $newinfo = NULL;
    if ($PHORUM["DATA"]["LOGGEDIN"]) {
        $newflagkey = $ann_forum_id . "-" . $PHORUM['user']['user_id'];
        if ($PHORUM['cache_newflags']) {
            $newinfo = phorum_api_cache_get('newflags', $newflagkey, $PHORUM['cache_version']);
        }
        if ($newinfo == NULL) {
            $newinfo = $PHORUM['DB']->newflag_get_flags($ann_forum_id);
            if ($PHORUM['cache_newflags']) {
                phorum_api_cache_put('newflags', $newflagkey, $newinfo, 86400, $PHORUM['cache_version']);
            }
        }
    }
    require_once PHORUM_PATH . '/include/api/format/messages.php';
    // Process the announcements.
    foreach ($messages as $message) {
        // Skip this message if it's older than the number of days that was
        // configured in the settings screen.
        if (!empty($PHORUM["mod_announcements"]["days_to_show"]) && $message["datestamp"] < time() - $PHORUM["mod_announcements"]["days_to_show"] * 86400) {
            continue;
        }
        // Check if there are new messages in the thread.
        if (isset($newinfo)) {
            $new = 0;
            foreach ($message["meta"]["message_ids"] as $id) {
                if (!isset($newinfo[$id]) && $id > $newinfo['min_id']) {
                    $new = 1;
                    break;
                }
            }
            // There are new messages. Setup the template data for showing
            // a new flag.
            if ($new) {
                $message["new"] = $new ? $PHORUM["DATA"]["LANG"]["newflag"] : NULL;
                $message["URL"]["NEWPOST"] = phorum_api_url(PHORUM_FOREIGN_READ_URL, $message["forum_id"], $message["thread"], "gotonewpost");
            } elseif ($PHORUM["mod_announcements"]["only_show_unread"]) {
                continue;
            }
        }
        // Setup template data for the message.
        unset($message['body']);
        $message["lastpost"] = phorum_api_format_date($PHORUM["short_date_time"], $message["modifystamp"]);
        $message["raw_datestamp"] = $message["datestamp"];
        $message["datestamp"] = phorum_api_format_date($PHORUM["short_date_time"], $message["datestamp"]);
        $message["URL"]["READ"] = phorum_api_url(PHORUM_FOREIGN_READ_URL, $message["forum_id"], $message["message_id"]);
        $PHORUM["DATA"]["ANNOUNCEMENTS"][] = $message;
    }
    // If all announcements were skipped, then we are done.
    if (!isset($PHORUM["DATA"]["ANNOUNCEMENTS"])) {
        return;
    }
    // format / clean etc. the messages found
    $PHORUM["DATA"]["ANNOUNCEMENTS"] = phorum_api_format_messages($PHORUM["DATA"]["ANNOUNCEMENTS"]);
    // Build the announcements code.
    ob_start();
    include phorum_api_template("announcements::announcements");
    $PHORUM['DATA']['MOD_ANNOUNCEMENTS'] = ob_get_contents();
    ob_end_clean();
}
Beispiel #16
0
            phorum_api_cache_put('message', $PHORUM["forum_id"] . "-" . $message["thread"], $top_parent);
        }
    }
}
// Do permission checks for replying to messages.
if ($mode == "reply") {
    // Find the direct parent for this message.
    if ($message["thread"] != $message["parent_id"]) {
        $parent = null;
        if ($PHORUM['cache_messages']) {
            $parent = phorum_api_cache_get('message', $PHORUM["forum_id"] . "-" . $message["parent_id"]);
        }
        if ($parent == null) {
            $parent = $PHORUM['DB']->get_message($message["parent_id"]);
            if ($PHORUM['cache_messages']) {
                phorum_api_cache_put('message', $PHORUM["forum_id"] . "-" . $message["parent_id"], $parent);
            }
        }
    } else {
        $parent = $top_parent;
    }
    // If this thread is unapproved, then get out.
    $unapproved = empty($top_parent) || empty($parent) || $top_parent["status"] != PHORUM_STATUS_APPROVED || $parent["status"] != PHORUM_STATUS_APPROVED;
    if ($unapproved) {
        // In case we run the editor included in the read page,
        // we should not redirect to the listpage for moderators.
        // Else a moderator can never read an unapproved message.
        if (isset($PHORUM["postingargs"]["as_include"])) {
            if ($PHORUM["DATA"]["MODERATOR"]) {
                $PHORUM["DATA"]["OKMSG"] = $PHORUM["DATA"]["LANG"]["UnapprovedMessage"];
                return;
Beispiel #17
0
/**
 * Check the cache functionality
 *
 * @return NULL|string
 *     This function returns NULL if no problems are found or a string
 *     describing the problem when one is found.
 */
function phorum_api_cache_check()
{
    global $PHORUM;
    if (!function_exists('memcache_connect')) {
        return "The function memcache_connect() is not available. " . "The PHP installation does not have the Memcache " . "PECL module enabled.";
    }
    // Connect to the memcached server. If the connection fails, then
    // destroy the memcache object. In this case, caching will not be
    // used during the remaining of the request. We will not return
    // an error for this case, since this might occur when restarting
    // the memcached server. We don't want to drop nasty error messages
    // on the users of the system in such case.
    if (empty($PHORUM['CACHECONFIG']['server'])) {
        $PHORUM['CACHECONFIG']['server'] = 'localhost';
    }
    $PHORUM['memcache_obj'] = new Memcache();
    if (!@$PHORUM['memcache_obj']->connect($PHORUM['CACHECONFIG']['server'], $PHORUM['CACHECONFIG']['port'])) {
        unset($PHORUM['memcache_obj']);
        return NULL;
    }
    $retval = phorum_api_cache_get('check', 'connection');
    // only retry the cache check if last check was more than 1 hour ago
    $data = time();
    if ($retval === NULL || $retval < $data - 3600) {
        phorum_api_cache_put('check', 'connection', $data, 7200);
        $gotten_data = phorum_api_cache_get('check', 'connection');
        if ($gotten_data !== $data) {
            return "Data that was put in the memcached cache could not be " . "retrieved successfully afterwards.";
        }
    }
    return NULL;
}