sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); $user->setup('posting', (int) $row['forum_style']); } else { $user->setup('posting'); } page_header($user->lang['SMILIES']); $sql = 'SELECT COUNT(smiley_id) AS item_count FROM ' . SMILIES_TABLE . ' GROUP BY smiley_url'; $result = $db->sql_query($sql, 3600); $smiley_count = 0; while ($row = $db->sql_fetchrow($result)) { ++$smiley_count; } $db->sql_freeresult($result); $template->set_filenames(array( 'body' => 'posting_smilies.html') ); $template->assign_var('PAGINATION', generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), $smiley_count, $config['smilies_per_page'], $start, true) ); } $display_link = false; if ($mode == 'inline') { $sql = 'SELECT smiley_id FROM ' . SMILIES_TABLE . ' WHERE display_on_posting = 0'; $result = $db->sql_query_limit($sql, 1, 0, 3600); if ($row = $db->sql_fetchrow($result)) { $display_link = true; } $db->sql_freeresult($result); } if ($mode == 'window') { $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height, MIN(smiley_order) AS min_smiley_order FROM ' . SMILIES_TABLE . ' GROUP BY smiley_url, smiley_width, smiley_height ORDER BY min_smiley_order'; $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600); } else { $sql = 'SELECT * FROM ' . SMILIES_TABLE . ' WHERE display_on_posting = 1 ORDER BY smiley_order'; $result = $db->sql_query($sql, 3600); } $smilies = array(); while ($row = $db->sql_fetchrow($result)) { if (empty($smilies[$row['smiley_url']])) { $smilies[$row['smiley_url']] = $row; } } $db->sql_freeresult($result); if (sizeof($smilies)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; foreach ($smilies as $row) { $template->assign_block_vars('smiley', array( 'SMILEY_CODE' => $row['code'], 'A_SMILEY_CODE' => addslashes($row['code']), 'SMILEY_IMG' => $root_path . $config['smilies_path'] . '/' . $row['smiley_url'], 'SMILEY_WIDTH' => $row['smiley_width'], 'SMILEY_HEIGHT' => $row['smiley_height'], 'SMILEY_DESC' => $row['emotion']) ); } } if ($mode == 'inline' && $display_link) { $template->assign_vars(array( 'S_SHOW_SMILEY_LINK' => true, 'U_MORE_SMILIES' => append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id)) ); } if ($mode == 'window') { page_footer(); } } /** * Update last post information * Should be used instead of sync() if only the last post information are out of sync... faster * * @param string $type Can be forum|topic * @param mixed $ids topic/forum ids * @param bool $return_update_sql true: SQL query shall be returned, false: execute SQL */ function update_post_information($type, $ids, $return_update_sql = false) { global $db; if (empty($ids)) { return; } if (!is_array($ids)) { $ids = array($ids); } $update_sql = $empty_forums = $not_empty_forums = array(); if ($type != 'topic') { $topic_join = ', ' . TOPICS_TABLE . ' t'; $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_approved = 1'; } else { $topic_join = ''; $topic_condition = ''; } if (sizeof($ids) == 1) { $sql = 'SELECT MAX(p.post_id) as last_post_id FROM ' . POSTS_TABLE . " p $topic_join WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " $topic_condition AND p.post_approved = 1"; } else { $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id FROM ' . POSTS_TABLE . " p $topic_join WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " $topic_condition AND p.post_approved = 1 GROUP BY p.{$type}_id"; } $result = $db->sql_query($sql); $last_post_ids = array(); while ($row = $db->sql_fetchrow($result)) { if (sizeof($ids) == 1) { $row[$type . '_id'] = $ids[0]; } if ($type == 'forum') { $not_empty_forums[] = $row['forum_id']; if (empty($row['last_post_id'])) { $empty_forums[] = $row['forum_id']; } } $last_post_ids[] = $row['last_post_id']; } $db->sql_freeresult($result); if ($type == 'forum') { $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums)); foreach ($empty_forums as $void => $forum_id) { $update_sql[$forum_id][] = 'forum_last_post_id = 0'; $update_sql[$forum_id][] = "forum_last_post_subject = ''"; $update_sql[$forum_id][] = 'forum_last_post_time = 0'; $update_sql[$forum_id][] = 'forum_last_poster_id = 0'; $update_sql[$forum_id][] = "forum_last_poster_name = ''"; $update_sql[$forum_id][] = "forum_last_poster_colour = ''"; } } if (sizeof($last_post_ids)) { $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND ' . $db->sql_in_set('p.post_id', $last_post_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id']; $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time']; $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id']; $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; } $db->sql_freeresult($result); } unset($empty_forums, $ids, $last_post_ids); if ($return_update_sql || !sizeof($update_sql)) { return $update_sql; } $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE; foreach ($update_sql as $update_id => $update_sql_ary) { $sql = "UPDATE $table SET " . implode(', ', $update_sql_ary) . " WHERE {$type}_id = $update_id"; $db->sql_query($sql); } return; } /** * Generate Topic Icons for display */ function posting_gen_topic_icons($mode, $icon_id) { global $phpbb_root_path, $config, $template, $cache; // Grab icons $icons = $cache->obtain_icons(); if (!$icon_id) { $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); } if (sizeof($icons)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; foreach ($icons as $id => $data) { if ($data['display']) { $template->assign_block_vars('topic_icon', array( 'ICON_ID' => $id, 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'], 'ICON_WIDTH' => $data['width'], 'ICON_HEIGHT' => $data['height'], 'S_CHECKED' => ($id == $icon_id) ? true : false, 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '') ); } } return true; } return false; } /** * Build topic types able to be selected */ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) { global $auth, $user, $template, $topic_type; $toggle = false; $topic_types = array( 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') ); $topic_type_array = array(); foreach ($topic_types as $auth_key => $topic_value) { // We do not have a special post global announcement permission $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key; if ($auth->acl_get('f_' . $auth_key, $forum_id)) { $toggle = true; $topic_type_array[] = array( 'VALUE' => $topic_value['const'], 'S_CHECKED' => ($cur_topic_type == $topic_value['const'] || ($forum_id == 0 && $topic_value['const'] == POST_GLOBAL)) ? ' checked="checked"' : '', 'L_TOPIC_TYPE' => $user->lang[$topic_value['lang']] ); } } if ($toggle) { $topic_type_array = array_merge(array(0 => array( 'VALUE' => POST_NORMAL, 'S_CHECKED' => ($cur_topic_type == POST_NORMAL) ? ' checked="checked"' : '', 'L_TOPIC_TYPE' => $user->lang['POST_NORMAL'])), $topic_type_array ); foreach ($topic_type_array as $array) { $template->assign_block_vars('topic_type', $array); } $template->assign_vars(array( 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->acl_get('f_announce', $forum_id))) ); } return $toggle; } // // Attachment related functions // /** * Upload Attachment - filedata is generated here * Uses upload class */ function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false) { global $auth, $user, $config, $db, $cache; global $phpbb_root_path, $phpEx; $filedata = array( 'error' => array() ); include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); $upload = new fileupload(); if ($config['check_attachment_content'] && isset($config['mime_triggers'])) { $upload->set_disallowed_content(explode('|', $config['mime_triggers'])); } if (!$local) { $filedata['post_attach'] = ($upload->is_valid($form_name)) ? true : false; } else { $filedata['post_attach'] = true; } if (!$filedata['post_attach']) { $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND']; return $filedata; } $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id)); $upload->set_allowed_extensions(array_keys($extensions['_allowed_'])); $file = ($local) ? $upload->local_upload($local_storage, $local_filedata) : $upload->form_upload($form_name); if ($file->init_error) { $filedata['post_attach'] = false; return $filedata; } $cat_id = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] : ATTACHMENT_CATEGORY_NONE; // Do we have to create a thumbnail? $filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && $config['img_create_thumbnail']) ? 1 : 0; // Check Image Size, if it is an image if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id) && $cat_id == ATTACHMENT_CATEGORY_IMAGE) { $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']); } // Admins and mods are allowed to exceed the allowed filesize if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id)) { if (!empty($extensions[$file->get('extension')]['max_filesize'])) { $allowed_filesize = $extensions[$file->get('extension')]['max_filesize']; } else { $allowed_filesize = ($is_message) ? $config['max_filesize_pm'] : $config['max_filesize']; } $file->upload->set_max_filesize($allowed_filesize); } $file->clean_filename('unique', $user->data['user_id'] . '_'); // Are we uploading an image *and* this image being within the image category? Only then perform additional image checks. $no_image = ($cat_id == ATTACHMENT_CATEGORY_IMAGE) ? false : true; $file->move_file($config['upload_path'], false, $no_image); if (sizeof($file->error)) { $file->remove(); $filedata['error'] = array_merge($filedata['error'], $file->error); $filedata['post_attach'] = false; return $filedata; } // Make sure the image category only holds valid images... if ($cat_id == ATTACHMENT_CATEGORY_IMAGE && !$file->is_image()) { $file->remove(); // If this error occurs a user tried to exploit an IE Bug by renaming extensions // Since the image category is displaying content inline we need to catch this. trigger_error($user->lang['ATTACHED_IMAGE_NOT_IMAGE']); } $filedata['filesize'] = $file->get('filesize'); $filedata['mimetype'] = $file->get('mimetype'); $filedata['extension'] = $file->get('extension'); $filedata['physical_filename'] = $file->get('realname'); $filedata['real_filename'] = $file->get('uploadname'); $filedata['filetime'] = time(); // Check our complete quota if ($config['attachment_quota']) { if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota']) { $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; $filedata['post_attach'] = false; $file->remove(); return $filedata; } } // Check free disk space if ($free_space = @disk_free_space($phpbb_root_path . $config['upload_path'])) { if ($free_space <= $file->get('filesize')) { if ($auth->acl_get('a_')) { $filedata['error'][] = $user->lang['ATTACH_DISK_FULL']; } else { $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; } $filedata['post_attach'] = false; $file->remove(); return $filedata; } } // Create Thumbnail if ($filedata['thumbnail']) { $source = $file->get('destination_file'); $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname'); if (!create_thumbnail($source, $destination, $file->get('mimetype'))) { $filedata['thumbnail'] = 0; } } return $filedata; } /** * Calculate the needed size for Thumbnail */ function get_img_size_format($width, $height) { global $config; // Maximum Width the Image can take $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400; if ($width > $height) { return array( round($width * ($max_width / $width)), round($height * ($max_width / $width)) ); } else { return array( round($width * ($max_width / $height)), round($height * ($max_width / $height)) ); } } /** * Return supported image types */ function get_supported_image_types($type = false) { if (@extension_loaded('gd')) { $format = imagetypes(); $new_type = 0; if ($type !== false) { // Type is one of the IMAGETYPE constants - it is fetched from getimagesize() // We do not use the constants here, because some were not available in PHP 4.3.x switch ($type) { // GIF case 1: $new_type = ($format & IMG_GIF) ? IMG_GIF : false; break; // JPG, JPC, JP2 case 2: case 9: case 10: case 11: case 12: $new_type = ($format & IMG_JPG) ? IMG_JPG : false; break; // PNG case 3: $new_type = ($format & IMG_PNG) ? IMG_PNG : false; break; // WBMP case 15: $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false; break; } } else { $new_type = array(); $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP); foreach ($go_through_types as $check_type) { if ($format & $check_type) { $new_type[] = $check_type; } } } return array( 'gd' => ($new_type) ? true : false, 'format' => $new_type, 'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1 ); } return array('gd' => false); } /** * Create Thumbnail */ function create_thumbnail($source, $destination, $mimetype) { global $config; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; if (!$img_filesize || $img_filesize <= $min_filesize) { return false; } $dimension = @getimagesize($source); if ($dimension === false) { return false; } list($width, $height, $type, ) = $dimension; if (empty($width) || empty($height)) { return false; } list($new_width, $new_height) = get_img_size_format($width, $height); // Do not create a thumbnail if the resulting width/height is bigger than the original one if ($new_width >= $width && $new_height >= $height) { return false; } $used_imagick = false; // Only use imagemagick if defined and the passthru function not disabled if ($config['img_imagick'] && function_exists('passthru')) { if (substr($config['img_imagick'], -1) !== '/') { $config['img_imagick'] .= '/'; } @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"'); if (file_exists($destination)) { $used_imagick = true; } } if (!$used_imagick) { $type = get_supported_image_types($type); if ($type['gd']) { // If the type is not supported, we are not able to create a thumbnail if ($type['format'] === false) { return false; } switch ($type['format']) { case IMG_GIF: $image = @imagecreatefromgif($source); break; case IMG_JPG: @ini_set('gd.jpeg_ignore_warning', 1); $image = @imagecreatefromjpeg($source); break; case IMG_PNG: $image = @imagecreatefrompng($source); break; case IMG_WBMP: $image = @imagecreatefromwbmp($source); break; } if (empty($image)) { return false; } if ($type['version'] == 1) { $new_image = imagecreate($new_width, $new_height); if ($new_image === false) { return false; } imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } else { $new_image = imagecreatetruecolor($new_width, $new_height); if ($new_image === false) { return false; } // Preserve alpha transparency (png for example) @imagealphablending($new_image, false); @imagesavealpha($new_image, true); imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on') { @touch($destination); } switch ($type['format']) { case IMG_GIF: imagegif($new_image, $destination); break; case IMG_JPG: imagejpeg($new_image, $destination, 90); break; case IMG_PNG: imagepng($new_image, $destination); break; case IMG_WBMP: imagewbmp($new_image, $destination); break; } imagedestroy($new_image); } else { return false; } } if (!file_exists($destination)) { return false; } phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); return true; } /** * Assign Inline attachments (build option fields) */ function posting_gen_inline_attachments(&$attachment_data) { global $template; if (sizeof($attachment_data)) { $s_inline_attachment_options = ''; foreach ($attachment_data as $i => $attachment) { $s_inline_attachment_options .= ''; } $template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options); return true; } return false; } /** * Generate inline attachment entry */ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true) { global $template, $config, $phpbb_root_path, $phpEx, $user, $auth; // Some default template variables $template->assign_vars(array( 'S_SHOW_ATTACH_BOX' => $show_attach_box, 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), 'FILESIZE' => $config['max_filesize'], 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', )); if (sizeof($attachment_data)) { // We display the posted attachments within the desired order. ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); foreach ($attachment_data as $count => $attach_row) { $hidden = ''; $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']); foreach ($attach_row as $key => $value) { $hidden .= ''; } $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false); $template->assign_block_vars('attach_row', array( 'FILENAME' => utf8_basename($attach_row['real_filename']), 'A_FILENAME' => addslashes(utf8_basename($attach_row['real_filename'])), 'FILE_COMMENT' => $attach_row['attach_comment'], 'ATTACH_ID' => $attach_row['attach_id'], 'S_IS_ORPHAN' => $attach_row['is_orphan'], 'ASSOC_INDEX' => $count, 'U_VIEW_ATTACHMENT' => $download_link, 'S_HIDDEN' => $hidden) ); } } return sizeof($attachment_data); } // // General Post functions // /** * Load Drafts */ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $msg_id = 0) { global $user, $db, $template, $auth; global $phpbb_root_path, $phpEx; $topic_ids = $forum_ids = $draft_rows = array(); // Load those drafts not connected to forums/topics // If forum_id == 0 AND topic_id == 0 then this is a PM draft if (!$topic_id && !$forum_id) { $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0'; } else { $sql_and = ''; $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : ''; $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : ''; } $sql = 'SELECT d.*, f.forum_id, f.forum_name FROM ' . DRAFTS_TABLE . ' d LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id) WHERE d.user_id = ' . $user->data['user_id'] . " $sql_and ORDER BY d.save_time DESC"; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { if ($row['topic_id']) { $topic_ids[] = (int) $row['topic_id']; } $draft_rows[] = $row; } $db->sql_freeresult($result); if (!sizeof($draft_rows)) { return; } $topic_rows = array(); if (sizeof($topic_ids)) { $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $topic_rows[$row['topic_id']] = $row; } $db->sql_freeresult($result); } unset($topic_ids); $template->assign_var('S_SHOW_DRAFTS', true); foreach ($draft_rows as $draft) { $link_topic = $link_forum = $link_pm = false; $insert_url = $view_url = $title = ''; if (isset($topic_rows[$draft['topic_id']]) && ( ($topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) || (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->acl_getf_global('f_read')) )) { $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id; $link_topic = true; $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']); $title = $topic_rows[$draft['topic_id']]['topic_title']; $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); } else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id'])) { $link_forum = true; $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']); $title = $draft['forum_name']; $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); } else { // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards... $link_pm = true; $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}" . (($pm_action) ? "&action=$pm_action" : '') . (($msg_id) ? "&p=$msg_id" : '')); } $template->assign_block_vars('draftrow', array( 'DRAFT_ID' => $draft['draft_id'], 'DATE' => $user->format_date($draft['save_time']), 'DRAFT_SUBJECT' => $draft['draft_subject'], 'TITLE' => $title, 'U_VIEW' => $view_url, 'U_INSERT' => $insert_url, 'S_LINK_PM' => $link_pm, 'S_LINK_TOPIC' => $link_topic, 'S_LINK_FORUM' => $link_forum) ); } } /** * Topic Review */ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) { global $user, $auth, $db, $template, $bbcode, $cache; global $config, $phpbb_root_path, $phpEx; // Go ahead and pull all data for this topic $sql = 'SELECT p.post_id FROM ' . POSTS_TABLE . ' p' . " WHERE p.topic_id = $topic_id " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . ' ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . ' ORDER BY p.post_time '; $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC'; $result = $db->sql_query_limit($sql, $config['posts_per_page']); $post_list = array(); while ($row = $db->sql_fetchrow($result)) { $post_list[] = $row['post_id']; } $db->sql_freeresult($result); if (!sizeof($post_list)) { return false; } // Handle 'post_review_edit' like 'post_review' from now on if ($mode == 'post_review_edit') { $mode = 'post_review'; } $sql = $db->sql_build_query('SELECT', array( 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', 'FROM' => array( USERS_TABLE => 'u', POSTS_TABLE => 'p', ), 'LEFT_JOIN' => array( array( 'FROM' => array(ZEBRA_TABLE => 'z'), 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id' ) ), 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' AND u.user_id = p.poster_id' )); $result = $db->sql_query($sql); $bbcode_bitfield = ''; $rowset = array(); $has_attachments = false; while ($row = $db->sql_fetchrow($result)) { $rowset[$row['post_id']] = $row; $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); if ($row['post_attachment']) { $has_attachments = true; } } $db->sql_freeresult($result); // Instantiate BBCode class if (!isset($bbcode) && $bbcode_bitfield !== '') { include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); $bbcode = new bbcode(base64_encode($bbcode_bitfield)); } // Grab extensions $extensions = $attachments = array(); if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) { $extensions = $cache->obtain_attach_extensions($forum_id); // Get attachments... $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . ' AND in_message = 0 ORDER BY filetime DESC, post_msg_id ASC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $attachments[$row['post_msg_id']][] = $row; } $db->sql_freeresult($result); } for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) { // A non-existing rowset only happens if there was no user present for the entered poster_id // This could be a broken posts table. if (!isset($rowset[$post_list[$i]])) { continue; } $row =& $rowset[$post_list[$i]]; $poster_id = $row['user_id']; $post_subject = $row['post_subject']; $message = censor_text($row['post_text']); $decoded_message = false; if ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) { $decoded_message = $message; decode_message($decoded_message, $row['bbcode_uid']); $decoded_message = bbcode_nl2br($decoded_message); } if ($row['bbcode_bitfield']) { $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); } $message = bbcode_nl2br($message); $message = smiley_text($message, !$row['enable_smilies']); if (!empty($attachments[$row['post_id']])) { $update_count = array(); parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count); } $post_subject = censor_text($post_subject); $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; $u_show_post = append_sid($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); $template->assign_block_vars($mode . '_row', array( 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, 'S_FRIEND' => ($row['friend']) ? true : false, 'S_IGNORE_POST' => ($row['foe']) ? true : false, 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "", '') : '', 'POST_SUBJECT' => $post_subject, 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 'POST_DATE' => $user->format_date($row['post_time']), 'MESSAGE' => $message, 'DECODED_MESSAGE' => $decoded_message, 'POST_ID' => $row['post_id'], 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '') ); // Display not already displayed Attachments for this post, we already parsed them. ;) if (!empty($attachments[$row['post_id']])) { foreach ($attachments[$row['post_id']] as $attachment) { $template->assign_block_vars($mode . '_row.attachment', array( 'DISPLAY_ATTACHMENT' => $attachment) ); } } unset($rowset[$post_list[$i]]); } if ($mode == 'topic_review') { $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE'])); } return true; } /** * User Notification */ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id, $author_name = '') { global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; $topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false; $forum_notification = ($mode == 'post') ? true : false; if (!$topic_notification && !$forum_notification) { trigger_error('NO_MODE'); } if (($topic_notification && !$config['allow_topic_notify']) || ($forum_notification && !$config['allow_forum_notify'])) { return; } $topic_title = ($topic_notification) ? $topic_title : $subject; $topic_title = censor_text($topic_title); // Exclude guests, current user and banned users from notifications if (!function_exists('phpbb_get_banned_user_ids')) { include($phpbb_root_path . 'includes/functions_user.' . $phpEx); } $sql_ignore_users = phpbb_get_banned_user_ids(); $sql_ignore_users[ANONYMOUS] = ANONYMOUS; $sql_ignore_users[$user->data['user_id']] = $user->data['user_id']; $notify_rows = array(); // -- get forum_userids || topic_userids $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . ' AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . ' AND w.notify_status = ' . NOTIFY_YES . ' AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') AND u.user_id = w.user_id'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $notify_user_id = (int) $row['user_id']; $notify_rows[$notify_user_id] = array( 'user_id' => $notify_user_id, 'username' => $row['username'], 'user_email' => $row['user_email'], 'user_jabber' => $row['user_jabber'], 'user_lang' => $row['user_lang'], 'notify_type' => ($topic_notification) ? 'topic' : 'forum', 'template' => ($topic_notification) ? 'topic_notify' : 'newtopic_notify', 'method' => $row['user_notify_type'], 'allowed' => false ); // Add users who have been already notified to ignore list $sql_ignore_users[$notify_user_id] = $notify_user_id; } $db->sql_freeresult($result); // forum notification is sent to those not already receiving topic notifications if ($topic_notification) { $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u WHERE fw.forum_id = $forum_id AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . ' AND fw.notify_status = ' . NOTIFY_YES . ' AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') AND u.user_id = fw.user_id'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { $notify_user_id = (int) $row['user_id']; $notify_rows[$notify_user_id] = array( 'user_id' => $notify_user_id, 'username' => $row['username'], 'user_email' => $row['user_email'], 'user_jabber' => $row['user_jabber'], 'user_lang' => $row['user_lang'], 'notify_type' => 'forum', 'template' => 'forum_notify', 'method' => $row['user_notify_type'], 'allowed' => false ); } $db->sql_freeresult($result); } if (!sizeof($notify_rows)) { return; } // Make sure users are allowed to read the forum foreach ($auth->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary) { foreach ($forum_ary as $auth_option => $user_ary) { foreach ($user_ary as $user_id) { $notify_rows[$user_id]['allowed'] = true; } } } // Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;) $msg_users = $delete_ids = $update_notification = array(); foreach ($notify_rows as $user_id => $row) { if (!$row['allowed'] || !trim($row['user_email'])) { $delete_ids[$row['notify_type']][] = $row['user_id']; } else { $msg_users[] = $row; $update_notification[$row['notify_type']][] = $row['user_id']; /* * We also update the forums watch table for this user when we are * sending out a topic notification to prevent sending out another * notification in case this user is also subscribed to the forum * this topic was posted in. * Since an UPDATE query is used, this has no effect on users only * subscribed to the topic (i.e. no row is created) and should not * be a performance issue. */ if ($row['notify_type'] === 'topic') { $update_notification['forum'][] = $row['user_id']; } } } unset($notify_rows); // Now, we are able to really send out notifications if (sizeof($msg_users)) { include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); $messenger = new messenger(); $msg_list_ary = array(); foreach ($msg_users as $row) { $pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]); $msg_list_ary[$row['template']][$pos]['method'] = $row['method']; $msg_list_ary[$row['template']][$pos]['email'] = $row['user_email']; $msg_list_ary[$row['template']][$pos]['jabber'] = $row['user_jabber']; $msg_list_ary[$row['template']][$pos]['name'] = $row['username']; $msg_list_ary[$row['template']][$pos]['lang'] = $row['user_lang']; $msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id']; } unset($msg_users); foreach ($msg_list_ary as $email_template => $email_list) { foreach ($email_list as $addr) { $messenger->template($email_template, $addr['lang']); $messenger->to($addr['email'], $addr['name']); $messenger->im($addr['jabber'], $addr['name']); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($addr['name']), 'TOPIC_TITLE' => htmlspecialchars_decode($topic_title), 'FORUM_NAME' => htmlspecialchars_decode($forum_name), 'AUTHOR_NAME' => htmlspecialchars_decode($author_name), 'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id", 'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id", 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", )); $messenger->send($addr['method']); } } unset($msg_list_ary); $messenger->save_queue(); } // Handle the DB updates $db->sql_transaction('begin'); if (!empty($update_notification['topic'])) { $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . ' SET notify_status = ' . NOTIFY_NO . " WHERE topic_id = $topic_id AND " . $db->sql_in_set('user_id', $update_notification['topic']); $db->sql_query($sql); } if (!empty($update_notification['forum'])) { $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . ' SET notify_status = ' . NOTIFY_NO . " WHERE forum_id = $forum_id AND " . $db->sql_in_set('user_id', $update_notification['forum']); $db->sql_query($sql); } // Now delete the user_ids not authorised to receive notifications on this topic/forum if (!empty($delete_ids['topic'])) { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " WHERE topic_id = $topic_id AND " . $db->sql_in_set('user_id', $delete_ids['topic']); $db->sql_query($sql); } if (!empty($delete_ids['forum'])) { $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " WHERE forum_id = $forum_id AND " . $db->sql_in_set('user_id', $delete_ids['forum']); $db->sql_query($sql); } $db->sql_transaction('commit'); } // // Post handling functions // /** * Delete Post */ function delete_post($forum_id, $topic_id, $post_id, &$data) { global $db, $user, $auth; global $config, $phpEx, $phpbb_root_path; // Specify our post mode $post_mode = 'delete'; if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && $data['topic_replies_real'] == 0) { $post_mode = 'delete_topic'; } else if ($data['topic_first_post_id'] == $post_id) { $post_mode = 'delete_first_post'; } else if ($data['topic_last_post_id'] == $post_id) { $post_mode = 'delete_last_post'; } $sql_data = array(); $next_post_id = false; include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); $db->sql_transaction('begin'); // we must make sure to update forums that contain the shadow'd topic if ($post_mode == 'delete_topic') { $shadow_forum_ids = array(); $sql = 'SELECT forum_id FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_moved_id', $topic_id); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { if (!isset($shadow_forum_ids[(int) $row['forum_id']])) { $shadow_forum_ids[(int) $row['forum_id']] = 1; } else { $shadow_forum_ids[(int) $row['forum_id']]++; } } $db->sql_freeresult($result); } if (!delete_posts('post_id', array($post_id), false, false)) { // Try to delete topic, we may had an previous error causing inconsistency if ($post_mode == 'delete_topic') { delete_topics('topic_id', array($topic_id), false); } trigger_error('ALREADY_DELETED'); } $db->sql_transaction('commit'); // Collect the necessary information for updating the tables $sql_data[FORUMS_TABLE] = ''; switch ($post_mode) { case 'delete_topic': foreach ($shadow_forum_ids as $updated_forum => $topic_count) { // counting is fun! we only have to do sizeof($forum_ids) number of queries, // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_topics_real = forum_topics_real - ' . $topic_count . ', forum_topics = forum_topics - ' . $topic_count . ' WHERE forum_id = ' . $updated_forum); update_post_information('forum', $updated_forum); } delete_topics('topic_id', array($topic_id), false); if ($data['topic_type'] != POST_GLOBAL) { $sql_data[FORUMS_TABLE] .= 'forum_topics_real = forum_topics_real - 1'; $sql_data[FORUMS_TABLE] .= ($data['topic_approved']) ? ', forum_posts = forum_posts - 1, forum_topics = forum_topics - 1' : ''; } $update_sql = update_post_information('forum', $forum_id, true); if (sizeof($update_sql)) { $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); } break; case 'delete_first_post': $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id ORDER BY p.post_time ASC"; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); if ($data['topic_type'] != POST_GLOBAL) { $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; } $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "', topic_time = " . (int) $row['post_time']; // Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply" $sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); $next_post_id = (int) $row['post_id']; break; case 'delete_last_post': if ($data['topic_type'] != POST_GLOBAL) { $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; } $update_sql = update_post_information('forum', $forum_id, true); if (sizeof($update_sql)) { $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); } $sql_data[TOPICS_TABLE] = 'topic_bumped = 0, topic_bumper = 0, topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); $update_sql = update_post_information('topic', $topic_id, true); if (sizeof($update_sql)) { $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); } else { $sql = 'SELECT MAX(post_id) as last_post_id FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : ''); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); $next_post_id = (int) $row['last_post_id']; } break; case 'delete': $sql = 'SELECT post_id FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '') . ' AND post_time > ' . $data['post_time'] . ' ORDER BY post_time ASC'; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); if ($data['topic_type'] != POST_GLOBAL) { $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; } $sql_data[TOPICS_TABLE] = 'topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); $next_post_id = (int) $row['post_id']; break; } if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post')) { $sql = 'SELECT 1 AS has_attachments FROM ' . ATTACHMENTS_TABLE . ' WHERE topic_id = ' . $topic_id; $result = $db->sql_query_limit($sql, 1); $has_attachments = (int) $db->sql_fetchfield('has_attachments'); $db->sql_freeresult($result); if (!$has_attachments) { $sql_data[TOPICS_TABLE] .= ', topic_attachment = 0'; } } // $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : ''; $db->sql_transaction('begin'); $where_sql = array( FORUMS_TABLE => "forum_id = $forum_id", TOPICS_TABLE => "topic_id = $topic_id", USERS_TABLE => 'user_id = ' . $data['poster_id'] ); foreach ($sql_data as $table => $update_sql) { if ($update_sql) { $db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]); } } // Adjust posted info for this user by looking for a post by him/her within this topic... if ($post_mode != 'delete_topic' && $config['load_db_track'] && $data['poster_id'] != ANONYMOUS) { $sql = 'SELECT poster_id FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . $topic_id . ' AND poster_id = ' . $data['poster_id']; $result = $db->sql_query_limit($sql, 1); $poster_id = (int) $db->sql_fetchfield('poster_id'); $db->sql_freeresult($result); // The user is not having any more posts within this topic if (!$poster_id) { $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' WHERE topic_id = ' . $topic_id . ' AND user_id = ' . $data['poster_id']; $db->sql_query($sql); } } $db->sql_transaction('commit'); if ($data['post_reported'] && ($post_mode != 'delete_topic')) { sync('topic_reported', 'topic_id', array($topic_id)); } return $next_post_id; } /** * Submit Post * @todo Split up and create lightweight, simple API for this. */ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) { global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path; // We do not handle erasing posts here if ($mode == 'delete') { return false; } $current_time = time(); if ($mode == 'post') { $post_mode = 'post'; $update_message = true; } else if ($mode != 'edit') { $post_mode = 'reply'; $update_message = true; } else if ($mode == 'edit') { $post_mode = ($data['topic_replies_real'] == 0) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit')); } // First of all make sure the subject and topic title are having the correct length. // To achieve this without cutting off between special chars we convert to an array and then count the elements. $subject = truncate_string($subject); $data['topic_title'] = truncate_string($data['topic_title']); // Collect some basic information about which tables and which rows to update/insert $sql_data = $topic_row = array(); $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id']; // Retrieve some additional information if not present if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false)) { $sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE t.topic_id = p.topic_id AND p.post_id = ' . $data['post_id']; $result = $db->sql_query($sql); $topic_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); $data['topic_approved'] = $topic_row['topic_approved']; $data['post_approved'] = $topic_row['post_approved']; } // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval // The variable name should be $post_approved, because it indicates if the post is approved or not $post_approval = 1; // Check the permissions for post approval. // Moderators must go through post approval like ordinary users. if (!$auth->acl_get('f_noapprove', $data['forum_id'])) { // Post not approved, but in queue $post_approval = 0; } // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved if (isset($data['force_approved_state'])) { $post_approval = ($data['force_approved_state']) ? 1 : 0; } // Start the transaction here $db->sql_transaction('begin'); // Collect Information switch ($post_mode) { case 'post': case 'reply': $sql_data[POSTS_TABLE]['sql'] = array( 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'poster_id' => (int) $user->data['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_approved' => $post_approval, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => (!$user->data['is_registered']) ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0, 'post_edit_locked' => $data['post_edit_locked'] ); break; case 'edit_first_post': case 'edit': case 'edit_last_post': case 'edit_topic': // If edit reason is given always display edit info // If editing last post then display no edit info // If m_edit permission then display no edit info // If normal edit display edit info // Display edit info if edit reason given or user is editing his post, which is not the last within the topic. if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) { $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false); $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user'], ); $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1'; } else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) { $sql_data[POSTS_TABLE]['sql'] = array( 'post_edit_reason' => '', ); } // If the person editing this post is different to the one having posted then we will add a log entry stating the edit // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods if ($user->data['user_id'] != $poster_id) { $log_subject = ($subject) ? $subject : $data['topic_title']; add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : $user->lang['GUEST']); } if (!isset($sql_data[POSTS_TABLE]['sql'])) { $sql_data[POSTS_TABLE]['sql'] = array(); } $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], 'post_approved' => (!$post_approval) ? 0 : $data['post_approved'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']) ); if ($update_message) { $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message']; } break; } $post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved']; $topic_row = array(); // And the topic ladies and gentlemen switch ($post_mode) { case 'post': $sql_data[TOPICS_TABLE]['sql'] = array( 'topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => $post_approval, 'topic_title' => $subject, 'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, ); if (isset($poll['poll_options']) && !empty($poll['poll_options'])) { $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; $poll_length = $poll['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; if ($poll_start < 0) { $poll_start = 0; } $poll_length = 1; } $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( 'poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']) ); } $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); if ($topic_type != POST_GLOBAL) { if ($post_approval) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; } $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($post_approval) ? ', forum_topics = forum_topics + 1' : ''); } break; case 'reply': $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', topic_replies_real = topic_replies_real + 1, topic_bumped = 0, topic_bumper = 0' . (($post_approval) ? ', topic_replies = topic_replies + 1' : '') . ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); if ($post_approval && $topic_type != POST_GLOBAL) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; } break; case 'edit_topic': case 'edit_first_post': if (isset($poll['poll_options'])) { $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time; $poll_length = $poll['poll_length'] * 86400; if ($poll_length < 0) { $poll_start = $poll_start + $poll_length; if ($poll_start < 0) { $poll_start = 0; } $poll_length = 1; } } $sql_data[TOPICS_TABLE]['sql'] = array( 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => (!$post_approval) ? 0 : $data['topic_approved'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0, 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0), ); // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved if (!$post_approval && $data['topic_approved']) { // Do we need to grab some topic informations? if (!sizeof($topic_row)) { $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved FROM ' . TOPICS_TABLE . ' WHERE topic_id = ' . $data['topic_id']; $result = $db->sql_query($sql); $topic_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); } // If this is the only post remaining we do not need to decrement topic_replies. // Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again. // If this is an edited topic or the first post the topic gets completely disapproved later on... $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1); set_config_count('num_topics', -1, true); set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * (-1), true); // Only decrement this post, since this is the one non-approved now if ($auth->acl_get('f_postcount', $data['forum_id'])) { $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; } } break; case 'edit': case 'edit_last_post': // Correctly set back the topic replies and forum posts... but only if the post was approved before. if (!$post_approval && $data['post_approved']) { $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1'; set_config_count('num_posts', -1, true); if ($auth->acl_get('f_postcount', $data['forum_id'])) { $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; } } break; } // Submit new topic if ($post_mode == 'post') { $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); $db->sql_query($sql); $data['topic_id'] = $db->sql_nextid(); $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'topic_id' => $data['topic_id']) ); unset($sql_data[TOPICS_TABLE]['sql']); } // Submit new post if ($post_mode == 'post' || $post_mode == 'reply') { if ($post_mode == 'reply') { $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( 'topic_id' => $data['topic_id']) ); } $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); $db->sql_query($sql); $data['post_id'] = $db->sql_nextid(); if ($post_mode == 'post') { $sql_data[TOPICS_TABLE]['sql'] = array( 'topic_first_post_id' => $data['post_id'], 'topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => (int) $user->data['user_id'], 'topic_last_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), 'topic_last_poster_colour' => $user->data['user_colour'], 'topic_last_post_subject' => (string) $subject, ); } unset($sql_data[POSTS_TABLE]['sql']); } $make_global = false; // Are we globalising or unglobalising? if ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic') { if (!sizeof($topic_row)) { $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved, topic_last_post_id FROM ' . TOPICS_TABLE . ' WHERE topic_id = ' . $data['topic_id']; $result = $db->sql_query($sql); $topic_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); } // globalise/unglobalise? if (($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) || ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL)) { if (!empty($sql_data[FORUMS_TABLE]['stat']) && implode('', $sql_data[FORUMS_TABLE]['stat'])) { $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET ' . implode(', ', $sql_data[FORUMS_TABLE]['stat']) . ' WHERE forum_id = ' . $data['forum_id']); } $make_global = true; $sql_data[FORUMS_TABLE]['stat'] = array(); } // globalise if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) { // Decrement topic/post count $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies_real'] + 1); $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real - 1' . (($topic_row['topic_approved']) ? ', forum_topics = forum_topics - 1' : ''); // Update forum_ids for all posts $sql = 'UPDATE ' . POSTS_TABLE . ' SET forum_id = 0 WHERE topic_id = ' . $data['topic_id']; $db->sql_query($sql); } // unglobalise else if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) { // Increment topic/post count $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + ' . ($topic_row['topic_replies_real'] + 1); $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($topic_row['topic_approved']) ? ', forum_topics = forum_topics + 1' : ''); // Update forum_ids for all posts $sql = 'UPDATE ' . POSTS_TABLE . ' SET forum_id = ' . $data['forum_id'] . ' WHERE topic_id = ' . $data['topic_id']; $db->sql_query($sql); } } // Update the topics table if (isset($sql_data[TOPICS_TABLE]['sql'])) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' WHERE topic_id = ' . $data['topic_id']; $db->sql_query($sql); } // Update the posts table if (isset($sql_data[POSTS_TABLE]['sql'])) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' WHERE post_id = ' . $data['post_id']; $db->sql_query($sql); } // Update Poll Tables if (isset($poll['poll_options'])) { $cur_poll_options = array(); if ($mode == 'edit') { $sql = 'SELECT * FROM ' . POLL_OPTIONS_TABLE . ' WHERE topic_id = ' . $data['topic_id'] . ' ORDER BY poll_option_id'; $result = $db->sql_query($sql); $cur_poll_options = array(); while ($row = $db->sql_fetchrow($result)) { $cur_poll_options[] = $row; } $db->sql_freeresult($result); } $sql_insert_ary = array(); for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) { if (strlen(trim($poll['poll_options'][$i]))) { if (empty($cur_poll_options[$i])) { // If we add options we need to put them to the end to be able to preserve votes... $sql_insert_ary[] = array( 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i] ); } else if ($poll['poll_options'][$i] != $cur_poll_options[$i]) { $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "' WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } } } $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) { $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' WHERE poll_option_id > ' . sizeof($poll['poll_options']) . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) { $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']); $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']); } } // Submit Attachments if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) { $space_taken = $files_added = 0; $orphan_rows = array(); foreach ($data['attachment_data'] as $pos => $attach_row) { $orphan_rows[(int) $attach_row['attach_id']] = array(); } if (sizeof($orphan_rows)) { $sql = 'SELECT attach_id, filesize, physical_filename FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' AND is_orphan = 1 AND poster_id = ' . $user->data['user_id']; $result = $db->sql_query($sql); $orphan_rows = array(); while ($row = $db->sql_fetchrow($result)) { $orphan_rows[$row['attach_id']] = $row; } $db->sql_freeresult($result); } foreach ($data['attachment_data'] as $pos => $attach_row) { if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) { continue; } if (!$attach_row['is_orphan']) { // update entry in db if attachment already stored in db and filespace $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' WHERE attach_id = " . (int) $attach_row['attach_id'] . ' AND is_orphan = 0'; $db->sql_query($sql); } else { // insert attachment into db if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) { continue; } $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; $files_added++; $attach_sql = array( 'post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment'], ); $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . ' WHERE attach_id = ' . $attach_row['attach_id'] . ' AND is_orphan = 1 AND poster_id = ' . $user->data['user_id']; $db->sql_query($sql); } } if ($space_taken && $files_added) { set_config_count('upload_dir_size', $space_taken, true); set_config_count('num_files', $files_added, true); } } // we need to update the last forum information // only applicable if the topic is not global and it is approved // we also check to make sure we are not dealing with globaling the latest topic (pretty rare but still needs to be checked) if ($topic_type != POST_GLOBAL && !$make_global && ($post_approved || !$data['post_approved'])) { // the last post makes us update the forum table. This can happen if... // We make a new topic // We reply to a topic // We edit the last post in a topic and this post is the latest in the forum (maybe) // We edit the only post in the topic // We edit the first post in the topic and all the other posts are not approved if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'"; } else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) { // this does not _necessarily_ mean that we must update the info again, // it just means that we might have to $sql = 'SELECT forum_last_post_id, forum_last_post_subject FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . (int) $data['forum_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // this post is the latest post in the forum, better update if ($row['forum_last_post_id'] == $data['post_id']) { // If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) { // the post's subject changed if ($row['forum_last_post_subject'] !== $subject) { $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . $db->sql_escape($subject) . '\''; } // Update the user name if poster is anonymous... just in case an admin changed it if ($data['poster_id'] == ANONYMOUS) { $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'"; } } else if ($data['post_approved'] !== $post_approved) { // we need a fresh change of socks, everything has become invalidated $sql = 'SELECT MAX(topic_last_post_id) as last_post_id FROM ' . TOPICS_TABLE . ' WHERE forum_id = ' . (int) $data['forum_id'] . ' AND topic_approved = 1'; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // any posts left in this forum? if (!empty($row['last_post_id'])) { $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND p.post_id = ' . (int) $row['last_post_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // salvation, a post is found! jam it into the forums table $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; } else { // just our luck, the last topic in the forum has just been turned unapproved... $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0'; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0'; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''"; } } } } } else if ($make_global) { // somebody decided to be a party pooper, we must recalculate the whole shebang (maybe) $sql = 'SELECT forum_last_post_id FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . (int) $data['forum_id']; $result = $db->sql_query($sql); $forum_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // we made a topic global, go get new data if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL && $forum_row['forum_last_post_id'] == $topic_row['topic_last_post_id']) { // we need a fresh change of socks, everything has become invalidated $sql = 'SELECT MAX(topic_last_post_id) as last_post_id FROM ' . TOPICS_TABLE . ' WHERE forum_id = ' . (int) $data['forum_id'] . ' AND topic_approved = 1'; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // any posts left in this forum? if (!empty($row['last_post_id'])) { $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND p.post_id = ' . (int) $row['last_post_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // salvation, a post is found! jam it into the forums table $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; } else { // just our luck, the last topic in the forum has just been globalized... $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0'; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0'; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0'; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''"; } } else if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL && $forum_row['forum_last_post_id'] < $topic_row['topic_last_post_id']) { // this post has a higher id, it is newer $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND p.post_id = ' . (int) $topic_row['topic_last_post_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // salvation, a post is found! jam it into the forums table $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; } } // topic sync time! // simply, we update if it is a reply or the last post is edited if ($post_approved) { // reply requires the whole thing if ($post_mode == 'reply') { $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id']; $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $user->data['user_id']; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . (($user->data['user_id'] != ANONYMOUS) ? $db->sql_escape($user->data['user_colour']) : '') . "'"; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time; } else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) { // only the subject can be changed from edit $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'"; // Maybe not only the subject, but also changing anonymous usernames. ;) if ($data['poster_id'] == ANONYMOUS) { $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'"; } } } else if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))) { // like having the rug pulled from under us $sql = 'SELECT MAX(post_id) as last_post_id FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . (int) $data['topic_id'] . ' AND post_approved = 1'; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // any posts left in this forum? if (!empty($row['last_post_id'])) { $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id AND p.post_id = ' . (int) $row['last_post_id']; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); // salvation, a post is found! jam it into the topics table $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id']; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'"; $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time']; $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id']; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'"; } } // Update total post count, do not consider moderated posts/topics if ($post_approval) { if ($post_mode == 'post') { set_config_count('num_topics', 1, true); set_config_count('num_posts', 1, true); } if ($post_mode == 'reply') { set_config_count('num_posts', 1, true); } } // Update forum stats $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id); foreach ($sql_data as $table => $update_ary) { if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) { $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table]; $db->sql_query($sql); } } // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement if ($make_global) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' WHERE topic_moved_id = ' . $data['topic_id']; $db->sql_query($sql); } // Committing the transaction before updating search index $db->sql_transaction('commit'); // Delete draft if post was loaded... $draft_id = request_var('draft_loaded', 0); if ($draft_id) { $sql = 'DELETE FROM ' . DRAFTS_TABLE . " WHERE draft_id = $draft_id AND user_id = {$user->data['user_id']}"; $db->sql_query($sql); } // Index message contents if ($update_search_index && $data['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised $search_type = basename($config['search_type']); if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) { trigger_error('NO_SUCH_SEARCH_MODULE'); } if (!class_exists($search_type)) { include("{$phpbb_root_path}includes/search/$search_type.$phpEx"); } $error = false; $search = new $search_type($error); if ($error) { trigger_error($error); } $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']); } // Topic Notification, do not change if moderator is changing other users posts... if ($user->data['user_id'] == $poster_id) { if (!$data['notify_set'] && $data['notify']) { $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')'; $db->sql_query($sql); } else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND topic_id = ' . $data['topic_id']; $db->sql_query($sql); } } if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') { // Mark this topic as posted to markread('post', $data['forum_id'], $data['topic_id']); } // Mark this topic as read // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) markread('topic', (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']), $data['topic_id'], time()); // if ($config['load_db_lastread'] && $user->data['is_registered']) { $sql = 'SELECT mark_time FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND forum_id = ' . (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']); $result = $db->sql_query($sql); $f_mark_time = (int) $db->sql_fetchfield('mark_time'); $db->sql_freeresult($result); } else if ($config['load_anon_lastread'] || $user->data['is_registered']) { $f_mark_time = false; } if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) { // Update forum info if ($topic_type == POST_GLOBAL) { $sql = 'SELECT MAX(topic_last_post_time) as forum_last_post_time FROM ' . TOPICS_TABLE . ' WHERE forum_id = 0'; } else { $sql = 'SELECT forum_last_post_time FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . $data['forum_id']; } $result = $db->sql_query($sql); $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); $db->sql_freeresult($result); update_forum_tracking_info((($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']), $forum_last_post_time, $f_mark_time, false); } // Send Notifications if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) { $username = ($username) ? $username : $user->data['username']; user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id'], $username); } $params = $add_anchor = ''; if ($post_approval) { $params .= '&t=' . $data['topic_id']; if ($mode != 'post') { $params .= '&p=' . $data['post_id']; $add_anchor = '#p' . $data['post_id']; } } else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') { $params .= '&t=' . $data['topic_id']; } $url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx"; $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor; return $url; } /** * Handle topic bumping * @param int $forum_id The ID of the forum the topic is being bumped belongs to * @param int $topic_id The ID of the topic is being bumping * @param array $post_data Passes some topic parameters: * - 'topic_title' * - 'topic_last_post_id' * - 'topic_last_poster_id' * - 'topic_last_post_subject' * - 'topic_last_poster_name' * - 'topic_last_poster_colour' * @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time(). * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&topic_id=2&p=3#p3 */ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) { global $config, $db, $user, $phpEx, $phpbb_root_path; if ($bump_time === false) { $bump_time = time(); } // Begin bumping $db->sql_transaction('begin'); // Update the topic's last post post_time $sql = 'UPDATE ' . POSTS_TABLE . " SET post_time = $bump_time WHERE post_id = {$post_data['topic_last_post_id']} AND topic_id = $topic_id"; $db->sql_query($sql); // Sync the topic's last post time, the rest of the topic's last post data isn't changed $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_post_time = $bump_time, topic_bumped = 1, topic_bumper = " . $user->data['user_id'] . " WHERE topic_id = $topic_id"; $db->sql_query($sql); // Update the forum's last post info $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_post_id = " . $post_data['topic_last_post_id'] . ", forum_last_poster_id = " . $post_data['topic_last_poster_id'] . ", forum_last_post_subject = '" . $db->sql_escape($post_data['topic_last_post_subject']) . "', forum_last_post_time = $bump_time, forum_last_poster_name = '" . $db->sql_escape($post_data['topic_last_poster_name']) . "', forum_last_poster_colour = '" . $db->sql_escape($post_data['topic_last_poster_colour']) . "' WHERE forum_id = $forum_id"; $db->sql_query($sql); // Update bumper's time of the last posting to prevent flood $sql = 'UPDATE ' . USERS_TABLE . " SET user_lastpost_time = $bump_time WHERE user_id = " . $user->data['user_id']; $db->sql_query($sql); $db->sql_transaction('commit'); // Mark this topic as posted to markread('post', $forum_id, $topic_id, $bump_time); // Mark this topic as read markread('topic', $forum_id, $topic_id, $bump_time); // Update forum tracking info if ($config['load_db_lastread'] && $user->data['is_registered']) { $sql = 'SELECT mark_time FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' AND forum_id = ' . $forum_id; $result = $db->sql_query($sql); $f_mark_time = (int) $db->sql_fetchfield('mark_time'); $db->sql_freeresult($result); } else if ($config['load_anon_lastread'] || $user->data['is_registered']) { $f_mark_time = false; } if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) { // Update forum info $sql = 'SELECT forum_last_post_time FROM ' . FORUMS_TABLE . ' WHERE forum_id = ' . $forum_id; $result = $db->sql_query($sql); $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); $db->sql_freeresult($result); update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time, false); } add_log('mod', $forum_id, $topic_id, 'LOG_BUMP_TOPIC', $post_data['topic_title']); $url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p={$post_data['topic_last_post_id']}") . "#p{$post_data['topic_last_post_id']}"; return $url; } ?>>2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420
# translation of DrakX-fa.po to Persian
# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
# Abbas Izad <abbasizad@hotmail.com>, 2003, 2004, 2005.
#
msgid ""
msgstr ""
"Project-Id-Version: DrakX-fa\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-09-17 15:08+0200\n"
"PO-Revision-Date: 2005-02-26 06:31+0100\n"
"Last-Translator: Abbas Izad <abbasizad@hotmail.com>\n"
"Language-Team: Persian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.3.1\n"

#: drakboot:49
#, c-format
msgid "No bootloader found, creating a new configuration"
msgstr ""

#: drakboot:83 harddrake2:194 harddrake2:195 logdrake:71
#, c-format
msgid "/_File"
msgstr "/_پرونده"

#: drakboot:84 logdrake:77
#, c-format
msgid "/File/_Quit"
msgstr "/پرونده/_خروج"

#: drakboot:84 harddrake2:195 logdrake:77
#, c-format
msgid "<control>Q"
msgstr "<control>Q"

#: drakboot:124
#, c-format
msgid "Text only"
msgstr "فقط متن"

#: drakboot:125
#, c-format
msgid "Verbose"
msgstr ""

#: drakboot:126
#, c-format
msgid "Silent"
msgstr ""

#: drakboot:133
#, c-format
msgid ""
"Your system bootloader is not in framebuffer mode. To activate graphical "
"boot, select a graphic video mode from the bootloader configuration tool."
msgstr ""
"بارگذار آغازگر سیستم‌تان در حالت framebuffer نیست. برای فعال کردن آغازگری "
"تصویری، حالت ویدیوی گرافیکی را از ابزار پیکربندی بارگذار آغازگری انتخاب کنید."

#: drakboot:134
#, c-format
msgid "Do you want to configure it now?"
msgstr "آیا میخواهید آن را اکنون پیکربندی کنید؟"

#: drakboot:143
#, c-format
msgid "Install themes"
msgstr "نصب تم‌ها"

#: drakboot:145
#, c-format
msgid "Graphical boot theme selection"
msgstr "گزینش تم آغازگری گرافیکی"

#: drakboot:148
#, fuzzy, c-format
msgid "Graphical boot mode:"
msgstr "استفاده از آغازگری گرافیکی"

#: drakboot:150
#, c-format
msgid "Theme"
msgstr "طرح"

#: drakboot:153
#, c-format
msgid ""
"Display theme\n"
"under console"
msgstr ""
"نمایش تم \n"
"در کنسول"

#: drakboot:158 draksplash:25
#, c-format
msgid "Create new theme"
msgstr "ایجاد تم‌ جدید"

#: drakboot:190
#, c-format
msgid "Default user"
msgstr "کاربر پیش‌فرض"

#: drakboot:191
#, c-format
msgid "Default desktop"
msgstr "رومیزی پیش‌فرض"

#: drakboot:194
#, c-format
msgid "No, I do not want autologin"
msgstr "نه، ثبت‌ورود خودکار را نمی‌خواهم"

#: drakboot:195
#, c-format
msgid "Yes, I want autologin with this (user, desktop)"
msgstr "بله، من ثبت‌ورود خودکار را با این (کاربر، رومیزی) می‌خواهم"

#: drakboot:202
#, c-format
msgid "System mode"
msgstr "حالت سیستم"

#: drakboot:205
#, c-format
msgid "Launch the graphical environment when your system starts"
msgstr "راه‌اندازی محیط گرافیکی هنگام شروع سیستم‌تان"

#: drakboot:260
#, c-format
msgid ""
"Please choose a video mode, it will be applied to each of the boot entries "
"selected below.\n"
"Be sure your video card supports the mode you choose."
msgstr ""
"لطفا حالت ویدیوئی را انتخاب کنید، آن به هر ورودی آغازگری انتخاب شده در زیر "
"اعمال خواهد گردید.\n"
"مطمئن شوید که کارت ویدیوئی شما حالت انتخابیتان را پشتیبانی میکند."

#: drakbug:46
#, c-format
msgid "Mandriva Linux Bug Report Tool"
msgstr "ابزار گزارش اشکال لینوکس ماندریبا"

#: drakbug:51
#, c-format
msgid "Mandriva Linux Control Center"
msgstr "مرکز کنترل ماندریبا"

#: drakbug:52
#, c-format
msgid "First Time Wizard"
msgstr "جادوگر بار اول"

#: drakbug:53
#, c-format
msgid "Synchronization tool"
msgstr "ابزار هم‌گاه‌سازی"

#: drakbug:54 drakbug:168
#, c-format
msgid "Standalone Tools"
msgstr "ابزارهای تک‌رایانه"

#: drakbug:56 drakbug:57
#, c-format
msgid "Mandriva Online"
msgstr "ماندریبا بر اینترنت"

#: drakbug:58
#, c-format
msgid "Remote Control"
msgstr "کنترل از راه دور"

#: drakbug:59
#, c-format
msgid "Software Manager"
msgstr "مدیر نرم‌افزار"

#: drakbug:60
#, c-format
msgid "Windows Migration tool"
msgstr "ابزار در بسترسازی ویندوز"

#: drakbug:61
#, c-format
msgid "Configuration Wizards"
msgstr "جادوگرهای پیکربندی"

#: drakbug:83
#, c-format
msgid "Select Mandriva Tool:"
msgstr "ابزار نرم‌افزار ماندریبا را انتخاب کنید:"

#: drakbug:84
#, c-format
msgid ""
"or Application Name\n"
"(or Full Path):"
msgstr ""
"یا نام برنامه \n"
"(یا مسیر کامل):"

#: drakbug:87
#, c-format
msgid "Find Package"
msgstr "یافتن بسته"

#: drakbug:89
#, c-format
msgid "Package: "
msgstr "بسته‌:"

#: drakbug:90
#, c-format
msgid "Kernel:"
msgstr "هسته:"

#: drakbug:102
#, c-format
msgid "The \"%s\" program has crashed with the following error:"
msgstr ""

#: drakbug:104
#, c-format
msgid "The \"%s\" program has crashed."
msgstr ""

#: drakbug:106
#, fuzzy, c-format
msgid ""
"To submit a bug report, click on the report button.  \n"
"This will open a web browser window on %s where you'll find a form to fill "
"in.  The information displayed above will be transferred to that server.  \n"
"Things useful to include in your report are the output of lspcidrake -v, "
"kernel version, and /proc/cpuinfo."
msgstr ""
"برای فرستادن گزارش اشکال، دکمه‌ی گزارش را کلیک کنید.\n"
"این پنجره‌ی مرورگر وب را بر %s باز می‌کند \n"
"در آن جا پرسشنامه‌ای را برای پر کردن می‌یابید. اطلاعات نشان داده شده در\n"
"بالا به آن کارگزار منتقل خواهد شد.\n"
"چیزهای مفید برای ضمیمه در گزارش برونداد lspcidrake -vdrake -v، نسخه هسته، و /"
"proc/cpuinfo است."

#: drakbug:112
#, c-format
msgid "Report"
msgstr "گزارش"

#: drakbug:178
#, c-format
msgid "Not installed"
msgstr "نصب نشده"

#: drakbug:191
#, c-format
msgid "Package not installed"
msgstr "بسته نصب نشده است"

#: drakclock:39
#, c-format
msgid "not defined"
msgstr "مشخص نشده است"

#: drakclock:41
#, c-format
msgid "Change Time Zone"
msgstr "تغییر دادن منطقه‌ی زمانی"

#: drakclock:44
#, c-format
msgid "Timezone - DrakClock"
msgstr "منطقه‌ی زمانی - DrakClock"

#: drakclock:45
#, c-format
msgid "GMT - DrakClock"
msgstr "GMT - DrakClock"

#: drakclock:45
#, c-format
msgid "Is your hardware clock set to GMT?"
msgstr "آیا ساعت سخت‌افزارتان به GMT گذاشته شده است؟"

#: drakclock:70
#, c-format
msgid "Network Time Protocol"
msgstr "پایان‌نامه‌ی زمان شبکه"

#: drakclock:72
#, c-format
msgid ""
"Your computer can synchronize its clock\n"
" with a remote time server using NTP"
msgstr ""
"رایانه‌ی شما می‌تواند ساعت خود را با کارگزار زمان\n"
"از راه دور با استفاده از NTP هم‌گاه‌سازی کند"

#: drakclock:73
#, c-format
msgid "Enable Network Time Protocol"
msgstr "بکار انداختن پایان‌نامه‌ی زمان شبکه"

#: drakclock:81
#, c-format
msgid "Server:"
msgstr "کارگزار‌:"

#: drakclock:110
#, fuzzy, c-format
msgid "Please enter a valid NTP server address."
msgstr "لطفا نشانی آی پی معتبری را وارد کنید."

#: drakclock:125
#, c-format
msgid "Could not synchronize with %s."
msgstr "نمیتوان با %s همگاه سازی کرد."

#: drakclock:127
#, fuzzy, c-format
msgid "Retry"
msgstr "بازسازی"

#: drakclock:149 drakclock:159
#, c-format
msgid "Reset"
msgstr "بازنشاندن"

#: drakedm:41
#, c-format
msgid "GDM (GNOME Display Manager)"
msgstr "GDM (مدیر نمایش گنوم)"

#: drakedm:42
#, c-format
msgid "KDM (KDE Display Manager)"
msgstr "KDM (مدیر نمایش کدئی)"

#: drakedm:43
#, c-format
msgid "XDM (X Display Manager)"
msgstr "XDM (X مدیر نمایش)"

#: drakedm:54
#, c-format
msgid "Choosing a display manager"
msgstr "انتخاب مدیر نمایشی"

#: drakedm:55
#, c-format
msgid ""
"X11 Display Manager allows you to graphically log\n"
"into your system with the X Window System running and supports running\n"
"several different X sessions on your local machine at the same time."
msgstr ""
"مدیر نمایش X11 به شما اجازه می‌دهد تا بدرون سیستم‌تان با سیستم\n"
"پنجره‌ی ایکس در حال اجرا ثبت‌ورود کرده و هم‌زمان از اجرای چندین\n"
"نشست گوناگون ایکس بر رایانه‌ی محلی‌تان پشتیبانی می‌کند."

#: drakedm:73
#, c-format
msgid "The change is done, do you want to restart the dm service?"
msgstr "تغییر انجام شد، آیا می‌خواهید سرویس dm را دوباره راه‌اندازی کنید؟"

#: drakedm:74
#, c-format
msgid ""
"You are going to close all running programs and lose your current session. "
"Are you really sure that you want to restart the dm service?"
msgstr ""
"شما در حال بستن همه برنامه‌های در حال اجرا هستید و نشست کنونی را از دست "
"میدهید. آیا واقعا مطمئن هستید که میخواهید سرویس dm را دوباره را ه‌اندازی کنید؟"

#: drakfont:187
#, c-format
msgid "Search installed fonts"
msgstr "جستجو برای قلم‌های نصب شده"

#: drakfont:189
#, c-format
msgid "Unselect fonts installed"
msgstr "قلم‌های انتخاب نشده نصب شد"

#: drakfont:213
#, c-format
msgid "No fonts found"
msgstr "هیچ قلمی یافت نشد"

#: drakfont:217
#, c-format
msgid "parse all fonts"
msgstr "تجزیه‌ی همه‌ی قلم‌ها"

#: drakfont:222 drakfont:263 drakfont:332 drakfont:373 drakfont:380
#: drakfont:406 drakfont:424 drakfont:438
#, c-format
msgid "done"
msgstr "انجام شد"

#: drakfont:226
#, c-format
msgid "Could not find any font in your mounted partitions"
msgstr "نمی‌توان هیچ قلمی را در قسمت‌بندی‌های سوار شده یافت"

#: drakfont:261
#, c-format
msgid "Reselect correct fonts"
msgstr "انتخاب مجدد قلم‌های درست"

#: drakfont:264
#, c-format
msgid "Could not find any font.\n"
msgstr "نمی‌توان هیچ قلمی را یافت.\n"

#: drakfont:274
#, c-format
msgid "Search for fonts in installed list"
msgstr "جستجو برای قلم‌ها در لیست نصب شده"

#: drakfont:293
#, c-format
msgid "%s fonts conversion"
msgstr "تبدیل قلم‌های %s"

#: drakfont:330
#, c-format
msgid "Fonts copy"
msgstr "کپی قلم‌ها"

#: drakfont:333
#, c-format
msgid "True Type fonts installation"
msgstr "نصب قلم‌های نوع حقیقی"

#: drakfont:341
#, c-format
msgid "please wait during ttmkfdir..."
msgstr "لطفاً در طول ttmkfdir صبر کنید..."

#: drakfont:342
#, c-format
msgid "True Type install done"
msgstr "نصب نوع حقیقی انجام شد"

#: drakfont:348 drakfont:363
#, c-format
msgid "type1inst building"
msgstr "ساختن type1inst "

#: drakfont:357
#, c-format
msgid "Ghostscript referencing"
msgstr "Ghostscript referencing"

#: drakfont:374
#, c-format
msgid "Suppress Temporary Files"
msgstr "فشرده‌سازی پرونده‌های موقت"

#: drakfont:376 drakfont:434
#, c-format
msgid "Restart XFS"
msgstr "راه‌اندازی مجدد XFS"

#: drakfont:422 drakfont:432
#, c-format
msgid "Suppress Fonts Files"
msgstr "فشرده‌سازی پرونده‌های قلم‌ها"

#: drakfont:442
#, c-format
msgid ""
"Before installing any fonts, be sure that you have the right to use and "
"install them on your system.\n"
"\n"
"You can install the fonts the normal way. In rare cases, bogus fonts may "
"hang up your X Server."
msgstr ""
"پیش از نصب هر قلمی، مطمئن شوید که شما اجازه‌ی استفاده و نصب آنها را بر سیستم "
"خود دارید.\n"
"\n"
"- شما می‌توانید قلم‌ها را به روش عادی نصب کنید. بندرت قلم‌های اشکال‌دار ممکن است "
"کارگزار X شما را متوقف کنند. "

#: drakfont:482
#, fuzzy, c-format
msgid "Font Installation"
msgstr "بعد از نصب"

#: drakfont:493
#, c-format
msgid "DrakFont"
msgstr "DrakFont"

#: drakfont:494 drakfont:646
#, c-format
msgid "Font List"
msgstr "لیست قلم"

#: drakfont:497
#, c-format
msgid "Get Windows Fonts"
msgstr ""

#: drakfont:503
#, c-format
msgid "About"
msgstr "درباره"

#: drakfont:505 drakfont:725
#, c-format
msgid "Uninstall"
msgstr "نصب‌برداری"

#: drakfont:506
#, c-format
msgid "Import"
msgstr "واردات"

#: drakfont:524
#, fuzzy, c-format
msgid "Drakfont"
msgstr "DrakFont"

#: drakfont:526
#, c-format
msgid "Copyright (C) 2001-2006 by Mandriva"
msgstr "حق نسخه‌برداری (C) 2001-2006 Mandriva."

#: drakfont:528
#, fuzzy, c-format
msgid "Font installer."
msgstr "نصب نشده"

#: drakfont:530 harddrake2:236
#, c-format
msgid "Mandriva Linux"
msgstr "ماندریبا لینوکس"

#. -PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>")
#. -PO: put here name(s) and email(s) of translator(s) (eg: "John Smith <jsmith@nowhere.com>")
#: drakfont:537 harddrake2:241
#, c-format
msgid "_: Translator(s) name(s) & email(s)\n"
msgstr "Abbas Izad <abbasizad@hotmail.com>\n"

#: drakfont:547
#, c-format
msgid "Choose the applications that will support the fonts:"
msgstr "انتخاب برنامه‌هایی که قلم‌ها را حمایت خواهند کرد:"

#: drakfont:558
#, c-format
msgid "Ghostscript"
msgstr "Ghostscript"

#: drakfont:559
#, c-format
msgid "OpenOffice.org"
msgstr ""

#: drakfont:560
#, c-format
msgid "Abiword"
msgstr "Abiword"

#: drakfont:561
#, c-format
msgid "Generic Printers"
msgstr "چاپگرهای عمومی"

#: drakfont:575
#, c-format
msgid "Select the font file or directory and click on 'Add'"
msgstr "انتخاب پرونده یا شاخه‌ی حاوی قلم و کلیک کردن بر 'افزودن'"

#: drakfont:576
#, c-format
msgid "File Selection"
msgstr "انتخاب پرونده"

#: drakfont:580
#, c-format
msgid "Fonts"
msgstr "قلم‌ها"

#: drakfont:644
#, c-format
msgid "Import fonts"
msgstr "واردات قلم‌ها"

#: drakfont:657
#, c-format
msgid "Install"
msgstr "نصب"

#: drakfont:688
#, c-format
msgid "Are you sure you want to uninstall the following fonts?"
msgstr ""

#: drakfont:733
#, c-format
msgid "Unselected All"
msgstr "همه انتخاب نشده‌اند"

#: drakfont:736
#, c-format
msgid "Selected All"
msgstr "همه انتخاب شده‌اند"

#: drakfont:750 drakfont:769
#, c-format
msgid "Importing fonts"
msgstr "وارد کردن قلم‌ها"

#: drakfont:754 drakfont:774
#, c-format
msgid "Initial tests"
msgstr "آزمایش‌های شروعی"

#: drakfont:755
#, c-format
msgid "Copy fonts on your system"
msgstr "کپی قلم‌ها بر سیستم‌تان"

#: drakfont:756
#, c-format
msgid "Install & convert Fonts"
msgstr "نصب و تبدیل قلم‌ها"

#: drakfont:757
#, c-format
msgid "Post Install"
msgstr "بعد از نصب"

#: drakfont:775
#, c-format
msgid "Remove fonts on your system"
msgstr "برداشتن قلم‌ها از سیستم‌تان"

#: drakfont:776
#, c-format
msgid "Post Uninstall"
msgstr "بعد از نصب‌برداری"

#: drakhelp:17
#, c-format
msgid ""
" drakhelp 0.1\n"
"Copyright (C) %s Mandriva.\n"
"This is free software and may be redistributed under the terms of the GNU "
"GPL.\n"
"\n"
"Usage: \n"
msgstr ""
" drakhelp 0.1\n"
"Copyright (C) %s Mandriva.\n"
"این یک نرم‌افزار آزاد بوده و ممکن است تحت شروط GNU GPL انتشار مجدد گردد.\n"
"\n"
"طرز استفاده: \n"

#: drakhelp:22
#, c-format
msgid " --help                - display this help     \n"
msgstr " --help                - این راهنما را نشان می‌دهد     \n"

#: drakhelp:23
#, c-format
msgid ""
" --id <id_label>       - load the html help page which refers to id_label\n"
msgstr ""
" --id <id_label>       - صفحه‌ی راهنمای html که به id_label ارجاع می‌کند را "
"بارگذاری می‌کند\n"

#: drakhelp:24
#, c-format
msgid ""
" --doc <link>          - link to another web page ( for WM welcome "
"frontend)\n"
msgstr ""
" --doc <link>          - پیوند به یک صفحه وب دیگر ( برای ظاهر خوش‌آمد گویی "
"مدیر پنجره)\n"

#: drakhelp:52
#, c-format
msgid "Mandriva Linux Help Center"
msgstr "مرکز راهنمای لینوکس ماندریبا"

#: drakhelp:52
#, c-format
msgid "No Help entry for %s\n"
msgstr ""

#: drakperm:22
#, c-format
msgid "System settings"
msgstr "تنظیمات سیستم"

#: drakperm:23
#, c-format
msgid "Custom settings"
msgstr "تنظیمات اختصاصی"

#: drakperm:24
#, c-format
msgid "Custom & system settings"
msgstr "تنظیمات سیستم & اختصاصی"

#: drakperm:32
#, fuzzy, c-format
msgid "Security Permissions"
msgstr "اجازه‌ها"

#: drakperm:44
#, c-format
msgid "Editable"
msgstr "قابل ویرایش"

#: drakperm:49 drakperm:322
#, c-format
msgid "Path"
msgstr "مسیر"

#: drakperm:49 drakperm:250
#, c-format
msgid "User"
msgstr "کاربر"

#: drakperm:49 drakperm:250
#, c-format
msgid "Group"
msgstr "گروه"

#: drakperm:49 drakperm:334
#, c-format
msgid "Permissions"
msgstr "اجازه‌ها"

#: drakperm:59
#, c-format
msgid "Add a new rule"
msgstr ""

#: drakperm:66 drakperm:101 drakperm:126
#, c-format
msgid "Edit current rule"
msgstr "ويرايش قاعده‌ی کنونی"

#: drakperm:108
#, c-format
msgid ""
"Here you can see files to use in order to fix permissions, owners, and "
"groups via msec.\n"
"You can also edit your own rules which will owerwrite the default rules."
msgstr ""
"در اینجا می‌توانید پرونده‌های مورد استفاده برای تعیین اجازه‌ها، مالکیت‌ها و "
"گروه‌هارا از طریق msec ببینید.\n"
"شما همچنین می‌توانید قواعد خود را ویرایش کرده که در آن صورت قواعد پیش‌فرض را "
"بازنگاری خواهد کرد."

#: drakperm:110
#, c-format
msgid ""
"The current security level is %s.\n"
"Select permissions to see/edit"
msgstr ""
"سطح کنونی امنیت %s است.\n"
"اجازه‌ها را برای دیدن/ویرایش انتخاب کنید"

#: drakperm:122
#, c-format
msgid "Up"
msgstr "بالا"

#: drakperm:122
#, c-format
msgid "Move selected rule up one level"
msgstr "انتقال دادن قاعده‌ی انتخاب شده به یک سطح بالا‌تر"

#: drakperm:123
#, c-format
msgid "Down"
msgstr "پایین"

#: drakperm:123
#, c-format
msgid "Move selected rule down one level"
msgstr "انتقال دادن قاعده‌ی انتخاب شده به یک سطح پایین‌تر"

#: drakperm:124
#, c-format
msgid "Add a rule"
msgstr "افزودن یک قاعده"

#: drakperm:124
#, c-format
msgid "Add a new rule at the end"
msgstr "افزودن یک قاعده‌ی جدید در آخر"

#: drakperm:125
#, c-format
msgid "Delete selected rule"
msgstr "حذف قواعد انتخاب‌شده"

#: drakperm:126 drakups:300 drakups:362 drakups:382
#, c-format
msgid "Edit"
msgstr "ویرایش"

#: drakperm:242
#, c-format
msgid "browse"
msgstr "مرور"

#: drakperm:247
#, c-format
msgid "user"
msgstr "کاربر"

#: drakperm:247
#, c-format
msgid "group"
msgstr "گروه"

#: drakperm:247
#, c-format
msgid "other"
msgstr "دیگر"

#: drakperm:252
#, c-format
msgid "Read"
msgstr "خواندن"

#. -PO: here %s will be either "user", "group" or "other"
#: drakperm:255
#, c-format
msgid "Enable \"%s\" to read the file"
msgstr "بکاراندازی \"%s\" برای خواندن پرونده"

#: drakperm:259
#, c-format
msgid "Write"
msgstr "نگارش"

#. -PO: here %s will be either "user", "group" or "other"
#: drakperm:262
#, c-format
msgid "Enable \"%s\" to write the file"
msgstr "برای نگارش پرونده \"%s\" را بکار اندازید"

#: drakperm:266
#, c-format
msgid "Execute"
msgstr "اجرا"

#. -PO: here %s will be either "user", "group" or "other"
#: drakperm:269
#, c-format
msgid "Enable \"%s\" to execute the file"
msgstr "برای اجرای پرونده \"%s\" را بکار اندازید"

#: drakperm:272
#, c-format
msgid "Sticky-bit"
msgstr "بیت-چسبنده"

#: drakperm:272
#, c-format
msgid ""
"Used for directory:\n"
" only owner of directory or file in this directory can delete it"
msgstr ""
"استفاده شده برای شاخه:\n"
"فقط صاحب شاخه یا پرونده در این شاخه می‌تواند آن را حذف کند"

#: drakperm:273
#, c-format
msgid "Set-UID"
msgstr "Set-UID"

#: drakperm:273
#, c-format
msgid "Use owner id for execution"
msgstr "استفاده از شناسه‌ی مالکیت برای اجرا"

#: drakperm:274
#, c-format
msgid "Set-GID"
msgstr "Set-GID"

#: drakperm:274
#, c-format
msgid "Use group id for execution"
msgstr "استفاده از شناسه‌ی گروه برای اجرا"

#: drakperm:292
#, c-format
msgid "User:"
msgstr "کاربر :"

#: drakperm:293
#, c-format
msgid "Group:"
msgstr "گروه :"

#: drakperm:297
#, c-format
msgid "Current user"
msgstr "کاربر کنونی"

#: drakperm:298
#, c-format
msgid "When checked, owner and group will not be changed"
msgstr "اگر علامت زده شده، مالک و گروه تغییر نخواهند کرد"

#: drakperm:308
#, c-format
msgid "Path selection"
msgstr "انتخاب مسیر"

#: drakperm:328
#, c-format
msgid "Property"
msgstr "مشخصات"

#: drakperm:378
#, c-format
msgid ""
"The first character of the path must be a slash (\"/\"):\n"
"\"%s\""
msgstr ""

#: drakperm:388
#, c-format
msgid "Both the username and the group must valid!"
msgstr ""

#: drakperm:389
#, c-format
msgid "User: %s"
msgstr ""

#: drakperm:390
#, c-format
msgid "Group: %s"
msgstr ""

#: draksec:53
#, c-format
msgid "ALL"
msgstr "همه"

#: draksec:54
#, c-format
msgid "LOCAL"
msgstr "محلی"

#: draksec:55
#, c-format
msgid "NONE"
msgstr "هیچکدام"

#: draksec:57
#, c-format
msgid "Ignore"
msgstr "نادیده گرفتن"

#. -PO: Do not alter the <span ..> and </span> tags.
#. -PO: Translate the security levels (Poor, Standard, High, Higher and Paranoid) in the same way, you translated these individuals words.
#. -PO: keep the double empty lines between sections, this is formatted a la LaTeX.
#: draksec:93
#, c-format
msgid ""
"Here, you can setup the security level and administrator of your machine.\n"
"\n"
"\n"
"The '<span weight=\"bold\">Security Administrator</span>' is the one who "
"will receive security alerts if the\n"
"'<span weight=\"bold\">Security Alerts</span>' option is set. It can be a "
"username or an email.\n"
"\n"
"\n"
"The '<span weight=\"bold\">Security Level</span>' menu allows you to select "
"one of the six preconfigured security levels\n"
"provided with msec. These levels range from '<span weight=\"bold\">poor</"
"span>' security and ease of use, to\n"
"'<span weight=\"bold\">paranoid</span>' config, suitable for very sensitive "
"server applications:\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">Poor</span>: This is a totally unsafe but "
"very\n"
"easy to use security level. It should only be used for machines not "
"connected to\n"
"any network and that are not accessible to everybody.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">Standard</span>: This is the standard "
"security\n"
"recommended for a computer that will be used to connect to the Internet as "
"a\n"
"client.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">High</span>: There are already some\n"
"restrictions, and more automatic checks are run every night.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">Higher</span>: The security is now high "
"enough\n"
"to use the system as a server which can accept connections from many "
"clients. If\n"
"your machine is only a client on the Internet, you should choose a lower "
"level.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">Paranoid</span>: This is similar to the "
"previous\n"
"level, but the system is entirely closed and security features are at their\n"
"maximum"
msgstr ""
"در اینجا میتوانید سطح امنیت و مدیریت ماشینتان را برپاسازی کنید.\n"
"\n"
"\n"
"'<span weight=\"bold\">مدیر امنیت</span>' کسی است که هشدارهای امنیتی را اگر "
"گزینه\n"
"'<span weight=\"bold\">هشدارهای امنیتی</span>' گذارده شده است دریافت میکند. "
"آن میتواندنام کاربری یا پست باشد.\n"
"\n"
"\n"
"منوی '<span weight=\"bold\">سطح امنیتی</span>' بشما اجازه میدهدتا یکی از شش "
"سطوح از پیش پیکربندی شده توسط msec را انتخاب کنید\n"
"این سطوح از امنیت '<span weight=\"bold\">ضعیف</span>' و استفاده آسان، تا\n"
"پیکربندی '<span weight=\"bold\">خیالاتی</span>' مناسب برای هر برنامه خیلی "
"حساس کارگزاری:\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">ضعیف</span>: این کاملاً ناامن ولی خیلی برای "
"استفاده\n"
"آسان می‌باشد. این باید برای ماشین‌هایی که به هیچ شبکه‌ای وصل نشده‌اند و\n"
"در دسترس هر کسی نمی‌باشند استفاده شود.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">استاندارد</span>: این امنیت استاندارد "
"پیشنهادی برای\n"
"یک رایانه که معمولاً مانند کارگیر به اینترنت وصل می‌شود می‌باشد.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">بالا</span>: چندین محدودیت از قبل وجود "
"دارند، و\n"
"کنترل‌های خودکار بیشتری هر شب اجرا می‌شود.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">بالاتر</span>: امنیت اکنون بقدر کافی بالاست "
"که بتوان \n"
"از سیستم بعنوان یک کارگزار که اتصالات بسیاری از کارگیرها را پذیرا باشد "
"استفاده کرد\n"
"اگر ماشین شما فقط یک کارگیر بر اینترنت می‌باشد، باید سطح پایین‌تری را انتخاب "
"نمایید.\n"
"\n"
"\n"
"<span foreground=\"royalblue3\">خیالاتی</span>: این شبیه به سطح پیشین "
"می‌باشد،\n"
"اما سیستم کاملاً بسته بوده و قابلیت‌های امنیتی در حد اعلای خود می‌باشند."

#: draksec:147 harddrake2:211
#, c-format
msgid ""
"Description of the fields:\n"
"\n"
msgstr ""
"توضیح محوطه‌ها:\n"
"\n"

#: draksec:161
#, c-format
msgid "(default value: %s)"
msgstr "(مقدار پیش‌فرض: %s)"

#: draksec:166
#, fuzzy, c-format
msgid "Security Level and Checks"
msgstr "سطح امنیت:"

#: draksec:203
#, c-format
msgid "Security Level:"
msgstr "سطح امنیت:"

#: draksec:210
#, c-format
msgid "Security Administrator:"
msgstr "مدیر امنیت:"

#: draksec:212
#, c-format
msgid "Basic options"
msgstr "گزینه‌های پایه"

#: draksec:226
#, c-format
msgid "Network Options"
msgstr "گزینه‌های شبکه"

#: draksec:226
#, c-format
msgid "System Options"
msgstr "گزینه‌ها‌ی سیستم"

#: draksec:261
#, c-format
msgid "Periodic Checks"
msgstr "بررسی‌های متناوب"

#: draksec:291
#, c-format
msgid "Please wait, setting security level..."
msgstr "لطفاً صبر کنید، در حال گذاردن سطح امنیتی..."

#: draksec:297
#, c-format
msgid "Please wait, setting security options..."
msgstr "لطفا صبر کنید، در حال گذاشتن گزینه‌های امنیتی..."

#: draksound:47
#, c-format
msgid "No Sound Card detected!"
msgstr "هیچ کارت صوتی شناسایی نشد!"

#. -PO: keep the double empty lines between sections, this is formatted a la LaTeX
#: draksound:50
#, c-format
msgid ""
"No Sound Card has been detected on your machine. Please verify that a Linux-"
"supported Sound Card is correctly plugged in.\n"
"\n"
"\n"
"You can visit our hardware database at:\n"
"\n"
"\n"
"http://www.mandrivalinux.com/en/hardware.php3"
msgstr ""
"هیچ کارت صوتی بر ماشین شما شناسایی نشد. لطفا کنترل کنید که یک کارت صوتی با "
"حمایت-لینوکس بدرستی وصل شده باشد. \n"
"\n"
"\n"
"می‌توانید از بانک اطلاعات سخت‌افزار ما بازدید کنید:\n"
"\n"
"\n"
"http://www.mandrivalinux.com/en/hardware.php3"

#: draksound:57
#, c-format
msgid ""
"\n"
"\n"
"\n"
"Note: if you've an ISA PnP sound card, you'll have to use the alsaconf or "
"the sndconfig program.  Just type \"alsaconf\" or \"sndconfig\" in a console."
msgstr ""
"\n"
"\n"
"\n"
"توجه: اگر شما یک کارت صوتی ISA PnP دارید, باید از alsaconf یا برنامه‌ی "
"sndconfig استفاده کنید.  فقط \"alsaconf\" یا \"sndconfig\" را در کنسول تایپ "
"کنید."

#: draksplash:32
#, c-format
msgid "X coordinate of text box"
msgstr ""

#: draksplash:33
#, c-format
msgid "Y coordinate of text box"
msgstr ""

#: draksplash:34
#, c-format
msgid "Text box width"
msgstr ""

#: draksplash:35
#, c-format
msgid "Text box height"
msgstr "ارتفاع جعبه متن"

#: draksplash:36
#, c-format
msgid ""
"The progress bar X coordinate\n"
"of its upper left corner"
msgstr ""
"مختصات x گوشه‌ی چپ بالای\n"
"نوار پیشروی"

#: draksplash:37
#, c-format
msgid ""
"The progress bar Y coordinate\n"
"of its upper left corner"
msgstr ""
"مختصات y گوشه‌ی چپ بالای\n"
"نوار پیشروی"

#: draksplash:38
#, c-format
msgid "The width of the progress bar"
msgstr "عرض نوار پیشروی"

#: draksplash:39
#, c-format
msgid "The height of the progress bar"
msgstr "ارتفاع نوار پیشروی"

#: draksplash:40
#, c-format
msgid "X coordinate of the text"
msgstr ""

#: draksplash:41
#, c-format
msgid "Y coordinate of the text"
msgstr ""

#: draksplash:42
#, c-format
msgid "Text box transparency"
msgstr ""

#: draksplash:43
#, c-format
msgid "Progress box transparency"
msgstr ""

#: draksplash:44
#, c-format
msgid "Text size"
msgstr ""

#: draksplash:61
#, c-format
msgid "Choose progress bar color 1"
msgstr ""

#: draksplash:62
#, c-format
msgid "Choose progress bar color 2"
msgstr ""

#: draksplash:63
#, c-format
msgid "Choose progress bar background"
msgstr ""

#: draksplash:64
#, c-format
msgid "Gradient type"
msgstr ""

#: draksplash:65
#, c-format
msgid "Choose text color"
msgstr ""

#: draksplash:67 draksplash:74
#, c-format
msgid "Choose picture"
msgstr ""

#: draksplash:68
#, c-format
msgid "Silent bootsplash"
msgstr ""

#: draksplash:71
#, c-format
msgid "Choose text zone color"
msgstr ""

#: draksplash:72
#, c-format
msgid "Text color"
msgstr ""

#: draksplash:73
#, c-format
msgid "Background color"
msgstr "رنگ پس‌زمینه"

#: draksplash:75
#, c-format
msgid "Verbose bootsplash"
msgstr ""

#: draksplash:81
#, c-format
msgid "Theme name"
msgstr "نام تم"

#: draksplash:84
#, c-format
msgid "Final resolution"
msgstr "تفکیک‌پذیری نهایی"

#: draksplash:87
#, c-format
msgid "Display logo on Console"
msgstr "نمایش ثبت‌ورود بر کنسول"

#: draksplash:92
#, c-format
msgid "Save theme"
msgstr "ذخیره‌ی تم"

#: draksplash:154
#, fuzzy, c-format
msgid "Please enter a theme name"
msgstr "لطفاً پارامترهای بی‌سیم را برای این کارت وارد کنید:"

#: draksplash:157
#, fuzzy, c-format
msgid "Please select a splash image"
msgstr "لطفا مدل UPS خود را انتخاب کنید."

#: draksplash:160
#, c-format
msgid "saving Bootsplash theme..."
msgstr "در حال ذخیره‌ی تم تصویرآغاز..."

#: draksplash:169
#, c-format
msgid "Unable to load image file %s"
msgstr ""

#: draksplash:180
#, c-format
msgid "choose image"
msgstr "انتخاب تصویر"

#: draksplash:195
#, c-format
msgid "Color selection"
msgstr ""

#: drakups:71
#, c-format
msgid "Connected through a serial port or an usb cable"
msgstr "از طریق درگاه سریال یا کابل usb متصل شده است"

#: drakups:72
#, c-format
msgid "Manual configuration"
msgstr "پیکربندی دستی"

#: drakups:78
#, c-format
msgid "Add an UPS device"
msgstr "افزودن یک دستگاه UPS"

#: drakups:81
#, c-format
msgid ""
"Welcome to the UPS configuration utility.\n"
"\n"
"Here, you'll add a new UPS to your system.\n"
msgstr ""
"به ابزار پیکربندی UPS خوش آمدید.\n"
"\n"
"در اینجا می‌توانی UPS جدیدی را به سیستم‌تان اضافه کنید.\n"

#: drakups:88
#, c-format
msgid ""
"We're going to add an UPS device.\n"
"\n"
"Do you want to autodetect UPS devices connected to this machine or to "
"manually select them?"
msgstr ""
"ما دستگاه UPS را اضافه خواهیم کرد.\n"
"\n"
"آیا ترجیح می‌دهید دستگاه‌های UPS متصل شده به این ماشین شناسائی‌خودکار شوند یا؟"

#: drakups:91
#, c-format
msgid "Autodetection"
msgstr "شناسائی خودکار"

#: drakups:99 harddrake2:367
#, c-format
msgid "Detection in progress"
msgstr "شناسایی در پیشروی است"

#: drakups:118 drakups:157 logdrake:457 logdrake:463
#, c-format
msgid "Congratulations"
msgstr "تبریک می‌گوئیم!"

#: drakups:119
#, c-format
msgid "The wizard successfully added the following UPS devices:"
msgstr "جادوگر با موفقیت دستگاه‌های UPS بدنبال آمده را اضافه کرد:"

#: drakups:121
#, c-format
msgid "No new UPS devices was found"
msgstr "هیچ دستگاه UPS جدیدی یافت نشد"

#: drakups:126 drakups:138
#, c-format
msgid "UPS driver configuration"
msgstr "پیکربندی راه‌انداز UPS"

#: drakups:126
#, c-format
msgid "Please select your UPS model."
msgstr "لطفا مدل UPS خود را انتخاب کنید."

#: drakups:127
#, c-format
msgid "Manufacturer / Model:"
msgstr "سازنده‌ / مدل:"

#: drakups:138
#, c-format
msgid ""
"We are configuring the \"%s\" UPS from \"%s\".\n"
"Please fill in its name, its driver and its port."
msgstr ""
"ما در حال پیکربندی UPS \"%s\" از \"%s\" هستیم.\n"
"لطفا نام، راه‌انداز و درگاه آن را پر کنید."

#: drakups:143
#, c-format
msgid "Name:"
msgstr "نام:"

#: drakups:143
#, c-format
msgid "The name of your ups"
msgstr "نام ups شما"

#: drakups:144
#, c-format
msgid "The driver that manages your ups"
msgstr "راه‌اندازی که ups شما را سازماندهی می‌کند"

#: drakups:145
#, c-format
msgid "Port:"
msgstr "درگاه:"

#: drakups:147
#, c-format
msgid "The port on which is connected your ups"
msgstr "نوع درگاهی که ups شما به آن وصل شده است"

#: drakups:157
#, c-format