/** * 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; }
* 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"]; }
* 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); }
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; }
* [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(); ?>
* 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);
* // 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") {
/** * 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); } }
* { * // 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,
* * [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;
$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); }
* * [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); }
* 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); }
/** * 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; }
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"];
* 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');
* $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"]);
$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']);
/** * 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); }
//////////////////////////////////////////////////////////////////////////////// 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']);
* [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; }
/** * 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; }
/** * 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; }
} } // 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"]; }
/** * 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); }
* 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']) {
* [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); }
/** * 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; }
/** * 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); } }
* 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']); }