Beispiel #1
0
/**
 * Adds the javascript and CSS for the editor tools to the page header.
 * Sets up internal datastructures for the editor tools module.
 * Allows other modules to register their editor tool buttons.
 */
function phorum_mod_editor_tools_common()
{
    global $PHORUM;
    $lang = $PHORUM["DATA"]["LANG"]["mod_editor_tools"];
    // Initialize the tool data array.
    $PHORUM["MOD_EDITOR_TOOLS"] = array("DO_TOOLS" => false, "STARTED" => false, "TOOLS" => array(), "JSLIBS" => array(), "HELP_CHAPTERS" => array(), "TRANSLATIONS" => $lang);
    // Add a help tool. We add it as the first tool, so we can
    // shift it nicely to the right side of the page using CSS float.
    if (!empty($PHORUM["mod_editor_tools"]["enable_help"])) {
        editor_tools_register_tool('help', $lang['help']);
    }
    // Give other modules a chance to setup their plugged in
    // editor tools. This is done through a standard hook call.
    if (isset($PHORUM["hooks"]["editor_tool_plugin"])) {
        phorum_api_hook('editor_tool_plugin');
    }
    // Keep track that the editor tools have been setup. From here
    // on, the API calls for registering tools, javascript libraries
    // help chapters and language strings are no longer allowed.
    $PHORUM["MOD_EDITOR_TOOLS"]["STARTED"] = true;
}
Beispiel #2
0
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_hide_thread($msgthd_id)
 *     {
 *         global $PHORUM;
 *
 *         // Log the hidden thread id
 *         $PHORUM["mod_foo"]["hidden_threads"][] = $msgthd_id;
 *         $PHORUM['DB']->update_settings(array(
 *             "mod_foo" => $PHORUM["mod_foo"]
 *         ));
 *
 *         return $msgthd_id;
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["hide_thread"])) {
    phorum_api_hook("hide_thread", $msgthd_id);
}
// updating the thread-info
phorum_api_thread_update_metadata($old_message['thread']);
// updating the forum-stats
$PHORUM['DB']->update_forum_stats(false, "-{$num_hidden}");
$PHORUM['DATA']['OKMSG'] = "{$num_hidden} " . $PHORUM['DATA']['LANG']['MsgHiddenOk'];
if (isset($PHORUM['args']["prepost"])) {
    $PHORUM['DATA']["URL"]["REDIRECT"] = phorum_api_url(PHORUM_CONTROLCENTER_URL, "panel=" . PHORUM_CC_UNAPPROVED);
} else {
    $PHORUM['DATA']["URL"]["REDIRECT"] = $PHORUM["DATA"]["URL"]["LIST"];
}
Beispiel #3
0
 *     Allow modules to perform custom action whenever the user edits his post.
 *     This can be used to e.g. redirect the user immediately back to the edited
 *     post where he came from.
 *
 * [category]
 *     Message handling
 *
 * [when]
 *     In <filename>action_edit.php</filename> at the end of the file when
 *     everything has been done.
 *
 * [input]
 *     Array containing message data.
 *
 * [output]
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_posting_action_edit_post ($message)
 *     {
 *         global $PHORUM;
 *
 *         // perform a custom redirect
 *         phorum_redirect_by_url($PHORUM["DATA"]["URL"]["REDIRECT"]);
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["posting_action_edit_post"])) {
    phorum_api_hook("posting_action_edit_post", $message);
}
Beispiel #4
0
function phorum_pm_quoteformat($orig_author, $orig_author_id, $message, $inreplyto = NULL)
{
    global $PHORUM;
    // Build the reply subject.
    if (substr($message["subject"], 0, 3) != "Re:") {
        $message["subject"] = "Re: " . $message["subject"];
    }
    // Lookup the plain text name that we have to use for the author that we reply to.
    $author = phorum_api_user_get_display_name($orig_author_id, '', PHORUM_FLAG_PLAINTEXT);
    // TODO we'll have to handle anonymous users in the PM box. Those are
    // TODO users which sent a PM to somebody, but signed out afterwards.
    // TODO Currently, there's no graceful handling for that I think
    // TODO (maybe it's handled already, but that would only be by accident).
    if (isset($PHORUM["hooks"]["quote"])) {
        $quote = phorum_api_hook("quote", array($author, $message["message"], $orig_author_id));
    }
    if (empty($quote) || is_array($quote)) {
        // Build a quoted version of the message body.
        $quote = phorum_api_format_strip($message["message"]);
        $quote = str_replace("\n", "\n> ", $quote);
        $quote = wordwrap(trim($quote), 50, "\n> ", true);
        $quote = "{$author} {$PHORUM['DATA']['LANG']['Wrote']}:\n" . str_repeat("-", 55) . "\n> {$quote}\n\n\n";
    }
    $quote = ($inreplyto != NULL ? "{$PHORUM['DATA']['LANG']['InReplyTo']} {$inreplyto}\n\n" : '') . $quote;
    $message["message"] = $quote;
    return $message;
}
Beispiel #5
0
 * [when]
 *     Right before the <literal>PhorumInputForm</literal> object is shown.
 *
 * [input]
 *     The <literal>PhorumInputForm</literal> object.
 *
 * [output]
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_admin_general ($frm) 
 *     {
 *         // Add a section for the foo settings
 *         $frm->addbreak( "Foo Module Settings" );
 *
 *         // Add the option to cache the bar
 *         $row=$frm->addrow( "Enable Bar Caching:", $frm->select_tag( "mod_foo[enable_bar_caching]", array( "No", "Yes" ), $PHORUM["mod_foo"]["enable_bar_caching"] ) );
 *         $frm->addhelp($row, "Enable Bar Caching", "If you select yes for this option, then the bar will be cached." );
 *
 *         // Return the modified PhorumInputForm
 *         return $frm;
 *
 *     }
 *     </hookcode>
 */
$frm = phorum_api_hook("admin_general", $frm);
$frm->show();
?>

