// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // // // You should have received a copy of the Phorum License // // along with this program. // //////////////////////////////////////////////////////////////////////////////// define('phorum_page', 'read'); include_once "./common.php"; include_once "./include/email_functions.php"; include_once "./include/format_functions.php"; // for dev-purposes .. //include_once('./include/timing.php'); //timing_start(); // set all our URL's ... we need these earlier phorum_build_common_urls(); // checking read-permissions if (!phorum_check_read_common()) { return; } // somehow we got to a folder if ($PHORUM["folder_flag"]) { $dest_url = phorum_get_url(PHORUM_INDEX_URL, $PHORUM["forum_id"]); phorum_redirect_by_url($dest_url); exit; } $newflagkey = $PHORUM["forum_id"] . "-" . $PHORUM['user']['user_id']; if ($PHORUM["DATA"]["LOGGEDIN"]) { // reading newflags in $PHORUM['user']['newinfo'] = null; if ($PHORUM['cache_newflags']) { $PHORUM['user']['newinfo'] = phorum_cache_get('newflags', $newflagkey, $PHORUM['cache_version']); }
/** * Check if a file exists and if the active user has permission to read it. * * The function will return either an array containing descriptive data * for the file or FALSE, in case access was not granted. * * Note that the file_data field is not available in the return array. * That data can be retrieved by the {@link phorum_api_file_retrieve()} * function. * * @param integer $file_id * The file_id of the file for which to check read access. * * @param integer $flags * If the {@link PHORUM_FLAG_IGNORE_PERMS} flag is used, then permission * checks are fully bypassed. In this case, the function will only check * if the file exists or not. * * @return mixed * On error, this function will return FALSE. * The functions {@link phorum_api_strerror()} and * {@link phorum_api_errno()} can be used to retrieve information about * the error which occurred. * * On success, it returns an array containing descriptive data for * the file. The following fields are available in this array: * <ul> * <li>file_id: The file_id for the requested file.</li> * <li>filename: The name of the file.</li> * <li>filesize: The size of the file in bytes.</li> * <li>add_datetime: Epoch timestamp describing at what time * the file was stored.</li> * <li>message_id: The message to which a message is linked * (in case it is a message attachment).</li> * <li>user_id: The user to which a message is linked * (in case it is a private user file).</li> * <li>link: A value describing to what type of entity the file is * linked. One of {@link PHORUM_LINK_USER}, * {@link PHORUM_LINK_MESSAGE}, {@link PHORUM_LINK_EDITOR} and * {@link PHORUM_LINK_TEMPFILE}.</li> * </ul> */ function phorum_api_file_check_read_access($file_id, $flags = 0) { global $PHORUM; settype($file_id, "int"); // Reset error storage. $GLOBALS["PHORUM"]["API"]["errno"] = NULL; $GLOBALS["PHORUM"]["API"]["error"] = NULL; // Check if the active user has read access for the active forum_id. if (!$flags & PHORUM_FLAG_IGNORE_PERMS && !phorum_check_read_common()) { return phorum_api_error_set(PHORUM_ERRNO_NOACCESS, "Read permission for file (id {$file_id}) denied."); } // Retrieve the descriptive file data for the file from the database. // Return an error if the file does not exist. $file = phorum_db_file_get($file_id, FALSE); if (empty($file)) { return phorum_api_error_set(PHORUM_ERRNO_NOTFOUND, "The requested file (id {$file_id}) was not found."); } // For the standard database based file storage, we do not have to // do checks for checking file existence (since the data is in the // database and we found the record for it). Storage modules might // have to do additional checks though (e.g. to see if the file data // exists on disk), so here we give them a chance to check for it. // This hook can also be used for implementing additional access // rules. The hook can use phorum_api_error_set() to return an error. // Hooks should be aware that their input might not be $file, but // FALSE instead, in which case they should immediately return // FALSE themselves. if (isset($PHORUM["hooks"]["file_check_read_access"])) { $file = phorum_hook("file_check_read_access", $file, $flags); if ($file === FALSE) { return FALSE; } } // If we do not do any permission checking, then we are done. if ($flags & PHORUM_FLAG_IGNORE_PERMS) { return $file; } // Is the file linked to a forum message? In that case, we have to // check if the message does really belong to the requested forum_id. if ($file["link"] == PHORUM_LINK_MESSAGE && !empty($file["message_id"])) { // Retrieve the message. If retrieving the message is not possible // or if the forum if of the message is different from the requested // forum_id, then return an error. $message = phorum_db_get_message($file["message_id"], "message_id", TRUE); if (empty($message)) { return phorum_api_error_set(PHORUM_ERRNO_INTEGRITY, "An integrity problem was detected in the database: " . "file id {$file_id} is linked to non existent " . "message_id {$file["message_id"]}."); } if ($message["forum_id"] != $PHORUM["forum_id"]) { return phorum_api_error_set(PHORUM_ERRNO_NOACCESS, "Permission denied for reading the file: it does not " . "belong to the requested forum_id {$PHORUM["forum_id"]}."); } } // A general purpose URL host matching regexp, that we'll use below. $matchhost = '!^https?://([^/]+)/!i'; // See if off site links are allowed. If this is not the case, then // check if an off site link is requested. We use the HTTP_REFERER for // doing the off site link check. This is not a water proof solution // (since HTTP referrers can be faked), but it will be good enough for // stopping the majority of the off site requests. if (isset($_SERVER["HTTP_REFERER"]) && $PHORUM["file_offsite"] != PHORUM_OFFSITE_ANYSITE && preg_match($matchhost, $_SERVER["HTTP_REFERER"])) { // Generate the base URL for the Phorum. $base = strtolower(phorum_get_url(PHORUM_BASE_URL)); // Strip query string from the base URL. We mainly want to // check if the location matches the Phorum location. // Otherwise, we might get in troubles with things like // URI authentication, where a session id is added to the URL. $base = preg_replace('/\\?.*$/', '', $base); // FORUMONLY: Links to forum files are only allowed from the forum. // Check if the referrer URL starts with the base Phorum URL. if ($PHORUM["file_offsite"] == PHORUM_OFFSITE_FORUMONLY) { $refbase = substr($_SERVER["HTTP_REFERER"], 0, strlen($base)); if (strcasecmp($base, $refbase) != 0) { return phorum_api_error_set(PHORUM_ERRNO_NOACCESS, "Permission denied: links to files in the forum are " . "only allowed from the forum itself."); } } elseif ($PHORUM["file_offsite"] == PHORUM_OFFSITE_THISSITE) { if (preg_match($matchhost, $_SERVER["HTTP_REFERER"], $rm) && preg_match($matchhost, $base, $bm) && strcasecmp($rm[1], $bm[1]) != 0) { return phorum_api_error_set(PHORUM_ERRNO_NOACCESS, "Permission denied: links to files in the forum are " . "only allowed from this web site."); } } } return $file; }