Beispiel #6
0
     *             case 'unapproved':
     *                 $log = 'No new password generated for ' .
     *                        'unapproved user ' . $user['username'];
     *                 break;
     *         }
     *
     *         if ($log !== NULL) {
     *             log_the_password_reset($log);
     *         }
     *
     *         return $user;
     *     }
     *     </hookcode>
     */
    if ($hook_args && isset($PHORUM['hooks']['password_reset'])) {
        phorum_api_hook("password_reset", $hook_args);
    }
}
// ----------------------------------------------------------------------------
// Build template data and output the page
// ----------------------------------------------------------------------------
$redir = htmlspecialchars($redir, ENT_COMPAT, $PHORUM['DATA']['HCHARSET']);
// Fill the breadcrumbs-info.
$PHORUM['DATA']['BREADCRUMBS'][] = array('URL' => '', 'TEXT' => $PHORUM['DATA']['LANG']['LogIn'], 'TYPE' => 'login');
// Fill the page heading info.
$PHORUM['DATA']['HEADING'] = $heading;
$PHORUM['DATA']['HTML_DESCRIPTION'] = '';
$PHORUM['DATA']['DESCRIPTION'] = '';
// Setup template data.
$PHORUM['DATA']['LOGIN']['redir'] = $redir;
$PHORUM['DATA']['URL']['REGISTER'] = phorum_api_url(PHORUM_REGISTER_URL);
Beispiel #7
0
  *         // Set the type of list page to use, based on a cookie.
  *         if (empty($_COOKIE['list_style'])) {
  *             $PHORUM['threaded_list'] = PHORUM_THREADED_DEFAULT;
  *         } elseif ($_COOKIE['list_style'] == 'threaded') {
  *             $PHORUM['threaded_list'] = PHORUM_THREADED_ON;
  *         } elseif ($_COOKIE['list_style'] == 'flat') {
  *             $PHORUM['threaded_list'] = PHORUM_THREADED_OFF;
  *         } elseif ($_COOKIE['list_style'] == 'hybrid') {
  *             $PHORUM['threaded_list'] = PHORUM_THREADED_HYBRID;
  *         }
  *     }
  *     </hookcode>
  */
 $page_hook = 'page_' . phorum_page;
 if (isset($PHORUM["hooks"][$page_hook])) {
     phorum_api_hook($page_hook, "");
 }
 $formatted = phorum_api_format_users(array($PHORUM['user']));
 $PHORUM['DATA']['USER'] = $formatted[0];
 $PHORUM['DATA']['PHORUM_PAGE'] = phorum_page;
 $PHORUM['DATA']['USERTRACK'] = $PHORUM['track_user_activity'];
 $PHORUM['DATA']['VROOT'] = $PHORUM['vroot'];
 $PHORUM['DATA']['POST_VARS'] .= "<input type=\"hidden\" name=\"forum_id\" value=\"{$PHORUM["forum_id"]}\" />\n";
 if (!empty($PHORUM['ref_thread_id'])) {
     $PHORUM['DATA']['POST_VARS'] .= "<input type=\"hidden\" name=\"ref_thread_id\" value=\"{$PHORUM["ref_thread_id"]}\" />\n";
 }
 if (!empty($PHORUM['ref_message_id'])) {
     $PHORUM['DATA']['POST_VARS'] .= "<input type=\"hidden\" name=\"ref_message_id\" value=\"{$PHORUM["ref_message_id"]}\" />\n";
 }
 if (!empty($PHORUM['use_rss'])) {
     if ($PHORUM["default_feed"] == "rss") {
Beispiel #8
0
/**
 * The Phorum shutdown function, which will always be called when a
 * Phorum script ends.
 */
function phorum_shutdown()
{
    global $PHORUM;
    // Strange things happen during shutdown
    // Make sure that we are in the Phorum dir.
    /**
     * @todo Still needed now we include files using absolute paths?
     */
    $working_dir = getcwd();
    chdir(PHORUM_PATH);
    /*
     * [hook]
     *     phorum_shutdown
     *
     * [description]
     *     This hook gives modules a chance to easily hook into
     *     PHP's <phpfunc>register_shutdown_function</phpfunc>
     *     functionality.<sbr/>
     *     <sbr/>
     *     Code that you put in a phorum_shutdown hook will be run after
     *     running a Phorum script finishes. This hook can be considered
     *     an expert hook. Only use it if you really need it and if you
     *     are aware of implementation details of PHP's shutdown
     *     functionality.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After running a Phorum script finishes.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     */
    if (isset($PHORUM["hooks"]["shutdown"])) {
        phorum_api_hook("shutdown");
    }
    // Shutdown the database connection.
    $PHORUM['DB']->close_connection();
    if ($working_dir !== FALSE) {
        chdir($working_dir);
    }
}
Beispiel #9
0
 * {
 *     // An optional name=.... argument can be used in the request.
 *     $name = phorum_ajax_getarg('name', 'string', 'Anonymous Person');
 *
 *     // This will return a JSON encoded string to the client.
 *     phorum_ajax_return("Hello, $name");
 * }
 * </hookcode>
 *
 * For this hook implementation, a GET based URL to fire this
 * Ajax call could look like
 * <literal>http://example.com/ajax.php?call=sayhello,name=JohnDoe</literal>.
 */
$call_hook = 'ajax_' . $ajax_call;
if (isset($PHORUM['hooks'][$call_hook])) {
    phorum_api_hook($call_hook, $PHORUM['ajax_args']);
}
// Check if the Ajax call has a core handler script.
if (file_exists("./include/ajax/call.{$ajax_call}.php")) {
    include "./include/ajax/call.{$ajax_call}.php";
    exit;
}
// No handler script available. Bail out.
phorum_ajax_error('Unknown call "' . $ajax_call . '" in Ajax POST request');
// ----------------------------------------------------------------------
// Utility functions that can be used by Ajax call implementations
// ----------------------------------------------------------------------
/**
 * Return an Ajax error to the caller.
 *
 * This will send an error (500 HTTP status code) message to the client,
Beispiel #10
0
     *
     * [when]
     *     Right after the javascript.php script has generated a new
     *     JavaScript file and right before storing that file in the cache.
     *     The filter hook will not be run for every request to
     *     javascript.php, but only in case the JavaScript code has
     *     to be refreshed.
     *
     * [input]
     *     The generated JavaScript code.
     *
     * [output]
     *     The filtered JavaScript code.
     */
    if (isset($PHORUM['hooks']['javascript_filter'])) {
        $content = phorum_api_hook('javascript_filter', $content);
    }
    if (!empty($PHORUM['cache_javascript'])) {
        $cache_time = time();
        phorum_cache_put('js', $cache_key, array($cache_time, $content), 86400);
    }
    // Send the JavaScript to the browser.
    header("Content-Type: text/javascript");
    print "/* FRESH */";
    print $content;
    // Exit here explicitly for not giving back control to portable and
    // embedded Phorum setups.
    exit(0);
}
// Find the modification time for the cache file.
$last_modified = $cache_time;
Beispiel #11
0
    $message["thread"] = $dbmessage["thread"];
    // Create Re: subject prefix.
    if (substr($dbmessage["subject"], 0, 4) != "Re: ") {
        $dbmessage["subject"] = "Re: " . $dbmessage["subject"];
    }
    $message["subject"] = $dbmessage["subject"];
    // Add a quoted version of the body for quoted reply messages.
    if ($mode == "quote") {
        // Lookup the name that we have to use for the author, if the
        // author is a registered user. The author field could be used
        // directly, but it can contain HTML formatting code, in case
        // some module uses the custom display name functionality.
        $author = phorum_api_user_get_display_name($dbmessage["user_id"], $dbmessage['author'], PHORUM_FLAG_PLAINTEXT);
        $quoted = 0;
        if (isset($PHORUM["hooks"]["quote"])) {
            $quoted = phorum_api_hook("quote", array($author, $dbmessage["body"], $dbmessage["user_id"]));
        }
        if (empty($quoted) || is_array($quoted)) {
            $quoted = phorum_api_format_strip($dbmessage["body"]);
            $quoted = str_replace("\n", "\n> ", $quoted);
            $quoted = wordwrap(trim($quoted), 50, "\n> ", true);
            $quoted = "{$author} " . "{$PHORUM["DATA"]["LANG"]["Wrote"]}:\n" . str_repeat("-", 55) . "\n> {$quoted}\n\n\n";
        }
        $message["body"] = $quoted;
    }
}
// Set message data for editing posts.
if ($mode == "edit" || $mode == "moderation") {
    // Transfer all database fields to the form fields.
    $message = phorum_posting_merge_db2form($message, $dbmessage, ALLFIELDS);
}
Beispiel #12
0
 *
 * [description]
 *     This hook can be used for performing actions like sending
 *     notifications or making log entries after making a message sticky.
 *
 * [category]
 *     Moderation
 *
 * [when]
 *     In <filename>include/moderation/make_sticky.php</filename>,
 *     right after a message has been made sticky by a moderator.
 *
 * [input]
 *     The id of the thread that has to be made sticky.
 *
 * [output]
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_make_sticky($msgthd_id)
 *     {
 *         // ... extra processing for make_sticky operations goes here ...
 *
 *         return $msgthd_id;
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["make_sticky"])) {
    phorum_api_hook("make_sticky", $msgthd_id);
}
Beispiel #13
0
 *     Allow modules to perform custom action whenever the user cancels editing
 *     of his post. This can be used to e.g. redirect the user immediately back
 *     to the edited post where he came from.
 *
 * [category]
 *     Message handling
 *
 * [when]
 *     In <filename>action_cancel.php</filename> at the end of the file when 
 *     everything has been done.
 *
 * [input]
 *     Array containing message data.
 *
 * [output]
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_posting_action_cancel_post ($message)
 *     {
 *         global $PHORUM;
 *
 *         // perform a custom redirect
 *         phorum_redirect_by_url($PHORUM["DATA"]["URL"]["REDIRECT"]);
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["posting_action_cancel_post"])) {
    phorum_api_hook("posting_action_cancel_post", $message);
}
Beispiel #14
0
/**
 * This function handles preparing message data for use in the templates.
 *
 * @param array $messages
 *     An array of messages that have to be formatted.
 *     Each message is an array on its own, containing the message data.
 *
 * @param array $author_specs
 *     By default, the formatting function will create author info
 *     data, based on the fields "user_id", "author" and "email".
 *     This will create $messages["URL"]["PROFILE"] if needed (either pointing
 *     to a user profile for registered users or the email address of
 *     anonymous users that left an email address in the forum) and will
 *     do formatting on the "author" field.
 *
 *     By providing extra $author_specs, this formatting can be done on
 *     more author fields. This argument should be an array, containing
 *     arrays with five fields:
 *
 *     - the name of the field that contains a user_id
 *     - the name of the field that contains the name of the author
 *     - the name of the field that contains the email address
 *       (can be NULL if none available)
 *     - the name of the field to store the author name in
 *     - the name of the URL field to store the profile/email link in
 *
 *     For the default author field handling like described above,
 *     this array would be:
 *
 *     array("user_id", "author", "email", "author", "PROFILE");
 *
 * @return data - The formatted messages.
 */
function phorum_api_format_messages($messages, $author_specs = NULL)
{
    global $PHORUM;
    // Prepare author specs.
    if ($author_specs === NULL) {
        $author_specs = array();
    }
    $author_specs[] = array("user_id", "author", "email", "author", "PROFILE");
    // Prepare censoring replacements.
    list($censor_search, $censor_replace) = phorum_api_format_censor_compile();
    // Prepare the profile URL template. This is used to prevent
    // having to call the phorum_api_url() function over and over again.
    $profile_url_template = phorum_api_url(PHORUM_PROFILE_URL, '%spec_data%');
    // A special <br> tag to keep track of breaks that are added by phorum.
    $phorum_br = '<phorum break>';
    // Apply Phorum's formatting rules to all messages.
    foreach ($messages as $id => $message) {
        // Normally, the message_id must be set, since we should be handling
        // message data. It might not be set however, because sometimes
        // the message formatting is called using some fake message data
        // for formatting something else than a message.
        if (!isset($message['message_id'])) {
            $messages[$id]['message_id'] = $message['message_id'] = $id;
        }
        // -----------------------------------------------------------------
        // Message body
        // -----------------------------------------------------------------
        if (isset($message['body']) && $message['body'] != '') {
            $body = $message["body"];
            // Convert legacy <...> URLs into bare URLs.
            $body = preg_replace("/<(\n                    (?:http|https|ftp):\\/\\/\n                    [a-z0-9;\\/\\?:@=\\&\$\\-_\\.\\+!*'\\(\\),~%]+?\n                  )>/xi", "\$1", $body);
            // Escape special HTML characters.
            $escaped_body = htmlspecialchars($body, ENT_COMPAT, $PHORUM["DATA"]["HCHARSET"]);
            // When there is a charset mismatch between the database
            // and the language file, then bodies might get crippled
            // because of the htmlspecialchars() call. Here we try to
            // correct this issue. It's not perfect, but we do what
            // we can ...
            if ($escaped_body == '') {
                if (function_exists("iconv")) {
                    // We are gonna guess and see if we get lucky.
                    $escaped_body = iconv("ISO-8859-1", $PHORUM["DATA"]["HCHARSET"], $body);
                } else {
                    // We let htmlspecialchars use its defaults.
                    $escaped_body = htmlspecialchars($body);
                }
            }
            $body = $escaped_body;
            // Replace newlines with $phorum_br temporarily.
            // This way the mods know what breaks were added by
            // Phorum and what breaks by the user.
            $body = str_replace("\n", "{$phorum_br}\n", $body);
            // Censor bad words in the body.
            if ($censor_search !== NULL) {
                $body = preg_replace($censor_search, $censor_replace, $body);
            }
            $messages[$id]['body'] = $body;
        }
        // -----------------------------------------------------------------
        // Message subject
        // -----------------------------------------------------------------
        // Censor bad words in the subject.
        if (isset($message['subject']) && $censor_search !== NULL) {
            $messages[$id]['subject'] = preg_replace($censor_search, $censor_replace, $message['subject']);
        }
        // Escape special HTML characters.
        if (isset($message['subject'])) {
            $messages[$id]['subject'] = htmlspecialchars($messages[$id]['subject'], ENT_COMPAT, $PHORUM['DATA']['HCHARSET']);
        }
        // -----------------------------------------------------------------
        // Message author
        // -----------------------------------------------------------------
        // Escape special HTML characters in the email address.
        if (isset($message['email'])) {
            $messages[$id]['email'] = htmlspecialchars($message['email'], ENT_COMPAT, $PHORUM['DATA']['HCHARSET']);
        }
        // Do author formatting for all provided author fields.
        foreach ($author_specs as $spec) {
            // Use "Anonymous user" as the author name if there's no author
            // name available for some reason.
            if (!isset($message[$spec[1]]) || $message[$spec[1]] == '') {
                $messages[$id][$spec[3]] = $PHORUM["DATA"]["LANG"]["AnonymousUser"];
            } elseif (!empty($message[$spec[0]])) {
                $url = str_replace('%spec_data%', $message[$spec[0]], $profile_url_template);
                $messages[$id]["URL"][$spec[4]] = $url;
                $messages[$id][$spec[3]] = empty($PHORUM["custom_display_name"]) ? htmlspecialchars($message[$spec[1]], ENT_COMPAT, $PHORUM["DATA"]["HCHARSET"]) : $message[$spec[1]];
            } elseif ($spec[2] !== NULL && !empty($message[$spec[2]]) && (empty($PHORUM['hide_email_addr']) || !empty($PHORUM["user"]["admin"]) || phorum_api_user_check_access(PHORUM_USER_ALLOW_MODERATE_MESSAGES) && PHORUM_MOD_EMAIL_VIEW || phorum_api_user_check_access(PHORUM_USER_ALLOW_MODERATE_USERS) && PHORUM_MOD_EMAIL_VIEW)) {
                $messages[$id][$spec[3]] = htmlspecialchars($message[$spec[1]], ENT_COMPAT, $PHORUM["DATA"]["HCHARSET"]);
                $email_url = phorum_api_format_html_encode("mailto:" . $message[$spec[2]]);
                $messages[$id]["URL"]["PROFILE"] = $email_url;
            } else {
                $messages[$id][$spec[3]] = htmlspecialchars($message[$spec[1]], ENT_COMPAT, $PHORUM["DATA"]["HCHARSET"]);
            }
            if ($censor_search !== NULL) {
                $messages[$id][$spec[3]] = preg_replace($censor_search, $censor_replace, $messages[$id][$spec[3]]);
            }
        }
    }
    // A hook for module writers to apply custom message formatting.
    if (isset($PHORUM["hooks"]["format"])) {
        $messages = phorum_api_hook("format", $messages);
    }
    // A hook for module writers for doing post formatting fixups.
    if (isset($PHORUM["hooks"]["format_fixup"])) {
        $messages = phorum_api_hook("format_fixup", $messages);
    }
    // Clean up after the mods are done.
    foreach ($messages as $id => $message) {
        // Clean up line breaks inside pre and xmp tags. These tags
        // take care of showing newlines as breaks themselves.
        if (isset($message['body']) && $message['body'] != '') {
            foreach (array('pre', 'goep', 'xmp') as $tagname) {
                if (preg_match_all("/(<{$tagname}.*?>).+?(<\\/{$tagname}>)/si", $message['body'], $matches)) {
                    foreach ($matches[0] as $match) {
                        $stripped = str_replace($phorum_br, '', $match);
                        $message['body'] = str_replace($match, $stripped, $message['body']);
                    }
                }
            }
            // Remove line break after div, quote and code tags. These
            // tags have their own line break. Without this, there would
            // be to many white lines.
            $message['body'] = preg_replace("/\\s*(<\\/?(?:div|xmp|blockquote|pre)[^>]*>)\\s*\\Q{$phorum_br}\\E/", '$1', $message['body']);
            // Normalize the Phorum line breaks that are left.
            $messages[$id]['body'] = str_replace($phorum_br, "<br />", $message['body']);
        }
    }
    return $messages;
}
Beispiel #15
0
         if (empty($_POST["explanation"])) {
             $_POST["explanation"] = "<" . $PHORUM["DATA"]["LANG"]["None"] . ">";
         }
         $mail_users = phorum_api_user_list_moderators($PHORUM['forum_id'], $PHORUM['email_ignore_admin'], TRUE);
         if (count($mail_users)) {
             $mail_data = array("mailmessage" => $PHORUM["DATA"]["LANG"]['ReportPostEmailBody'], "mailsubject" => $PHORUM["DATA"]["LANG"]['ReportPostEmailSubject'], "forumname" => $PHORUM["DATA"]["NAME"], "reportedby" => $PHORUM["user"]["display_name"], "author" => $message["author"], "subject" => $message["subject"], "body" => wordwrap($message["body"], 72), "ip" => $message["ip"], "raw_date" => $message["datestamp"], "date" => phorum_api_format_date($PHORUM["short_date_time"], $message["datestamp"]), "explanation" => wordwrap($_POST["explanation"], 72), "url" => phorum_api_url(PHORUM_READ_URL, $message["thread"], $message_id), "delete_url" => phorum_api_url(PHORUM_MODERATION_URL, PHORUM_DELETE_MESSAGE, $message_id), "hide_url" => phorum_api_url(PHORUM_MODERATION_URL, PHORUM_HIDE_POST, $message_id), "edit_url" => phorum_api_url(PHORUM_POSTING_URL, 'moderation', $message_id), "reporter_url" => phorum_api_url(PHORUM_PROFILE_URL, $PHORUM["user"]["user_id"]), "message" => $message);
             if (isset($_POST[PHORUM_SESSION_LONG_TERM])) {
                 // strip any auth info from the created urls
                 $mail_data["url"] = preg_replace("!,{0,1}" . PHORUM_SESSION_LONG_TERM . "=" . urlencode($_POST[PHORUM_SESSION_LONG_TERM]) . "!", "", $mail_data["url"]);
                 $mail_data["delete_url"] = preg_replace("!,{0,1}" . PHORUM_SESSION_LONG_TERM . "=" . urlencode($_POST[PHORUM_SESSION_LONG_TERM]) . "!", "", $mail_data["delete_url"]);
                 $mail_data["hide_url"] = preg_replace("!,{0,1}" . PHORUM_SESSION_LONG_TERM . "=" . urlencode($_POST[PHORUM_SESSION_LONG_TERM]) . "!", "", $mail_data["hide_url"]);
                 $mail_data["edit_url"] = preg_replace("!,{0,1}" . PHORUM_SESSION_LONG_TERM . "=" . urlencode($_POST[PHORUM_SESSION_LONG_TERM]) . "!", "", $mail_data["edit_url"]);
                 $mail_data["reporter_url"] = preg_replace("!,{0,1}" . PHORUM_SESSION_LONG_TERM . "=" . urlencode($_POST[PHORUM_SESSION_LONG_TERM]) . "!", "", $mail_data["reporter_url"]);
             }
             if (isset($PHORUM["hooks"]["report"])) {
                 $mail_data = phorum_api_hook("report", $mail_data);
             }
             phorum_api_mail($mail_users, $mail_data);
             $PHORUM["DATA"]["URL"]["REDIRECT"] = phorum_api_url(PHORUM_FOREIGN_READ_URL, $message["forum_id"], $message["thread"], $message['message_id']);
             $PHORUM["DATA"]["BACKMSG"] = $PHORUM["DATA"]["LANG"]["BackToThread"];
             $PHORUM["DATA"]["OKMSG"] = $PHORUM["DATA"]["LANG"]["ReportPostSuccess"];
             $template = "message";
             $report = true;
         }
     } else {
         $PHORUM["DATA"]["ReportPostMessage"] = $PHORUM["DATA"]["LANG"]['ReportPostNotAllowed'];
     }
 }
 // format message
 list($message) = phorum_api_format_messages(array($message));
 $PHORUM["DATA"]["PostSubject"] = $message["subject"];
Beispiel #16
0
 *     The same array as the one that was used for the hook call
 *     argument, possibly with some updated fields in it.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_index($data)
 *     {
 *         global $PHORUM;
 *
 *         // An example to add some data to the description of
 *         // forums on the index page in flat view.
 *         if ($PHORUM['index_style'] == PHORUM_INDEX_FLAT)
 *         {
 *             foreach ($data as $id => $item)
 *             {
 *                 if (!$item['folder_flag'])
 *                 {
 *                     $data[$id]['description'] .= '<br/>Blah foo bar baz';
 *                 }
 *             }
 *         }
 *
 *         return $data;
 *     }
 *     </hookcode>
 */
if (isset($PHORUM['hooks']['index'])) {
    $PHORUM['DATA']['FORUMS'] = phorum_api_hook('index', $PHORUM['DATA']['FORUMS']);
}
// Display the page.
phorum_api_output('index_flat');
Beispiel #17
0
 *         $pm_message = preg_replace(
 *             "%message_subject%",
 *             $data[0]["subject"],
 *             $PHORUM["DATA"]["LANG"]["mod_foo"]["MessageApprovedBody"]
 *             );
 *         $PHORUM['DB']->pm_send(
 *             $PHORUM["DATA"]["LANG"]["mod_foo"]["MessageApprovedSubject"],
 *             $pm_message,
 *             $data[0]["user_id"]
 *             );
 *
 *         return $data;
 *
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["after_approve"])) {
    phorum_api_hook("after_approve", array($old_message, PHORUM_APPROVE_MESSAGE));
}
if ($old_message['status'] != PHORUM_STATUS_HIDDEN) {
    phorum_api_mail_message_notify($old_message);
}
if (isset($PHORUM['args']['old_forum']) && is_numeric($PHORUM['args']['old_forum'])) {
    $PHORUM['forum_id'] = (int) $PHORUM['args']['old_forum'];
}
if (isset($PHORUM['args']["prepost"])) {
    $PHORUM['DATA']["URL"]["REDIRECT"] = phorum_api_url(PHORUM_CONTROLCENTER_URL, "panel=" . PHORUM_CC_UNAPPROVED);
} else {
    $PHORUM['DATA']["URL"]["REDIRECT"] = $PHORUM["DATA"]["URL"]["LIST"];
}
$invalidate_message_cache[] = array("message_id" => $msgthd_id, "forum_id" => $PHORUM["forum_id"]);
Beispiel #18
0
$thread_id = phorum_ajax_getarg('thread_id', 'int', 0);
$threads_only = phorum_ajax_getarg('threads_only', 'boolean', 0);
$format = phorum_ajax_getarg('format', 'string', 'html');
// Retrieve the recent messages.
$recent = $PHORUM['DB']->get_recent_messages($count, 0, $forum_id, $thread_id, $threads_only);
unset($recent["users"]);
// Add newflag info to the messages.
if ($PHORUM["DATA"]["LOGGEDIN"]) {
    $type = $threads_only ? PHORUM_NEWFLAGS_BY_THREAD : PHORUM_NEWFLAGS_BY_MESSAGE;
    $recent = phorum_api_newflags_apply_to_messages($recent, $type);
}
// Format the messages.
$recent = phorum_api_format_messages($recent);
// Apply the list hook to the messages.
if (isset($PHORUM["hooks"]["list"])) {
    $recent = phorum_api_hook("list", $recent);
}
// Retrieve information about the forums for the active user.
$allowed_forums = phorum_api_user_check_access(PHORUM_USER_ALLOW_READ, PHORUM_ACCESS_LIST);
$forums = $PHORUM['DB']->get_forums($allowed_forums);
foreach ($forums as $id => $forum) {
    $forums[$id]['url'] = phorum_get_url(PHORUM_LIST_URL, $forum['forum_id']);
}
// Add forum info to the messages and clean up data.
foreach ($recent as $id => $message) {
    $recent[$id]['foruminfo'] = array('id' => $message['forum_id'], 'name' => $forums[$message['forum_id']]['name'], 'url' => $forums[$message['forum_id']]['url']);
    // Strip fields that the caller should not see in the return data.
    unset($recent[$id]['email']);
    unset($recent[$id]['ip']);
    unset($recent[$id]['meta']);
    unset($recent[$id]['msgid']);
Beispiel #19
0
/**
 * Write a new message to the event logging table.
 *
 * This function will automatically fill the log information with
 * user_id, ip, hostname (if hostname resolving is enabled for the log module)
 * datestamp and vroot information. Other log info can be provided throught
 * the $loginfo argument.
 *
 * @param $loginfo - An array containing logging information. This array
 *                   can contain the following fields:
 *
 *                   message     A short log message on one line.
 *                   details     Details about the log message, which can
 *                               span multiple lines. This could for example
 *                               be used for providing a debug backtrace.
 *                   source      The source of the log message. This is a
 *                               free 32 char text field, which can be used
 *                               to specifiy what part of Phorum generated the
 *                               log message (e.g. "mod_smileys"). If no
 *                               source is provided, the "phorum_page"
 *                               constant will be used instead.
 *                   category    A high level category for the message.
 *                               Options for this field are:
 *                               EVENTLOG_CAT_APPLICATION (default)
 *                               EVENTLOG_CAT_DATABASE
 *                               EVENTLOG_CAT_SECURITY
 *                               EVENTLOG_CAT_SYSTEM
 *                               EVENTLOG_CAT_MODULE
 *                   loglevel    This indicates the severety of the message.
 *                               Options for this field are:
 *                               EVENTLOG_LVL_DEBUG
 *                                 Messages that are used by programmers
 *                                 for tracking low level Phorum operation.
 *                               EVENTLOG_LVL_INFO
 *                                 Messages that provide logging for events
 *                                 that occur during normal operation. These
 *                                 messages could be harvested for usage
 *                                 reporting and other types of reports.
 *                               EVENTLOG_LVL_WARNING
 *                                 Warning messages do not indicate errors,
 *                                 but they do report events that are not
 *                                 considered to belong to normal operation
 *                                 (e.g. a user which enters a wrong password
 *                                 or a duplicate message being posted).
 *                               EVENTLOG_LVL_ERROR
 *                                 Error messages indicate non urgent failures
 *                                 in Phorum operation. These should be
 *                                 relayed to administrators and/or developers
 *                                 to have them solved.
 *                               EVENTLOG_LVL_ALERT
 *                                 Alert messages indicate errors which should
 *                                 be corrected as soon as possible (e.g. loss
 *                                 of network connectivity or a full disk).
 *                                 These should be relayed to the system
 *                                 administrator).
 *
 *                   vroot       vroot for which a message is generated.
 *                   forum_id    forum_id for which a message is generated.
 *                   thread_id   thread_id for which a message is generated
 *                   message_id  message_id for which a message is generated
 *
 *                   user_id     Filled automatically, but can be overridden
 *                   ip          Filled automatically, but can be overridden
 *                   hostname    Filled automatically, but can be overridden
 *                   datestamp   Filled automatically, but can be overridden
 */
function event_logging_writelog($loginfo)
{
    global $PHORUM;
    // Check the minimum log level. Only write to the log if the
    // log level of the event is at or above the configured minimum.
    $lvl = isset($loginfo["loglevel"]) ? (int) $loginfo["loglevel"] : 0;
    if ($lvl < $PHORUM["mod_event_logging"]["min_log_level"]) {
        return;
    }
    $loginfo = phorum_api_hook("event_logging_writelog", $loginfo);
    // The record that we will insert in the database.
    $record = array();
    // Handle messages that exceed the maximum message length.
    if ($loginfo["message"] !== NULL && strlen($loginfo["message"]) > 255) {
        if (!isset($loginfo["details"])) {
            $loginfo["details"] = '';
        }
        $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" . $loginfo["details"];
        $loginfo["message"] = substr($loginfo["message"], 0, 100) . "... (see event details for the full message)\n";
    } elseif (isset($loginfo["details"])) {
        $loginfo["details"] = "Message:\n\n{$loginfo["message"]}\n\n" . $loginfo["details"];
    }
    // Add the fields from the $loginfo argument.
    foreach ($loginfo as $key => $val) {
        switch ($key) {
            case "datestamp":
            case "user_id":
            case "vroot":
            case "forum_id":
            case "thread_id":
            case "message_id":
            case "category":
            case "loglevel":
                settype($val, "int");
                $record[$key] = $val;
                break;
            case "message":
            case "details":
            case "source":
            case "ip":
            case "hostname":
                $record[$key] = "'" . $PHORUM['DB']->interact(DB_RETURN_QUOTED, $val) . "'";
                break;
            default:
                phorum_api_error(PHORUM_ERRNO_DATABASE, "event_logging_log(): Illegal key " . "field \"{$key}\" in the \$loginfo argument");
        }
    }
    // Add the message source.
    $from_module = FALSE;
    if (!isset($record["source"])) {
        list($source, $from_module) = event_logging_find_source(1);
        $record["source"] = "'" . $PHORUM['DB']->interact(DB_RETURN_QUOTED, $source) . "'";
    }
    // Add the category.
    if (!isset($record["category"])) {
        $record["category"] = $from_module ? EVENTLOG_CAT_MODULE : EVENTLOG_CAT_APPLICATION;
    }
    // Add the datestamp.
    if (!isset($record["datestamp"])) {
        $record["datestamp"] = time();
    }
    // Add the IP address for the current visitor.
    if (!isset($record["ip"]) && isset($_SERVER["REMOTE_ADDR"])) {
        $ip = $_SERVER["REMOTE_ADDR"];
        $record["ip"] = "'" . $PHORUM['DB']->interact(DB_RETURN_QUOTED, $ip) . "'";
    }
    // Add the hostname for the current visitor.
    if (!isset($record["hostname"]) && isset($record["ip"]) && $PHORUM["mod_event_logging"]["resolve_hostnames"]) {
        $hostname = gethostbyaddr($ip);
        if ($hostname != $ip) {
            $record["hostname"] = "'" . $PHORUM['DB']->interact(DB_RETURN_QUOTED, $hostname) . "'";
        }
    }
    // Add the user_id in case the visitor is an authenticated user.
    if (!isset($record["user_id"]) && isset($PHORUM["user"]["user_id"]) && $PHORUM["user"]["user_id"]) {
        $record["user_id"] = $PHORUM["user"]["user_id"];
    }
    // Add the current vroot.
    if (!isset($record["vroot"]) && isset($PHORUM["vroot"])) {
        $record["vroot"] = $PHORUM["vroot"];
    }
    // Insert the logging record in the database.
    $PHORUM['DB']->interact(DB_RETURN_RES, "INSERT INTO {$PHORUM["event_logging_table"]}\n                (" . implode(', ', array_keys($record)) . ")\n         VALUES (" . implode(', ', $record) . ")", NULL, DB_MASTERQUERY);
}
Beispiel #20
0
////////////////////////////////////////////////////////////////////////////////
if (!defined("PHORUM_CONTROL_CENTER")) {
    return;
}
$template = "cc_start";
$PHORUM['DATA']['UserPerms'] = phorum_readable_permissions();
$PHORUM['DATA']['PROFILE']['raw_date_added'] = $PHORUM['DATA']['PROFILE']['date_added'];
$PHORUM['DATA']['PROFILE']['date_added'] = phorum_api_format_date($PHORUM['short_date_time'], $PHORUM['DATA']['PROFILE']['date_added']);
if ($PHORUM["track_user_activity"] && (!empty($PHORUM["user"]["admin"]) || phorum_api_user_check_access(PHORUM_USER_ALLOW_MODERATE_MESSAGES) || phorum_api_user_check_access(PHORUM_USER_ALLOW_MODERATE_USERS) || !$PHORUM['DATA']['PROFILE']["hide_activity"])) {
    $PHORUM["DATA"]["PROFILE"]["raw_date_last_active"] = $PHORUM["DATA"]["PROFILE"]["date_last_active"];
    $PHORUM["DATA"]["PROFILE"]["date_last_active"] = phorum_api_format_date($PHORUM['short_date_time'], $PHORUM["DATA"]["PROFILE"]["date_last_active"]);
} else {
    unset($PHORUM["DATA"]["PROFILE"]["date_last_active"]);
}
if (isset($PHORUM["hooks"]["profile"])) {
    $PHORUM["DATA"]["PROFILE"] = phorum_api_hook("profile", $PHORUM["DATA"]["PROFILE"]);
}
/* --------------------------------------------------------------- */
function phorum_readable_permissions()
{
    global $PHORUM;
    $newperms = array();
    if (isset($PHORUM["user"]["permissions"])) {
        $forums = phorum_api_forums_get(array_keys($PHORUM["user"]["permissions"]));
        foreach ($PHORUM["user"]["permissions"] as $forum => $perms) {
            if (isset($forums[$forum])) {
                if ($perms & PHORUM_USER_ALLOW_MODERATE_MESSAGES) {
                    $newperms[] = array('forum' => $forums[$forum]["name"], 'perm' => $PHORUM['DATA']['LANG']['PermModerator']);
                }
                if ($perms & PHORUM_USER_ALLOW_READ) {
                    $newperms[] = array('forum' => $forums[$forum]["name"], 'perm' => $PHORUM['DATA']['LANG']['PermAllowRead']);
Beispiel #21
0
      * [example]
      *     <hookcode>
      *     function phorum_mod_foo_admin_editforum_form_save_after_defaults ($error) 
      *     {
      *         # Early bail out in case another hook generated already an error
      *         if (strlen($error) > 0) {
      *             return $error;
      *         }
      *         # Do your stuff, possible setting $error to a error string
      *         # for the user to be shown; or simply leave it untouched.
      *         return $error;
      *
      *     }
      *     </hookcode>
      */
     $error = phorum_api_hook("admin_editforum_form_save_after_defaults", $error);
 }
 // If there were no errors, then store the data in the database.
 if (empty($errors)) {
     // Store default settings.
     if (defined('PHORUM_DEFAULT_OPTIONS')) {
         // Store the default settings in the database.
         phorum_api_forums_save($forum, PHORUM_FLAG_DEFAULTS);
         $url = phorum_admin_build_url(array('module=forum_defaults', 'okmsg=' . rawurlencode('The default settings were successfully saved')), TRUE);
     } else {
         // Some statically assigned fields.
         $forum['folder_flag'] = 0;
         // For new forums.
         if (!defined('PHORUM_EDIT_FORUM')) {
             $forum['forum_id'] = NULL;
         }
Beispiel #22
0
/**
 * Generate a Phorum URL.
 */
function phorum_api_url()
{
    global $PHORUM;
    // So we do not call function_exists() for each phorum_api_url() call.
    static $do_custom_url = NULL;
    if ($do_custom_url === NULL) {
        $do_custom_url = function_exists('phorum_custom_get_url');
    }
    $argv = func_get_args();
    $url = '';
    $suffix = '';
    $pathinfo = NULL;
    $add_forum_id = 1;
    $add_get_vars = TRUE;
    $type = array_shift($argv);
    if (!isset($PHORUM['API']['url_patterns'][$type])) {
        // these URL types need extra care
        // please do not add anything to this unless it is a last resort
        switch ($type) {
            case PHORUM_REPLY_URL:
                $add_get_vars = TRUE;
                $add_forum_id = 2;
                // The reply URL depends on how the reply form is handled.
                if (!empty($PHORUM['reply_on_read_page'])) {
                    $name = 'read';
                    $suffix = '#REPLY';
                } else {
                    $name = 'posting';
                }
                break;
            case PHORUM_FILE_URL:
                $name = 'file';
                $add_forum_id = 2;
                // If a filename=... parameter is set, then change that
                // parameter to a URL path, unless this feature is not
                // enabled in the admin setup.
                $unset = array();
                if (!empty($PHORUM['file_url_uses_pathinfo'])) {
                    $file_id = NULL;
                    $filename = NULL;
                    $download = '';
                    foreach ($argv as $id => $arg) {
                        if (substr($arg, 0, 5) == 'file=') {
                            $file_id = substr($arg, 5);
                            // %file_id% is sometimes used for creating URL
                            // templates, so we should not mangle that one.
                            if ($file_id != '%file_id%') {
                                settype($file_id, 'int');
                            }
                            $unset[] = $id;
                        } elseif (substr($arg, 0, 9) == 'filename=') {
                            $filename = urldecode(substr($arg, 9));
                            // %file_name% is sometimes used for creating URL
                            // templates, so we should not mangle that one.
                            if ($filename != '%file_name%') {
                                $filename = preg_replace('/[^\\w\\_\\-\\.]/', '_', $filename);
                                $filename = preg_replace('/_+/', '_', $filename);
                            }
                            $unset[] = $id;
                        } elseif (substr($arg, 0, 9) == 'download=') {
                            $download = 'download/';
                            $unset[] = $id;
                        }
                    }
                    if ($file_id !== NULL && $filename !== NULL) {
                        foreach ($unset as $id) {
                            unset($argv[$id]);
                        }
                        $add_forum_id = 2;
                        $pathinfo = "/{$download}{$PHORUM['forum_id']}/" . "{$file_id}/{$filename}";
                    }
                }
                break;
                // this is for adding own generic urls
            // this is for adding own generic urls
            case PHORUM_CUSTOM_URL:
                // first arg is our page
                $name = array_shift($argv);
                // second arg determines if we should add the forum_id
                $add_forum_id = (bool) array_shift($argv) ? 2 : 0;
                break;
            default:
                trigger_error("phorum_api_url(): Illegal URL type " . "\"{$type}\" used", E_USER_ERROR);
                break;
        }
    } else {
        list($name, $add_forum_id, $add_get_vars, $suffix_p, $suffix_fld) = $PHORUM['API']['url_patterns'][$type];
        if ($suffix_p !== NULL) {
            if (empty($suffix_fld)) {
                $suffix = $suffix_p;
            } else {
                $suffix_fld--;
                // because we shift()ed $argv before.
                if (!empty($argv[$suffix_fld]) && (is_numeric($argv[$suffix_fld]) || strpos($argv[$suffix_fld], '%') === 0)) {
                    $suffix = $suffix_p . $argv[$suffix_fld];
                }
            }
        }
    }
    // Build the URL.
    $url = $PHORUM['http_path'] . '/';
    if ($name) {
        $url .= $name . '.' . PHORUM_FILE_EXTENSION;
    }
    // Build the query parameters to add.
    // Add forum id if requested.
    if ($add_forum_id === 2) {
        array_unshift($argv, $PHORUM['forum_id']);
    }
    // Add forum id if setting is conditional and there are no params.
    if ($add_forum_id === 3 & count($argv) == 0) {
        array_unshift($argv, $PHORUM['forum_id']);
    }
    // Add forum id and (if available) the thread and message id.
    if ($add_forum_id === 4) {
        if (!empty($PHORUM['ref_message_id'])) {
            array_push($argv, 'ref_message_id=' . $PHORUM['ref_message_id']);
        }
        if (!empty($PHORUM['ref_thread_id'])) {
            array_push($argv, 'ref_thread_id=' . $PHORUM['ref_thread_id']);
        }
        array_unshift($argv, $PHORUM['forum_id']);
    }
    // Add GET vars if requested.
    if ($add_get_vars) {
        $query_params = array_merge($argv, $PHORUM['DATA']['GET_VARS']);
    } else {
        $query_params = $argv;
    }
    /**
     * @todo document the 'url_build' hook.
     */
    if (isset($PHORUM['hooks']['url_build'])) {
        $hook_url = phorum_api_hook('url_build', NULL, $name, $query_params, $suffix, $pathinfo);
        if ($hook_url !== NULL) {
            return $hook_url;
        }
    }
    // Allow full overriding of the URL building mechanism by
    // implementing the function "phorum_custom_get_url()".
    // This is a legacy solution (a hook avant la lettre).
    // When writing new code, then please use the "url_build"
    // hook instead.
    if ($do_custom_url) {
        $url = phorum_custom_get_url($name, $query_params, $suffix, $pathinfo);
    } else {
        if ($pathinfo !== null) {
            $url .= $pathinfo;
        }
        if (!empty($query_params)) {
            $url .= '?' . implode(',', $query_params);
        }
        if ($suffix) {
            $url .= $suffix;
        }
    }
    return $url;
}
Beispiel #23
0
/**
 * Delete a forum or folder.
 *
 * When a folder is deleted, then the contained folders and forums are
 * linked to the parent of the folder.
 *
 * @param integer $forum_id
 *   The forum_id to delete.
 *
 * @return mixed
 *   An array containing the data for the deleted forum or folder.
 *   NULL in case no forum or folder exists for the provided forum id. 
 */
function phorum_api_forums_delete($forum_id)
{
    global $PHORUM;
    $forum = phorum_api_forums_get($forum_id);
    // Check if the forum or folder was found. If not, then return NULL.
    // We do not trigger an error here, since the forum/folder not existing
    // is the desired situation anyway.
    if ($forum === NULL) {
        return NULL;
    }
    // Handle deleting a folder.
    if ($forum['folder_flag']) {
        /*
         * [hook]
         *     admin_folder_delete
         *
         * [availability]
         *     Phorum 5 >= 5.3
         *
         * [description]
         *     This hook is called whenever a folder is deleted.
         *
         * [category]
         *     Admin interface
         *
         * [when]
         *     Right before the folder will be deleted from the database.
         *
         * [input]
         *     The ID of the folder.
         *
         * [output]
         *     Same as input.
         *
         * [example]
         *     <hookcode>
         *     function phorum_mod_foo_admin_folder_delete ($id) 
         *     {
         *         // E.g. Notify an external system that the folder has
         *         // been deleted.
         *
         *         // Return the folder ID for other hooks.
         *         return $id;
         *
         *     }
         *     </hookcode>
         */
        phorum_api_hook("admin_folder_delete", $forum_id);
        // When the folder is a vroot folder currently, then disable
        // the vroot setting for it by linking it to the vroot of
        // the parent folder. This will take care of recursive updates
        // down the hierarchy as well.
        if ($forum['vroot'] == $forum['forum_id']) {
            $parent_vroot = 0;
            if ($forum['parent_id']) {
                $parent_folder = phorum_api_forums_get($forum['parent_id']);
                if ($parent_folder) {
                    // This check should not be necessary.
                    $parent_vroot = $parent_folder['vroot'];
                }
            }
            phorum_api_forums_save(array('forum_id' => $forum['forum_id'], 'vroot' => $parent_vroot));
        }
        // This call deletes the folder from the database.
        // It will link child folders and forums to the deleted folder's parent.
        $PHORUM['DB']->drop_folder($forum_id);
    } else {
        /*
         * [hook]
         *     admin_forum_delete
         *
         * [description]
         *     This hook is called whenever a forum is deleted.
         *
         * [category]
         *     Admin interface
         *
         * [when]
         *     Right before the forum will be deleted from the database.
         *
         * [input]
         *     The ID of the forum.
         *
         * [output]
         *     Same as input.
         *
         * [example]
         *     <hookcode>
         *     function phorum_mod_foo_admin_forum_delete ($id) 
         *     {
         *         // E.g. Notify an external system that the forum has
         *         // been deleted.
         *
         *         // Return the forum ID for other hooks.
         *         return $id;
         *
         *     }
         *     </hookcode>
         */
        phorum_api_hook("admin_forum_delete", $forum_id);
        $PHORUM['DB']->drop_forum($forum_id);
    }
    return $forum;
}
Beispiel #24
0
        }
    }
    // Check if we have moved threads to delete.
    // We unset the forum id, so $PHORUM['DB']->get_messages()
    // will return messages with the same thread id in
    // other forums as well (those are the move notifications).
    $forum_id = $PHORUM["forum_id"];
    $PHORUM["forum_id"] = 0;
    $moved = $PHORUM['DB']->get_messages($msgthd_id);
    foreach ($moved as $id => $data) {
        if (!empty($data["moved"])) {
            $PHORUM["forum_id"] = $data['forum_id'];
            $PHORUM['DB']->delete_message($id, PHORUM_DELETE_MESSAGE);
        }
    }
    $PHORUM["forum_id"] = $forum_id;
}
$nummsgs = count($msg_ids);
// Run a hook for performing custom actions after cleanup.
if (isset($PHORUM["hooks"]["delete"])) {
    phorum_api_hook("delete", $msg_ids);
}
$PHORUM['DATA']['OKMSG'] = $nummsgs . " " . $PHORUM["DATA"]["LANG"]['MsgDeletedOk'];
if (isset($PHORUM['args']['old_forum']) && !empty($PHORUM['args']['old_forum'])) {
    $PHORUM['forum_id'] = (int) $PHORUM['args']['old_forum'];
}
if (isset($PHORUM['args']["prepost"])) {
    $PHORUM['DATA']["URL"]["REDIRECT"] = phorum_api_url(PHORUM_CONTROLCENTER_URL, "panel=" . PHORUM_CC_UNAPPROVED);
} else {
    $PHORUM['DATA']["URL"]["REDIRECT"] = $PHORUM["DATA"]["URL"]["LIST"];
}
Beispiel #25
0
/**
 * Resolve the input and output files to use for a given template.
 *
 * @param string $page
 *     The template name (e.g. "header", "css", "foobar::frontpage", etc.).
 *
 * @return array
 *     This function returns an array, containing three elements:
 *     - The template name, which could be different from the input template
 *       name, because the "get_template_file" hook can override it.
 *     - The PHP file to include for rendering the template.
 *     - The file to use as the template source. When there is no
 *       pre-processing required for compiling the template source
 *       into the rendering PHP include file, then this value will
 *       be NULL.
 */
function phorum_api_template_resolve($page)
{
    global $PHORUM;
    $page = basename($page);
    /*
     * [hook]
     *     get_template_file
     *
     * [availability]
     *     Phorum 5 >= 5.2.11
     *
     * [description]
     *     Allow modules to have influence on the results of the
     *     phorum_api_template_resolve() function. This function translates
     *     a page name (e.g. <literal>list</literal>) into a filename
     *     to use as the template source for that page (e.g.
     *      <filename>/path/to/phorum/templates/emerald/list.tpl</filename>).
     *
     * [category]
     *     Page output
     *
     * [when]
     *     At the start of the api_template_resolve() function
     *     from <filename>include/api/template.php</filename>.
     *
     * [input]
     *     An array containing two elements:
     *     <ul>
     *       <li>page:
     *           The page that was requested.</li>
     *       <li>source:
     *           The file that has to be used as the source for the page.
     *           This one is initialized as NULL.</li>
     *     </ul>
     *
     * [output]
     *     Same as input. Modules can override either or both of the array
     *     elements. When the "source" element is set after running the
     *     hook, then the file named in this element is directly used as
     *     the template source. It must end in either ".php" or ".tpl" to
     *     be accepted as a template source. Phorum does not do any additional
     *     checking on this source file name. It is the module's duty to
     *     provide a correct source file name.<sbr/>
     *     Otherwise, the template source file is determined based on
     *     the value of the "page" element, following the standard
     *     Phorum template resolving rules.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_get_template_file($data)
     *     {
     *         // Override the "index_new" template with a custom
     *         // template from the "foo" module.
     *         if ($data['page'] == 'index_new') {
     *             $data['page'] = 'foo::index_new';
     *         }
     *
     *         // Point the "pm" template directly at a custom PHP script.
     *         if ($data['page'] == 'pm') {
     *             $data['source'] = './mods/foo/pm_output_handler.php';
     *         }
     *
     *         return $data;
     *     }
     *     </hookcode>
     */
    $tplbase = NULL;
    $template = NULL;
    if (isset($GLOBALS["PHORUM"]["hooks"]["get_template_file"])) {
        $res = phorum_api_hook("get_template_file", array('page' => $page, 'source' => NULL));
        $page = basename($res['page']);
        if ($res['source'] !== NULL && strlen($res['source']) > 4) {
            // PHP source can be returned right away. These will be included
            // directly by the template handling code.
            if (substr($res['source'], -4, 4) == '.php') {
                return array($page, $res['source'], NULL);
            }
            // For .tpl files, we continue running this function, because
            // a cache file name has to be compiled for storing the
            // compiled template data.
            if (substr($res['source'], -4, 4) == '.tpl') {
                $tplbase = substr($res['source'], 0, -4);
            }
        }
        $template = 'set_from_module';
    }
    // No template source set by a module? Then continue by finding
    // a template based on the provided template page name.
    if ($tplbase === NULL) {
        // Check for a module reference in the page name.
        $fullpage = $page;
        $module = NULL;
        if (($pos = strpos($fullpage, "::", 1)) !== FALSE) {
            $module = substr($fullpage, 0, $pos);
            $page = substr($fullpage, $pos + 2);
        }
        if ($module === NULL) {
            $prefix = $PHORUM['template_path'];
            // The postfix is used for checking if the template directory
            // contains at least the mandatory info.php file. Otherwise, it
            // could be an incomplete or empty template.
            $postfix = '/info.php';
        } else {
            $prefix = PHORUM_PATH . '/mods/' . basename($module) . '/templates';
            $postfix = '';
        }
        // If no user template is set or if the template cannot be found,
        // fallback to the configured default template. If that one can also
        // not be found, then fallback to the hard-coded default template.
        if (empty($PHORUM["template"]) || !file_exists("{$prefix}/{$PHORUM['template']}{$postfix}")) {
            $template = $PHORUM["default_forum_options"]["template"];
            if ($template != PHORUM_DEFAULT_TEMPLATE && !file_exists("{$prefix}/{$template}{$postfix}")) {
                $template = PHORUM_DEFAULT_TEMPLATE;
            }
            // If we're not handling a module template, then we can change the
            // global template to remember the fallback template and to make
            // sure that {URL->TEMPLATE} and {TEMPLATE} aren't pointing to a
            // non-existent template in the end..
            if ($module === NULL) {
                $PHORUM["template"] = $template;
            }
        } else {
            $template = $PHORUM['template'];
        }
        $tplbase = "{$prefix}/{$template}/{$page}";
        // check for straight PHP file
        if (file_exists("{$tplbase}.php")) {
            return array($page, "{$tplbase}.php", NULL);
        }
    }
    // Build the compiled template and template input file names.
    $tplfile = "{$tplbase}.tpl";
    $safetemplate = str_replace(array("-", ":"), array("_", "_"), $template);
    if (isset($module)) {
        $page = "{$module}::{$page}";
    }
    $safepage = str_replace(array("-", ":"), array("_", "_"), $page);
    $phpfile = "{$PHORUM['CACHECONFIG']['directory']}/tpl-{$safetemplate}-{$safepage}-" . md5(dirname(__FILE__) . $tplfile) . ".php";
    return array($page, $phpfile, $tplfile);
}
Beispiel #26
0
 *         global $PHORUM;
 *
 *         // Log the deleted message ids
 *         foreach ($msgthd_ids as $msgthd_id) {
 *             $PHORUM["mod_foo"]["deleted_messages"][] = $msgthd_id;
 *         }
 *         $PHORUM['DB']->update_settings(array(
 *             "mod_foo" => $PHORUM["mod_foo"]
 *         ));
 *
 *         return $msgthd_ids;
 *     }
 *     </hookcode>
 */
if (isset($PHORUM["hooks"]["delete"])) {
    phorum_api_hook("delete", array($msgthd_id));
}
$PHORUM['DATA']['OKMSG'] = "1 " . $PHORUM["DATA"]['LANG']['MsgDeletedOk'];
if (isset($PHORUM['args']['old_forum']) && !empty($PHORUM['args']['old_forum'])) {
    $PHORUM['forum_id'] = (int) $PHORUM['args']['old_forum'];
}
// Determine where to redirect to after the delete operation.
//
// When we're coming from the message moderation interface in
// the control center, then redirect back to there.
if (isset($PHORUM['args']["prepost"])) {
    $PHORUM['DATA']["URL"]["REDIRECT"] = phorum_api_url(PHORUM_CONTROLCENTER_URL, "panel=" . PHORUM_CC_UNAPPROVED);
} else {
    // If we did not delete the thread starter, then redirect
    // back to the parent of the deleted message.
    if ($message['parent_id']) {
Beispiel #27
0
 * [category]
 *     Miscellaneous
 *
 * [when]
 *     In the <filename>script.php</filename> when called from the command
 *     prompt or a script file.
 *
 * [input]
 *     Any array of arguments. (Optional)
 *
 * [output]
 *     Same as input.
 */
if ($callhook == 'external') {
    $module = array_shift($modules);
    // The first argument in $callargs is set to the name of the
    // called module. This module name is not really needed, but it
    // in there for backward compatibility (in older code, all "external"
    // hooks were called and the external hook implementation had to check
    // the module name to see if it had to be run or not).
    array_unshift($callargs, $module);
    $callargs = array_values($callargs);
    // reindex (0, 1, 2, ...) array keys.
    // Call the external hook.
    phorum_api_hook("external", $callargs);
} elseif ($callhook == 'scheduled') {
    phorum_api_hook('scheduled');
} else {
    echo $PHORUM["DATA"]["LANG"]["ScriptUsage"];
    exit(1);
}
Beispiel #28
0
/**
 * Retrieve the maximum possible file upload size.
 *
 * This function determines the system's upload limit. This limit is
 * defined by the maximum upload filesize (PHP), the maximum POST request
 * size (PHP) and the maximum database packet size.
 *
 * @return array
 *     An array containing three elements:
 *     - The overall system's maximum upload size
 *     - The maximum as imposed by PHP
 *     - The maximum as imposed by the database
 */
function phorum_api_system_get_max_upload()
{
    global $PHORUM;
    // Determine limit as imposed by PHP.
    $pms = phorum_api_system_phpsize2bytes(ini_get('post_max_size'));
    $umf = phorum_api_system_phpsize2bytes(ini_get('upload_max_filesize'));
    $php_limit = $umf > $pms ? $pms : $umf;
    // Determines the database server's limit for file uploads. This limit
    // is determined by the maximum packet size that the database can handle.
    // We asume that there's a 40% overhead in the packet, so that 60% of
    // the packet can be used for sending an uploaded file to the database.
    $db_limit = $PHORUM['DB']->maxpacketsize();
    if ($db_limit != NULL) {
        $db_limit = $db_limit * 0.6;
    }
    $limit = $php_limit;
    if ($db_limit && $db_limit < $php_limit) {
        $limit = $db_limit;
    }
    $data = array($limit, $php_limit, $db_limit);
    /*
     * [hook]
     *     system_max_upload
     *
     * [description]
     *     This hook allows a module to control the maximum file size for
     *     a file upload.  Most notable would be file system storage.  It
     *     could ignore the db_limit.
     *
     * [category]
     *     File storage
     *
     * [when]
     *     In <filename>include/api/system.php</filename>,
     *     in the function phorum_api_system_get_max_upload().
     *
     * [input]
     *     An array containing the default limit, the data layer limit and
     *     the PHP limit
     *
     * [output]
     *     A 3 part array with the limits adjusted as you wish.  The first
     *     element in the array would be the most important.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_system_max_upload($data)
     *     {
     *         // ignore the db_limit
     *         $data[0] = $data[2];
     *         return $data;
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM["hooks"]["system_max_upload"])) {
        $data = phorum_api_hook("system_max_upload", $data);
    }
    return $data;
}
Beispiel #29
0
/**
 * Wrapper function to handle most common output scenarios.
 *
 * @param string|array $templates
 *     If a string, then that template is included.
 *     If an array, then all templates are included in the order of the array.
 */
function phorum_api_output($templates)
{
    if (!is_array($templates)) {
        $templates = array($templates);
    }
    /*
     * [hook]
     *     output_templates
     *
     * [description]
     *     This hook can be used to alter the list of templates that
     *     will be displayed by the phorum_api_output() call.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     Before sending any output from phorum_api_output().
     *
     * [input]
     *     An array, containing the names of the templates to display
     *     in the page body (between the header and footer template).
     *
     * [output]
     *     Same as input, possibly modified.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_output_templates($templates)
     *     {
     *         // Add some advertisements at the top and bottom of the page.
     *         array_unshift($templates, "foo::top_advertisement);
     *         array_push($templates, "foo::bottom_advertisement);
     *
     *         return $templates;
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM['hooks']['output_templates'])) {
        $templates = phorum_api_hook('output_templates', $templates);
    }
    /* 
     * [availability]
     *     Phorum 5 >= 5.2.16
     *
     * [hook]
     *     output_templates_<page>
     *
     * [description]
     *     This hook provides the same functionality as the
     *     <hook>output_templates</hook> hook. The difference is that this
     *     hook is called for a specific phorum_page, which makes
     *     this a lightweight hook if you only need to do processing
     *     for a single phorum_page.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     Before sending any output from phorum_api_output().
     *
     * [input]
     *     An array, containing the names of the templates to display
     *     in the page body (between the header and footer template).
     *
     * [output]
     *     Same as input, possibly modified.
     */
    if (isset($GLOBALS['PHORUM']['hooks']['output_templates_' . phorum_page])) {
        $templates = phorum_api_hook('output_templates_' . phorum_page, $templates);
    }
    /*
     * [hook]
     *     start_output
     *
     * [description]
     *     This hook gives modules a chance to apply some last minute
     *     changes to the Phorum data. You can also use this hook to
     *     call <phpfunc>ob_start</phpfunc> if you need to buffer Phorum's
     *     full output (e.g. to do some post processing on the data
     *     from the <hook>end_output</hook> hook.<sbr/>
     *     <sbr/>
     *     Note: this hook is only called for standard pages (the ones
     *     that are constructed using a header, body and footer) and not
     *     for output from scripts that do raw output like
     *     <filename>file.php</filename>, <filename>javascript.php</filename>,
     *     <filename>css.php</filename> and <filename>rss.php</filename>.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After setting up all Phorum data, right before sending the
     *     page header template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_start_output()
     *     {
     *         global $PHORUM;
     *
     *         // Add some custom data to the page title.
     *         $title = $PHORUM['DATA']['HTML_TITLE'];
     *         $PHORUM['DATA']['HTML_TITLE'] = "-=| Phorum Rocks! |=- $title";
     *     }
     *     </hookcode>
     */
    if (isset($GLOBALS['PHORUM']['hooks']['start_output'])) {
        phorum_api_hook('start_output');
    }
    /* 
     * [availability]
     *     Phorum 5 >= 5.2.16
     *
     * [hook]
     *     start_output_<page>
     *
     * [description]
     *     This hook provides the same functionality as the
     *     <hook>start_output</hook> hook. The difference is that this
     *     hook is called for a specific phorum_page, which makes
     *     this a lightweight hook if you only need to do processing
     *     for a single phorum_page.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After setting up all Phorum data, right before sending the
     *     page header template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     */
    if (isset($GLOBALS['PHORUM']['hooks']['start_output_' . phorum_page])) {
        phorum_api_hook('start_output_' . phorum_page);
    }
    // Add some information to the breadcrumbs to make it easy for the
    // templates to apply different styling for the first and the
    // last (i.e. the currently active) breadcrumbs item.
    //
    // Reindex the array. It might not be sequential, due to module tinkering.
    $bc =& $GLOBALS['PHORUM']['DATA']['BREADCRUMBS'];
    $bc = array_values($bc);
    // Add a "FIRST" and "LAST" field to the appropriate records.
    $bc[0]['FIRST'] = TRUE;
    $bc[count($bc) - 1]['LAST'] = TRUE;
    // Copy only what we need into the current scope. We do this at
    // this point and not earlier, so the hooks before this code can be
    // used for changing values in the $PHORUM data.
    $PHORUM = array('DATA' => $GLOBALS['PHORUM']['DATA'], 'locale' => $GLOBALS['PHORUM']['locale'], 'hooks' => $GLOBALS['PHORUM']['hooks']);
    include phorum_api_template('header');
    /*
     * [hook]
     *     after_header
     *
     * [description]
     *     This hook can be used for adding content to the pages that is
     *     displayed after the page header template, but before the main
     *     page content.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the page header template, but before sending the
     *     main page content.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_after_header()
     *     {
     *         // Only add data after the header for the index and list pages.
     *         if (phorum_page != 'index' && phorum_page != 'list') return;
     *
     *         // Add some static notification after the header.
     *         print '<div style="border:1px solid orange; padding: 1em">';
     *         print 'Welcome to our forums!';
     *         print '</div>';
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM['hooks']['after_header'])) {
        phorum_api_hook('after_header');
    }
    /* 
     * [availability]
     *     Phorum 5 >= 5.2.16
     *
     * [hook]
     *     after_header_<page>
     *
     * [description]
     *     This hook provides the same functionality as the
     *     <hook>after_header</hook> hook. The difference is that this
     *     hook is called for a specific phorum_page, which makes
     *     this a lightweight hook if you only need to do processing
     *     for a single phorum_page.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the page header template, but before sending the
     *     main page content.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     */
    if (isset($GLOBALS['PHORUM']['hooks']['after_header_' . phorum_page])) {
        phorum_api_hook('after_header_' . phorum_page);
    }
    foreach ($templates as $template) {
        include phorum_api_template($template);
    }
    /* 
     * [availability]
     *     Phorum 5 >= 5.2.16
     *
     * [hook]
     *     before_footer_<page>
     *
     * [description]
     *     This hook provides the same functionality as the
     *     <hook>before_footer</hook> hook. The difference is that this
     *     hook is called for a specific phorum_page, which makes
     *     this a lightweight hook if you only need to do processing
     *     for a single phorum_page.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the main page content, but before sending the
     *     page footer template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     */
    if (isset($GLOBALS['PHORUM']['hooks']['before_footer_' . phorum_page])) {
        phorum_api_hook('before_footer_' . phorum_page);
    }
    /*
     * [hook]
     *     before_footer
     *
     * [description]
     *     This hook can be used for adding content to the pages that is
     *     displayed after the main page content, but before the page footer.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the main page content, but before sending the
     *     page footer template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_before_footer()
     *     {
     *         // Add some static notification before the footer.
     *         print '<div style="font-size: 90%">';
     *         print '  For technical support, please send a mail to ';
     *         print '  <a href="mailto:tech@example.com">the webmaster</a>.';
     *         print '</div>';
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM['hooks']['before_footer'])) {
        phorum_api_hook('before_footer');
    }
    include phorum_api_template('footer');
    /*
     * [hook]
     *     end_output
     *
     * [description]
     *     This hook can be used for performing post output tasks.
     *     One of the things that you could use this for, is for
     *     reading in buffered output using <phpfunc>ob_get_contents</phpfunc>
     *     in case you started buffering using <phpfunc>ob_start</phpfunc>
     *     from the <hook>start_output</hook> hook.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the page footer template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     *
     * [example]
     *     <hookcode>
     *     function phorum_mod_foo_end_output()
     *     {
     *         // Some made up call to some fake statistics package.
     *         include "/usr/share/lib/footracker.php";
     *         footracker_register_request();
     *     }
     *     </hookcode>
     */
    if (isset($PHORUM['hooks']['end_output'])) {
        phorum_api_hook('end_output');
    }
    /* 
     * [availability]
     *     Phorum 5 >= 5.2.16
     *
     * [hook]
     *     end_output_<page>
     *
     * [description]
     *     This hook provides the same functionality as the
     *     <hook>end_output</hook> hook. The difference is that this
     *     hook is called for a specific phorum_page, which makes
     *     this a lightweight hook if you only need to do processing
     *     for a single phorum_page.
     *
     * [category]
     *     Page output
     *
     * [when]
     *     After sending the page footer template.
     *
     * [input]
     *     No input.
     *
     * [output]
     *     No output.
     */
    if (isset($GLOBALS['PHORUM']['hooks']['end_output_' . phorum_page])) {
        phorum_api_hook('end_output_' . phorum_page);
    }
}
Beispiel #30
0
 *     has been moved by a moderator.
 *
 * [input]
 *     The id of the thread that has been moved (read-only).
 *
 * [output]
 *     Same as input.
 *
 * [example]
 *     <hookcode>
 *     function phorum_mod_foo_move_thread($msgthd_id)
 *     {
 *         global $PHORUM;
 *
 *         // Log the moved thread id
 *         $PHORUM["mod_foo"]["moved_threads"][] = $msgthd_id;
 *         $PHORUM['DB']->update_settings(array(
 *             "mod_foo" => $PHORUM["mod_foo"]
 *         ));
 *
 *         return $msgthd_id;
 *     }
 *     </hookcode>
 */
if (isset($PHORUM['hooks']['move_thread'])) {
    phorum_api_hook('move_thread', $msgthd_id);
}
// Register the messages for which the message cache must be cleared.
foreach ($message['meta']['message_ids'] as $message_id) {
    $invalidate_message_cache[] = array('message_id' => $message_id, 'forum_id' => $message['forum_id']);
}