/** * Get details for an ajax-tree-list of entries for the content covered by this search hook. * * @return array A pair: the hook, and the options */ function ajax_tree() { $catalogue_name = get_param('catalogue_name', ''); if ($catalogue_name == '') { @ob_end_clean(); $tree = nice_get_catalogues(NULL, true); if ($tree->is_empty()) { inform_exit(do_lang_tempcode('NO_ENTRIES')); } require_code('form_templates'); $fields = form_input_list(do_lang_tempcode('NAME'), '', 'catalogue_name', $tree, NULL, true); if (running_script('iframe')) { $post_url = get_self_url_easy(); } else { $post_url = get_self_url(false, false, NULL, false, true); } $submit_name = do_lang_tempcode('PROCEED'); $hidden = build_keep_post_fields(); $title = get_page_title('SEARCH'); $tpl = do_template('FORM_SCREEN', array('_GUID' => 'a2812ac8056903811f444682d45ee448', 'TARGET' => '_self', 'GET' => true, 'SKIP_VALIDATION' => true, 'HIDDEN' => $hidden, 'TITLE' => $title, 'TEXT' => '', 'URL' => $post_url, 'FIELDS' => $fields, 'SUBMIT_NAME' => $submit_name)); $echo = globalise($tpl, NULL, '', true); $echo->evaluate_echo(); exit; } return array('choose_catalogue_category', array('catalogue_name' => $catalogue_name)); }
/** * Standard code module initialisation function. */ function init__database__xml() { global $SCHEMA_CACHE, $DIR_CONTENTS_CACHE; $SCHEMA_CACHE = array(); $DIR_CONTENTS_CACHE = array(); global $DELIMITERS_FLIPPED, $DELIMITERS, $SYMBOL_DELIMINITER, $DELIMITERS_ALPHA; $DELIMITERS = array_merge(array("\t", ' ', "\n"), _get_sql_keywords()); sort($DELIMITERS); $DELIMITERS_FLIPPED = array_flip($DELIMITERS); $SYMBOL_DELIMINITER = array_flip(array("\t", ' ', "\n", '+', '-', '*', '/', '>', '<', '=', "'", '"', "\\'", '(', ')', ',')); foreach ($DELIMITERS as $d) { if (!isset($DELIMITERS_ALPHA[$d[0]])) { $DELIMITERS_ALPHA[$d[0]] = array(); } $DELIMITERS_ALPHA[$d[0]][] = $d; } global $TABLE_BASES; $TABLE_BASES = array(); // Support for chaining a DB- to make reads faster global $SITE_INFO; if (array_key_exists('db_chain_type', $SITE_INFO) && !running_script('xml_db_import') && get_param_integer('keep_no_chain', 0) != 1) { require_code('database/' . $SITE_INFO['db_chain_type']); $GLOBALS['XML_CHAIN_DB'] = new database_driver($SITE_INFO['db_chain'], $SITE_INFO['db_chain_host'], $SITE_INFO['db_chain_user'], $SITE_INFO['db_chain_password'], get_table_prefix(), false, object_factory('Database_Static_' . $SITE_INFO['db_chain_type'])); } else { $GLOBALS['XML_CHAIN_DB'] = NULL; } if (function_exists('set_time_limit')) { @set_time_limit(100); } // XML DB is *slow* }
/** * Check a post would be valid. * * @param LONG_TEXT The post. * @param ?AUTO_LINK The ID of the topic the post would be in (NULL: don't check with regard to any particular topic). * @param ?MEMBER The poster (NULL: current member). * @return ?array Row of the existing post if a double post (single row map-element in a list of rows) (NULL: not a double post). */ function ocf_check_post($post, $topic_id = NULL, $poster = NULL) { if (is_null($poster)) { $poster = get_member(); } require_code('comcode_check'); check_comcode($post, NULL, false, NULL, true); if (strlen($post) == 0) { warn_exit(do_lang_tempcode('POST_TOO_SHORT')); } require_code('ocf_groups'); if (strlen($post) > ocf_get_member_best_group_property($poster, 'max_post_length_comcode')) { warn_exit(make_string_tempcode(escape_html(do_lang('_POST_TOO_LONG')))); } if (!is_null($topic_id)) { if (running_script('stress_test_loader')) { return NULL; } // Check this isn't the same as the last post here $last_posts = $GLOBALS['FORUM_DB']->query_select('f_posts', array('p_post', 'p_poster', 'p_ip_address'), array('p_topic_id' => $topic_id), 'ORDER BY p_time DESC,id DESC', 1); if (array_key_exists(0, $last_posts)) { if ($last_posts[0]['p_poster'] == $GLOBALS['OCF_DRIVER']->get_guest_id() && get_ip_address() != $last_posts[0]['p_ip_address']) { $last_posts[0]['p_poster'] = -1; } if ($last_posts[0]['p_poster'] == $poster && get_translated_text($last_posts[0]['p_post'], $GLOBALS['FORUM_DB']) == $post && get_param_integer('keep_debug_notifications', 0) != 1) { warn_exit(do_lang_tempcode('DOUBLE_POST_PREVENTED')); } } return $last_posts; } return NULL; }
/** * Check the Comcode is valid. * * @param LONG_TEXT The comcode to convert * @param ?MEMBER The member the evaluation is running as. This is a security issue, and you should only run as an administrator if you have considered where the comcode came from carefully (NULL: current member) * @param boolean Whether to explicitly execute this with admin rights. There are a few rare situations where this should be done, for data you know didn't come from a member, but is being evaluated by one. * @param ?object The database connection to use (NULL: standard site connection) * @param boolean Whether there might be new attachments. If there are, we will check as lax- as attachments are always preserved by forcing lax parsing. */ function check_comcode($comcode, $source_member = NULL, $as_admin = false, $connection = NULL, $attachment_possibility = false) { if (running_script('stress_test_loader')) { return; } global $LAX_COMCODE; $temp = $LAX_COMCODE; if ($attachment_possibility) { $has_one = false; foreach ($_POST as $key => $value) { if (preg_match('#^hidFileID\\_#i', $key) != 0) { require_code('uploads'); $has_one = is_swf_upload(); } } foreach ($_FILES as $key => $file) { $matches = array(); if (is_uploaded_file($file['tmp_name']) && preg_match('#file(\\d)#', $key, $matches) != 0) { $has_one = true; } } if ($has_one) { $LAX_COMCODE = true; } // We don't want a simple syntax error to cause us to lose our attachments } comcode_to_tempcode($comcode, $source_member, $as_admin, 60, NULL, $connection, false, false, false, false, true); $LAX_COMCODE = $temp; }
/** * @license http://opensource.org/licenses/cpal_1.0 Common Public Attribution License * @copyright ocProducts Ltd * @package activity_feed */ function activities_addon_syndicate_described_activity($a_language_string_code = '', $a_label_1 = '', $a_label_2 = '', $a_label_3 = '', $a_pagelink_1 = '', $a_pagelink_2 = '', $a_pagelink_3 = '', $a_addon = '', $a_is_public = 1, $a_member_id = NULL, $sitewide_too = false, $a_also_involving = NULL) { require_code('activities'); require_lang('activities'); if (get_db_type() == 'xml' && get_param_integer('keep_testing_logging', 0) != 1) { return NULL; } $stored_id = 0; if (is_null($a_member_id)) { $a_member_id = get_member(); } if (is_guest($a_member_id)) { return NULL; } $go = array('a_language_string_code' => $a_language_string_code, 'a_label_1' => $a_label_1, 'a_label_2' => $a_label_2, 'a_label_3' => $a_label_3, 'a_is_public' => $a_is_public); $stored_id = mixed(); // Check if this has been posted previously (within the last 10 minutes) to // stop spamming but allow generalised repeat status messages. $test = $GLOBALS['SITE_DB']->query_select('activities', array('a_language_string_code', 'a_label_1', 'a_label_2', 'a_label_3', 'a_is_public'), NULL, 'WHERE a_time>' . strval(time() - 600), 1); if (!array_key_exists(0, $test) || $test[0] != $go || running_script('execute_temp')) { // Log the activity $row = $go + array('a_member_id' => $a_member_id, 'a_also_involving' => $a_also_involving, 'a_pagelink_1' => $a_pagelink_1, 'a_pagelink_2' => $a_pagelink_2, 'a_pagelink_3' => $a_pagelink_3, 'a_time' => time(), 'a_addon' => $a_addon, 'a_is_public' => $a_is_public); $stored_id = $GLOBALS['SITE_DB']->query_insert('activities', $row, true); // Update the latest activity file log_newest_activity($stored_id, 1000); // External places if ($a_is_public == 1 && !$GLOBALS['IS_ACTUALLY_ADMIN']) { $dests = find_all_hooks('systems', 'syndication'); foreach (array_keys($dests) as $hook) { require_code('hooks/systems/syndication/' . $hook); $ob = object_factory('Hook_Syndication_' . $hook); if ($ob->is_available()) { $ob->syndicate_user_activity($a_member_id, $row); if ($sitewide_too && has_specific_permission(get_member(), 'syndicate_site_activity') && post_param_integer('syndicate_this', 0) == 1) { $ob->syndicate_site_activity($row); } } } } list($message) = render_activity($row, false); require_code('notifications'); $username = $GLOBALS['FORUM_DRIVER']->get_username($a_member_id); $subject = do_lang('ACTIVITY_NOTIFICATION_MAIL_SUBJECT', get_site_name(), $username, html_entity_decode(strip_tags($message->evaluate()), ENT_QUOTES, get_charset())); $mail = do_lang('ACTIVITY_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($username), array('[semihtml]' . $message->evaluate() . '[/semihtml]')); dispatch_notification('activity', strval($a_member_id), $subject, $mail); } return $stored_id; }
/** * Standard modular install function. * * @param ?integer What version we're upgrading from (NULL: new install) * @param ?integer What hack version we're upgrading from (NULL: new-install/not-upgrading-from-a-hacked-version) */ function install($upgrade_from = NULL, $upgrade_from_hack = NULL) { add_config_option('_MESSAGING_FORUM_NAME', 'messaging_forum_name', 'forum', 'return do_lang(\'MESSAGING_FORUM_NAME\',\'\',\'\',\'\',get_site_default_lang());', 'FEATURE', 'CONTACT_US_MESSAGING'); if (get_forum_type() == 'ocf' && !running_script('upgrader')) { $moderator_groups = $GLOBALS['FORUM_DRIVER']->get_moderator_groups(); $staff_access = array(); foreach ($moderator_groups as $id) { $staff_access[$id] = 5; } ocf_require_all_forum_stuff(); require_code('ocf_forums_action'); require_code('ocf_forums_action2'); $GLOBALS['OCF_DRIVER'] = $GLOBALS['FORUM_DRIVER']; ocf_make_forum(do_lang('MESSAGING_FORUM_NAME'), '', db_get_first_id() + 1, $staff_access, db_get_first_id()); } }
/** * Standard modular render function for profile tab hooks. * * @param MEMBER The ID of the member who is being viewed * @param MEMBER The ID of the member who is doing the viewing * @param boolean Whether to leave the tab contents NULL, if tis hook supports it, so that AJAX can load it later * @return array A triple: The tab title, the tab contents, the suggested tab order */ function render_tab($member_id_of, $member_id_viewing, $leave_to_ajax_if_possible = false) { $GLOBALS['FEED_URL'] = find_script('backend') . '?mode=activities&filter=' . strval($member_id_of); require_lang('activities'); $title = do_lang_tempcode('ACTIVITIES_TITLE'); $order = 70; // Need to declare these here as the Tempcode engine can't look as deep, into a loop (I think), as it would need to, to find the block declaring the dependency require_css('activities'); require_javascript('javascript_activities_state'); require_javascript('javascript_activities'); require_javascript('javascript_jquery'); require_javascript('javascript_base64'); // Allow user to link up things for syndication $syndications = array(); if ($member_id_of == $member_id_viewing) { $dests = find_all_hooks('systems', 'syndication'); foreach (array_keys($dests) as $hook) { require_code('hooks/systems/syndication/' . $hook); $ob = object_factory('Hook_Syndication_' . $hook); if ($ob->is_available()) { if (either_param('syndicate_stop__' . $hook, NULL) !== NULL) { $ob->auth_unset($member_id_of); } elseif (either_param('syndicate_start__' . $hook, NULL) !== NULL) { $url_map = array('page' => '_SELF', 'type' => 'view', 'id' => $member_id_of, 'oauth_in_progress' => 1); $url_map['syndicate_start__' . $hook] = 1; $oauth_url = build_url($url_map, '_SELF', NULL, false, false, false, 'tab__activities'); $ob->auth_set($member_id_of, $oauth_url); } elseif (running_script('index') && !$leave_to_ajax_if_possible && $ob->auth_is_set($member_id_of) && either_param('oauth_in_progress', NULL) === NULL && !$GLOBALS['IS_ACTUALLY_ADMIN']) { /* running_script('index') won't work currently due to execution contexts, and it is never non-AJAX, and it's probably not needed anyway // Do a refresh to make sure the token is updated $url_map=array('page'=>'_SELF','type'=>'view','id'=>$member_id_of,'oauth_in_progress'=>1); $url_map['syndicate_start__'.$hook]=1; $oauth_url=build_url($url_map,'_SELF',NULL,false,false,false,'tab__activities'); $ob->auth_set($member_id_of,$oauth_url); */ } $syndications[$hook] = array('SYNDICATION_IS_SET' => $ob->auth_is_set($member_id_of), 'SYNDICATION_SERVICE_NAME' => $ob->get_service_name()); } } } if ($leave_to_ajax_if_possible) { return array($title, NULL, $order); } $content = do_template('OCF_MEMBER_PROFILE_ACTIVITIES', array('MEMBER_ID' => strval($member_id_of), 'SYNDICATIONS' => $syndications)); return array($title, $content, $order); }
/** * Give ability to reply to any communication. * * @param AUTO_LINK The ID of the chat room * @param string The message used. * @return ?string Bot reply (NULL: bot does not handle the command) */ function reply_to_any_communication($room_id, $string) { $people = get_chatters_in_room($room_id); if (count($people) > 2) { return NULL; } // Don't spam if noone is here if (running_script('shoutbox')) { return NULL; } // Messes up shoutbox $is_im = $GLOBALS['SITE_DB']->query_value('chat_rooms', 'is_im', array('id' => $room_id)); if ($is_im == 1) { return NULL; } $message = preg_replace('#\\[[^\\[\\]]*\\]#U', '', $string); if ($message == '') { return NULL; } return $this->handle_commands($room_id, $message); }
/** * Add a download. * * @param AUTO_LINK The ID of the category the download is to be in * @param SHORT_TEXT The name of the download * @param URLPATH The URL to the download * @param LONG_TEXT The description of the download * @param ID_TEXT The author of the download (not necessarily same as the submitter) * @param LONG_TEXT The comments for the download * @param ?AUTO_LINK The out-mode-id (the ID of a download that this download is an old version of). Often people wonder why this is specified with the old version, and not the opposite with the new version - it is because statistically, we perceive more chance of downloads merging than splitting (NULL: none) * @param BINARY Whether the download has been validated * @param BINARY Whether the download may be rated * @param SHORT_INTEGER Whether comments are allowed (0=no, 1=yes, 2=review style) * @param BINARY Whether the download may be trackbacked * @param LONG_TEXT Hidden notes pertaining to the download * @param SHORT_TEXT The downloads original filename (the URL may be obfuscated) * @param integer The file size of the download (we can't really detect this in real-time for remote URLs) * @param integer The cost of the download that members will have to pay to get it * @param BINARY Whether the submitter gets the points for the download (they are selling it) (otherwise they are just thrown out, which is an alternative model - one of enforcing community point building) * @param ?AUTO_LINK The licence to use (NULL: none) * @param ?TIME The add date for the download (NULL: now) * @param integer The number of downloads that this download has had * @param integer The number of views that this download has had * @param ?MEMBER The submitter (NULL: current user) * @param ?TIME The edit date (NULL: never) * @param ?AUTO_LINK Force an ID (NULL: don't force an ID) * @return AUTO_LINK The ID of the newly added download */ function add_download($category_id, $name, $url, $description, $author, $comments, $out_mode_id, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes, $original_filename, $file_size, $cost, $submitter_gets_points, $licence = NULL, $add_date = NULL, $num_downloads = 0, $views = 0, $submitter = NULL, $edit_date = NULL, $id = NULL) { if (is_null($add_date)) { $add_date = time(); } if (is_null($submitter)) { $submitter = get_member(); } if ($file_size == 0 || url_is_local($url)) { if (url_is_local($url)) { $file_size = @filesize(get_custom_file_base() . '/' . rawurldecode($url)) or $file_size = NULL; } else { $file_size = @filesize($url) or $file_size = NULL; } } $met = @ini_get('max_execution_time'); $data_mash = $url == '' ? '' : create_data_mash($url, NULL, get_file_extension($original_filename)); if (function_exists('set_time_limit')) { @set_time_limit($met); } if (!addon_installed('unvalidated')) { $validated = 1; } $map = array('download_data_mash' => $data_mash, 'download_licence' => $licence, 'rep_image' => '', 'edit_date' => $edit_date, 'download_submitter_gets_points' => $submitter_gets_points, 'download_cost' => $cost, 'original_filename' => $original_filename, 'download_views' => $views, 'allow_rating' => $allow_rating, 'allow_comments' => $allow_comments, 'allow_trackbacks' => $allow_trackbacks, 'notes' => $notes, 'submitter' => $submitter, 'default_pic' => 1, 'num_downloads' => $num_downloads, 'out_mode_id' => $out_mode_id, 'category_id' => $category_id, 'name' => insert_lang($name, 2), 'url' => $url, 'description' => insert_lang_comcode($description, 3), 'author' => $author, 'comments' => insert_lang_comcode($comments, 3), 'validated' => $validated, 'add_date' => $add_date, 'file_size' => $file_size); if (!is_null($id)) { $map['id'] = $id; } $id = $GLOBALS['SITE_DB']->query_insert('download_downloads', $map, true); require_code('seo2'); seo_meta_set_for_implicit('downloads_download', strval($id), array($name, $description, $comments), $description); // Make its gallery if (addon_installed('galleries') && !running_script('stress_test_loader')) { $test = $GLOBALS['SITE_DB']->query_value_null_ok('galleries', 'name', array('name' => 'download_' . strval($id))); if (is_null($test)) { require_code('galleries2'); $download_gallery_root = get_option('download_gallery_root'); if (is_null($download_gallery_root)) { $download_gallery_root = 'root'; } add_gallery('download_' . strval($id), do_lang('GALLERY_FOR_DOWNLOAD', $name), '', '', '', $download_gallery_root); } } // Stat update_stat('num_archive_downloads', 1); if ($file_size > 0) { update_stat('archive_size', $file_size); } if ($validated == 1) { require_lang('downloads'); require_code('notifications'); $subject = do_lang('DOWNLOAD_NOTIFICATION_MAIL_SUBJECT', get_site_name(), $name); $self_url = build_url(array('page' => 'downloads', 'type' => 'entry', 'id' => $id), get_module_zone('downloads'), NULL, false, false, true); $mail = do_lang('DOWNLOAD_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($name), array(comcode_escape($self_url->evaluate()))); dispatch_notification('download', strval($category_id), $subject, $mail); } log_it('ADD_DOWNLOAD', strval($id), $name); decache('main_recent_downloads'); decache('main_top_downloads'); decache('main_download_category'); decache('main_download_tease'); return $id; }
/** * Get the value for the specified field, for the stated catalogue entry. * * @param AUTO_LINK The ID of the field we are getting * @param mixed The ID of the entry we are getting for OR the row * @param ID_TEXT The type of field * @set short long * @param ?array A list of field IDs that we are limiting ourselves to (NULL: get ALL fields) * @return string The value */ function _get_catalogue_entry_field($field_id, $entry_id, $type = 'short', $only_field_ids = NULL) { if (is_array($entry_id)) { $entry_id = $entry_id['id']; } global $SITE_INFO; if (!running_script('ajax_tree') && (!isset($SITE_INFO['mysql_old']) || $SITE_INFO['mysql_old'] == '0') && (!isset($SITE_INFO['mysql_old']) || !is_file(get_file_base() . '/mysql_old'))) { // Pre-caching of whole entry static $catalogue_entry_cache = array(); if (!isset($catalogue_entry_cache[$entry_id][$field_id])) { if (!isset($catalogue_entry_cache[$entry_id])) { $catalogue_entry_cache[$entry_id] = array(); } $query = ''; foreach (array('catalogue_efv_float', 'catalogue_efv_integer', 'catalogue_efv_long', 'catalogue_efv_long_trans', 'catalogue_efv_short', 'catalogue_efv_short_trans') as $table) { if ($query != '') { $query .= ' UNION '; } $query .= 'SELECT f.id,v.cv_value,'; if (strpos($table, '_trans') !== false) { $query .= 't.text_original,t.text_parsed'; } else { $query .= 'NULL AS text_original,NULL AS text_parsed'; } $query .= ' FROM ' . get_table_prefix() . 'catalogue_fields f JOIN ' . get_table_prefix() . $table . ' v ON v.cf_id=f.id'; if (strpos($table, '_trans') !== false) { $query .= ' JOIN ' . get_table_prefix() . 'translate t ON t.id=v.cv_value'; } $query .= ' WHERE v.ce_id=' . strval($entry_id); if (!is_null($only_field_ids)) { $query .= ' AND ('; if ($only_field_ids != array()) { foreach ($only_field_ids as $i => $_field_id) { if ($i != 0) { $query .= ' OR '; } $query .= 'f.id=' . strval($_field_id); } } else { $query .= '1=0'; } $query .= ')'; } } foreach ($GLOBALS['SITE_DB']->query($query, NULL, NULL, false, true) as $line) { $catalogue_entry_cache[$entry_id][$line['id']] = $line['cv_value']; if (isset($line['text_original'])) { $GLOBALS['SITE_DB']->text_lookup_original_cache[$line['cv_value']] = $line['text_original']; $GLOBALS['SITE_DB']->text_lookup_cache[$line['cv_value']] = $line['text_parsed']; } } } $value = isset($catalogue_entry_cache[$entry_id][$field_id]) ? $catalogue_entry_cache[$entry_id][$field_id] : NULL; } else { $value = $GLOBALS['SITE_DB']->query_value_null_ok('catalogue_efv_' . $type, 'cv_value', array('cf_id' => $field_id, 'ce_id' => $entry_id)); } if (is_integer($value)) { $value = strval($value); } if (is_float($value)) { $value = float_to_raw_string($value); } return $value; }
/** * Find whether we can get away with natural file access, not messing with AFMs, world-writability, etc. * * @return boolean Whether we have this */ function is_suexec_like() { return function_exists('posix_getuid') && strpos(@ini_get('disable_functions'), 'posix_getuid') === false && !isset($_SERVER['HTTP_X_MOSSO_DT']) && is_integer(@posix_getuid()) && @posix_getuid() == @fileowner(get_file_base() . '/' . (running_script('install') ? 'install.php' : 'index.php')) || is_writable_wrap(get_file_base() . '/' . (running_script('index') ? 'index.php' : 'install.php')); }
/** * Send out a notification to members enabled. */ function dispatch() { if (running_script('stress_test_loader')) { return; } if (get_page_name() == 'admin_import') { return; } $subject = $this->subject; $message = $this->message; $no_cc = $this->no_cc; if ($GLOBALS['DEBUG_MODE']) { if (strpos($this->message, 'keep_devtest') !== false && $this->notification_code != 'hack_attack' && $this->notification_code != 'auto_ban' && strpos($this->message, running_script('index') ? static_evaluate_tempcode(build_url(array('page' => '_SELF'), '_SELF', NULL, true, false, true)) : get_self_url_easy()) === false && (strpos(ocp_srv('HTTP_REFERER'), 'keep_devtest') === false || strpos($this->message, ocp_srv('HTTP_REFERER')) === false)) { // Bad URL - it has to be general, not session-specific fatal_exit(do_lang_tempcode('INTERNAL_ERROR')); } } $ob = _get_notification_ob_for_code($this->notification_code); if (is_null($ob)) { if (get_page_name() != 'admin_setupwizard') { // Setupwizard may have removed after register_shutdown_function was called fatal_exit('Missing notification code: ' . $this->notification_code); } return; } require_lang('notifications'); require_code('mail'); if (function_exists('set_time_limit')) { @set_time_limit(0); } if ($this->store_in_staff_messaging_system && addon_installed('staff_messaging')) { require_lang('messaging'); list($type, $id) = explode('_', $this->code_category, 2); $message_url = build_url(array('page' => 'admin_messaging', 'type' => 'view', 'id' => $id, 'message_type' => $type), get_module_zone('admin_messaging'), NULL, false, false, true); $message = do_lang('MESSAGING_NOTIFICATION_WRAPPER', $message, $message_url->evaluate()); require_code('feedback'); actualise_post_comment(true, $type, $id, $message_url, $subject, get_option('messaging_forum_name'), true, 1, true, true, true); } $testing = get_param_integer('keep_debug_notifications', 0) == 1; $start = 0; $max = 300; do { list($members, $possibly_has_more) = $ob->list_members_who_have_enabled($this->notification_code, $this->code_category, $this->to_member_ids, $start, $max); if (get_value('notification_safety_testing') === '1') { if (count($members) > 20) { $members = array(6 => A_INSTANT_EMAIL); // This is just for testing on ocportal.com, if lots of notifications going out it's probably a scary bug, so send just to Chris (#6) with a note $message = 'OVER-ADDRESSED?' . "\n\n" . $message; } } foreach ($members as $to_member_id => $setting) { if (!is_null($this->no_notify_for__notification_code)) { if (notifications_enabled($this->no_notify_for__notification_code, $this->no_notify_for__code_category, $to_member_id)) { continue; } // Signal they are getting some other notification for this } if ($to_member_id !== $this->from_member_id || $testing) { $no_cc = _dispatch_notification_to_member($to_member_id, $setting, $this->notification_code, $this->code_category, $subject, $message, $this->from_member_id, $this->priority, $no_cc); } } $start += $max; } while ($possibly_has_more); }
/** * Attempt to send an e-mail to the specified recipient. The mail will be forwarding to the CC address specified in the options (if there is one, and if not specified not to cc). * The mail will be sent in dual HTML/text format, where the text is the unconverted comcode source: if a member does not read HTML mail, they may wish to fallback to reading that. * * @param string The subject of the mail in plain text * @param LONG_TEXT The message, as Comcode * @param ?array The destination (recipient) e-mail addresses [array of strings] (NULL: site staff address) * @param ?mixed The recipient name. Array or string. (NULL: site name) * @param EMAIL The from address (blank: site staff address) * @param string The from name (blank: site name) * @param integer The message priority (1=urgent, 3=normal, 5=low) * @range 1 5 * @param ?array An list of attachments (each attachment being a map, path=>filename) (NULL: none) * @param boolean Whether to NOT CC to the CC address * @param ?MEMBER Convert comcode->tempcode as this member (a privilege thing: we don't want people being able to use admin rights by default!) (NULL: guest) * @param boolean Replace above with arbitrary admin * @param boolean HTML-only * @param boolean Whether to bypass queueing, because this code is running as a part of the queue management tools * @param ID_TEXT The template used to show the email * @param boolean Whether to bypass queueing * @return ?tempcode A full page (not complete XHTML) piece of tempcode to output (NULL: it worked so no tempcode message) */ function mail_wrap($subject_tag, $message_raw, $to_email = NULL, $to_name = NULL, $from_email = '', $from_name = '', $priority = 3, $attachments = NULL, $no_cc = false, $as = NULL, $as_admin = false, $in_html = false, $coming_out_of_queue = false, $mail_template = 'MAIL', $bypass_queue = false) { if (get_option('smtp_sockets_use') == '0') { return non_overrided__mail_wrap($subject_tag, $message_raw, $to_email, $to_name, $from_email, $from_name, $priority, $attachments, $no_cc, $as, $as_admin, $in_html, $coming_out_of_queue); } if (running_script('stress_test_loader')) { return NULL; } if (is_null($bypass_queue)) { $bypass_queue = $priority < 3 || strpos(serialize($attachments), 'tmpfile') !== false; } global $EMAIL_ATTACHMENTS; $EMAIL_ATTACHMENTS = array(); require_code('site'); require_code('mime_types'); if (is_null($as)) { $as = $GLOBALS['FORUM_DRIVER']->get_guest_id(); } if (!$coming_out_of_queue) { $GLOBALS['SITE_DB']->query('DELETE FROM ' . get_table_prefix() . 'logged_mail_messages WHERE m_date_and_time<' . strval(time() - 60 * 60 * 24 * 14) . ' AND m_queued=0'); // Log it all for 2 weeks, then delete $through_queue = !$bypass_queue && (get_option('mail_queue_debug') === '1' || get_option('mail_queue') === '1' && cron_installed()); $GLOBALS['SITE_DB']->query_insert('logged_mail_messages', array('m_subject' => $subject_tag, 'm_message' => $message_raw, 'm_to_email' => serialize($to_email), 'm_to_name' => serialize($to_name), 'm_from_email' => $from_email, 'm_from_name' => $from_name, 'm_priority' => 3, 'm_attachments' => serialize($attachments), 'm_no_cc' => $no_cc ? 1 : 0, 'm_as' => $as, 'm_as_admin' => $as_admin ? 1 : 0, 'm_in_html' => $in_html ? 1 : 0, 'm_date_and_time' => time(), 'm_member_id' => get_member(), 'm_url' => get_self_url(true), 'm_queued' => $through_queue ? 1 : 0, 'm_template' => $mail_template)); if ($through_queue) { return NULL; } } if (count($attachments) == 0) { $attachments = NULL; } global $SENDING_MAIL; if ($SENDING_MAIL) { return NULL; } $SENDING_MAIL = true; // To and from, and language $staff_address = get_option('staff_address'); if (is_null($to_email)) { $to_email = array($staff_address); } $to_email_new = array(); foreach ($to_email as $test_address) { if ($test_address != '') { $to_email_new[] = $test_address; } } $to_email = $to_email_new; if ($to_email == array()) { $SENDING_MAIL = false; return NULL; } if ($to_email[0] == $staff_address) { $lang = get_site_default_lang(); } else { $lang = user_lang(); if (method_exists($GLOBALS['FORUM_DRIVER'], 'get_member_from_email_address')) { $member_id = $GLOBALS['FORUM_DRIVER']->get_member_from_email_address($to_email[0]); if (!is_null($member_id)) { $lang = get_lang($member_id); } } } if (is_null($to_name)) { if ($to_email[0] == $staff_address) { $to_name = get_site_name(); } else { $to_name = ''; } } if ($from_email == '') { $from_email = get_option('staff_address'); } if ($from_name == '') { $from_name = get_site_name(); } $theme = method_exists($GLOBALS['FORUM_DRIVER'], 'get_theme') ? $GLOBALS['FORUM_DRIVER']->get_theme() : 'default'; if ($theme == 'default') { $theme = $GLOBALS['FORUM_DRIVER']->get_theme(''); // ... So get theme of welcome zone } // Our subject $_subject = do_template('MAIL_SUBJECT', array('_GUID' => '44a57c666bb00f96723256e26aade9e5', 'SUBJECT_TAG' => $subject_tag), $lang, false, NULL, '.tpl', 'templates', $theme); $subject = $_subject->evaluate($lang); // Note that this is slightly against spec, because characters aren't forced to be printable us-ascii. But it's better we allow this (which works in practice) than risk incompatibility via charset-base64 encoding. // Evaluate message. Needs doing early so we know if we have any headers // Misc settings $website_email = get_option('website_email'); if ($website_email == '') { $website_email = $from_email; } $cc_address = $no_cc ? '' : get_option("cc_address"); global $CID_IMG_ATTACHMENT; $CID_IMG_ATTACHMENT = array(); // Decide message $GLOBALS['NO_LINK_TITLES'] = true; global $LAX_COMCODE; $temp = $LAX_COMCODE; $LAX_COMCODE = true; $html_content = comcode_to_tempcode($message_raw, $as, $as_admin); $LAX_COMCODE = $temp; $GLOBALS['NO_LINK_TITLES'] = false; if (!$in_html) { $_html_content = $html_content->evaluate($lang); $_html_content = preg_replace('#(keep|for)_session=[\\d\\w]*#', 'filtered=1', $_html_content); $message_html = strpos($_html_content, '<html') !== false ? make_string_tempcode($_html_content) : do_template($mail_template, array('_GUID' => 'b23069c20202aa59b7450ebf8d49cde1', 'CSS' => '{CSS}', 'LOGOURL' => get_logo_url(''), 'LANG' => $lang, 'TITLE' => $subject, 'CONTENT' => $_html_content), $lang, false, NULL, '.tpl', 'templates', $theme); $css = css_tempcode(true, true, $message_html->evaluate($lang), $theme); $_css = $css->evaluate($lang); if (get_option('allow_ext_images') != '1') { $_css = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $_css); } $html_evaluated = $message_html->evaluate($lang); $html_evaluated = str_replace('{CSS}', $_css, $html_evaluated); // Cleanup the Comcode a bit $message_plain = comcode_to_clean_text($message_raw); } else { $html_evaluated = $message_raw; } // Character set $regexp = '#^[\\x' . dechex(32) . '-\\x' . dechex(126) . ']*$#'; $charset = preg_match($regexp, $html_evaluated) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii'; // CID attachments if (get_option('allow_ext_images') != '1') { $html_evaluated = preg_replace_callback('#<img\\s([^>]*)src="(http://[^"]*)"#U', '_mail_img_rep_callback', $html_evaluated); $matches = array(); foreach (array('#<([^"<>]*\\s)style="([^"]*)"#', '#<style( [^<>]*)?' . '>(.*)</style>#Us') as $over) { $num_matches = preg_match_all($over, $html_evaluated, $matches); for ($i = 0; $i < $num_matches; $i++) { $altered_inner = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $matches[2][$i]); if ($matches[2][$i] != $altered_inner) { $altered_outer = str_replace($matches[2][$i], $altered_inner, $matches[0][$i]); $html_evaluated = str_replace($matches[0][$i], $altered_outer, $html_evaluated); } } } } $cid_attachments = array(); foreach ($CID_IMG_ATTACHMENT as $id => $img) { $file_path_stub = convert_url_to_path($img); $mime_type = get_mime_type(get_file_extension($img)); $filename = basename($img); if (!is_null($file_path_stub)) { $cid_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $file_path_stub, 'temp' => false, 'cid' => $id); } else { $myfile = ocp_tempnam('email_attachment'); http_download_file($img, NULL, false, false, 'ocPortal', NULL, NULL, NULL, NULL, NULL, $myfile); if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) { $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE']; } if (!is_null($GLOBALS['HTTP_FILENAME'])) { $filename = $GLOBALS['HTTP_FILENAME']; } $cid_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $myfile, 'temp' => true, 'cid' => $id); } $cid_attachments[] = $cid_attachment; } // Attachments $real_attachments = array(); $attachments = array_merge(is_null($attachments) ? array() : $attachments, $EMAIL_ATTACHMENTS); if (!is_null($attachments)) { foreach ($attachments as $path => $filename) { $mime_type = get_mime_type(get_file_extension($filename)); if (strpos($path, '://') === false) { $real_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $path, 'temp' => false); } else { $myfile = ocp_tempnam('email_attachment'); http_download_file($path, NULL, false, false, 'ocPortal', NULL, NULL, NULL, NULL, NULL, $myfile); if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) { $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE']; } if (!is_null($GLOBALS['HTTP_FILENAME'])) { $filename = $GLOBALS['HTTP_FILENAME']; } $real_attachment = array('mime' => $mime_type, 'filename' => $filename, 'path' => $myfile, 'temp' => true); } $real_attachments[] = $real_attachment; } } // ========================== // Interface with SwiftMailer // ========================== require_code('Swift-4.1.1/lib/swift_required'); // Read in SMTP settings $host = get_option('smtp_sockets_host'); $port = intval(get_option('smtp_sockets_port')); $username = get_option('smtp_sockets_username'); $password = get_option('smtp_sockets_password'); $smtp_from_address = get_option('smtp_from_address'); if ($smtp_from_address != '') { $from_email = $smtp_from_address; } // Create the Transport $transport = Swift_SmtpTransport::newInstance($host, $port)->setUsername($username)->setPassword($password); if ($port == 419 || $port == 465 || $port == 587) { $transport->setEncryption('tls'); } // Create the Mailer using your created Transport $mailer = Swift_Mailer::newInstance($transport); // Create a message $to_array = array(); if ($to_name === '') { foreach ($to_email as $_to_email) { $to_array[] = $_to_email; } } else { foreach ($to_email as $i => $_to_email) { $to_array[$_to_email] = is_array($to_name) ? $to_name[$i] : $to_name; } } $message = Swift_Message::newInstance($subject)->setFrom(array($website_email => $from_name))->setReplyTo(array($from_email => $from_name))->setTo($to_array)->setPriority($priority)->setCharset($charset)->setBody($html_evaluated, 'text/html', $charset)->addPart($message_plain, 'text/plain', $charset); if ($cc_address != '') { $message->setCc($cc_address); } // Attachments foreach ($real_attachments as $r) { $attachment = Swift_Attachment::fromPath($r['path'], $r['mime'])->setFilename($r['filename'])->setDisposition('attachment'); $message->attach($attachment); } foreach ($cid_attachments as $r) { $attachment = Swift_Attachment::fromPath($r['path'], $r['mime'])->setFilename($r['filename'])->setDisposition('attachment')->setId($r['cid']); $message->attach($attachment); } // Send the message, and error collection $error = ''; try { $result = $mailer->send($message); } catch (Exception $e) { $error = $e->getMessage(); } if ($error == '' && !$result) { $error = 'Unknown error'; } // Attachment cleanup foreach ($real_attachments as $r) { if ($r['temp']) { @unlink($r['path']); } } foreach ($cid_attachments as $r) { if ($r['temp']) { @unlink($r['path']); } } // Return / Error handling $SENDING_MAIL = false; if ($error != '') { if (get_param_integer('keep_hide_mail_failure', 0) == 0) { require_code('site'); attach_message(!is_null($error) ? make_string_tempcode($error) : do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))), 'warn'); } else { return warn_screen(get_page_title('ERROR_OCCURRED'), do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address')))); } } return NULL; }
/** * Makes a post in the specified forum, in the specified topic according to the given specifications. If the topic doesn't exist, it is created along with a spacer-post. * Spacer posts exist in order to allow staff to delete the first true post in a topic. Without spacers, this would not be possible with most forum systems. They also serve to provide meta information on the topic that cannot be encoded in the title (such as a link to the content being commented upon). * * @param object Link to the real forum driver * @param SHORT_TEXT The forum name * @param SHORT_TEXT The topic identifier (usually <content-type>_<content-id>) * @param MEMBER The member ID * @param LONG_TEXT The post title * @param LONG_TEXT The post content in Comcode format * @param string The topic title; must be same as content title if this is for a comment topic * @param string This is put together with the topic identifier to make a more-human-readable topic title or topic description (hopefully the latter and a $content_title title, but only if the forum supports descriptions) * @param ?URLPATH URL to the content (NULL: do not make spacer post) * @param ?TIME The post time (NULL: use current time) * @param ?IP The post IP address (NULL: use current members IP address) * @param ?BINARY Whether the post is validated (NULL: unknown, find whether it needs to be marked unvalidated initially). This only works with the OCF driver. * @param ?BINARY Whether the topic is validated (NULL: unknown, find whether it needs to be marked unvalidated initially). This only works with the OCF driver. * @param boolean Whether to skip post checks * @param SHORT_TEXT The name of the poster * @param ?AUTO_LINK ID of post being replied to (NULL: N/A) * @param boolean Whether the reply is only visible to staff * @param ?ID_TEXT DO NOT send notifications to: The notification code (NULL: no restriction) * @param ?SHORT_TEXT DO NOT send notifications to: The category within the notification code (NULL: none / no restriction) * @return array Topic ID (may be NULL), and whether a hidden post has been made */ function _helper_make_post_forum_topic($this_ref, $forum_name, $topic_identifier, $member_id, $post_title, $post, $content_title, $topic_identifier_encapsulation_prefix, $content_url, $time, $ip, $validated, $topic_validated, $skip_post_checks, $poster_name_if_guest, $parent_id, $staff_only, $no_notify_for__notification_code, $no_notify_for__code_category) { if (is_null($time)) { $time = time(); } if (is_null($ip)) { $ip = get_ip_address(); } require_code('comcode_check'); check_comcode($post, NULL, false, NULL, true); require_code('ocf_topics'); require_code('ocf_posts'); //require_code('ocf_forums'); require_lang('ocf'); require_code('ocf_posts_action'); require_code('ocf_posts_action2'); if (!is_integer($forum_name)) { $forum_id = $this_ref->forum_id_from_name($forum_name); if (is_null($forum_id)) { warn_exit(do_lang_tempcode('MISSING_FORUM', escape_html($forum_name))); } } else { $forum_id = (int) $forum_name; } $topic_id = $this_ref->find_topic_id_for_topic_identifier($forum_name, $topic_identifier); $update_caching = false; $support_attachments = false; if (!running_script('stress_test_loader') && get_page_name() != 'admin_import') { $update_caching = true; $support_attachments = true; } if (is_null($topic_id)) { $is_starter = true; require_code('ocf_topics_action'); $topic_id = ocf_make_topic($forum_id, $topic_identifier_encapsulation_prefix . ': #' . $topic_identifier, '', $topic_validated, 1, 0, 0, 0, NULL, NULL, false, 0, NULL, $content_url); if (strpos($topic_identifier, ':') !== false) { // Sync comment_posted ones to also monitor the forum ones; no need for opposite way as comment ones already trigger forum ones $start = 0; $max = 300; require_code('notifications'); $ob = _get_notification_ob_for_code('comment_posted'); do { list($members, $possibly_has_more) = $ob->list_members_who_have_enabled('comment_posted', $topic_identifier, NULL, $start, $max); foreach ($members as $to_member_id => $setting) { enable_notifications('ocf_topic', strval($topic_id), $to_member_id); } $start += $max; } while ($possibly_has_more); } // Make spacer post if (!is_null($content_url)) { $spacer_title = $content_title; $home_link = hyperlink($content_url, escape_html($content_title)); $spacer_post = '[semihtml]' . do_lang('SPACER_POST', $home_link->evaluate(), '', '', get_site_default_lang()) . '[/semihtml]'; ocf_make_post($topic_id, $spacer_title, $spacer_post, 0, true, 1, 0, do_lang('SYSTEM'), $ip, $time, db_get_first_id(), NULL, NULL, NULL, false, $update_caching, $forum_id, $support_attachments, $content_title, 0, NULL, false, false, false, false); $is_starter = false; } $is_new = true; } else { $is_starter = false; $is_new = false; } $GLOBALS['LAST_TOPIC_ID'] = $topic_id; $GLOBALS['LAST_TOPIC_IS_NEW'] = $is_new; if ($post == '') { return array(NULL, false); } ocf_check_post($post, $topic_id, $member_id); $poster_name = $poster_name_if_guest; if ($poster_name == '') { $poster_name = $this_ref->get_username($member_id); } $post_id = ocf_make_post($topic_id, $post_title, $post, 0, $is_starter, $validated, 0, $poster_name, $ip, $time, $member_id, $staff_only ? $GLOBALS['FORUM_DRIVER']->get_guest_id() : NULL, NULL, NULL, false, $update_caching, $forum_id, $support_attachments, $content_title, 0, NULL, false, $skip_post_checks, false, false, $parent_id); $GLOBALS['LAST_POST_ID'] = $post_id; if ($is_new) { // Broken cache now for the rest of this page view - fix by flushing global $TOPIC_IDENTIFIERS_TO_IDS; $TOPIC_IDENTIFIERS_TO_IDS = array(); } // Send out notifications $_url = build_url(array('page' => 'topicview', 'type' => 'findpost', 'id' => $post_id), 'forum', NULL, false, false, true, 'post_' . strval($post_id)); $url = $_url->evaluate(); ocf_send_topic_notification($url, $topic_id, $forum_id, $member_id, $is_new, $post, $content_title, NULL, false, $no_notify_for__notification_code, $no_notify_for__code_category); $is_hidden = false; if (!running_script('stress_test_loader') && get_page_name() != 'admin_import') { $validated_actual = $this_ref->connection->query_value('f_posts', 'p_validated', array('id' => $post_id)); if ($validated_actual == 0) { require_code('site'); attach_message(do_lang_tempcode('SUBMIT_UNVALIDATED'), 'inform'); $is_hidden = true; } } return array($topic_id, $is_hidden); }
/** * Attempt to send an e-mail to the specified recipient. The mail will be forwarding to the CC address specified in the options (if there is one, and if not specified not to cc). * The mail will be sent in dual HTML/text format, where the text is the unconverted comcode source: if a member does not read HTML mail, they may wish to fallback to reading that. * * @param string The subject of the mail in plain text * @param LONG_TEXT The message, as Comcode * @param ?array The destination (recipient) e-mail addresses [array of strings] (NULL: site staff address) * @param ?mixed The recipient name. Array or string. (NULL: site name) * @param EMAIL The from address (blank: site staff address) * @param string The from name (blank: site name) * @param integer The message priority (1=urgent, 3=normal, 5=low) * @range 1 5 * @param ?array An list of attachments (each attachment being a map, path=>filename) (NULL: none) * @param boolean Whether to NOT CC to the CC address * @param ?MEMBER Convert comcode->tempcode as this member (a privilege thing: we don't want people being able to use admin rights by default!) (NULL: guest) * @param boolean Replace above with arbitrary admin * @param boolean HTML-only * @param boolean Whether to bypass queueing, because this code is running as a part of the queue management tools * @param ID_TEXT The template used to show the email * @param boolean Whether to bypass queueing * @return ?tempcode A full page (not complete XHTML) piece of tempcode to output (NULL: it worked so no tempcode message) */ function mail_wrap($subject_tag, $message_raw, $to_email = NULL, $to_name = NULL, $from_email = '', $from_name = '', $priority = 3, $attachments = NULL, $no_cc = false, $as = NULL, $as_admin = false, $in_html = false, $coming_out_of_queue = false, $mail_template = 'MAIL', $bypass_queue = false) { if (running_script('stress_test_loader')) { return NULL; } global $EMAIL_ATTACHMENTS; $EMAIL_ATTACHMENTS = array(); require_code('site'); require_code('mime_types'); $bypass_queue = $bypass_queue || $priority < 3 || strpos(serialize($attachments), 'tmpfile') !== false; if (is_null($as)) { $as = $GLOBALS['FORUM_DRIVER']->get_guest_id(); } if (!$coming_out_of_queue) { $GLOBALS['SITE_DB']->query('DELETE FROM ' . get_table_prefix() . 'logged_mail_messages WHERE m_date_and_time<' . strval(time() - 60 * 60 * 24 * 14) . ' AND m_queued=0'); // Log it all for 2 weeks, then delete $through_queue = !$bypass_queue && (get_option('mail_queue_debug') === '1' || get_option('mail_queue') === '1' && cron_installed()); $GLOBALS['SITE_DB']->query_insert('logged_mail_messages', array('m_subject' => substr($subject_tag, 0, 255), 'm_message' => $message_raw, 'm_to_email' => serialize($to_email), 'm_to_name' => serialize($to_name), 'm_from_email' => $from_email, 'm_from_name' => $from_name, 'm_priority' => $priority, 'm_attachments' => serialize($attachments), 'm_no_cc' => $no_cc ? 1 : 0, 'm_as' => $as, 'm_as_admin' => $as_admin ? 1 : 0, 'm_in_html' => $in_html ? 1 : 0, 'm_date_and_time' => time(), 'm_member_id' => get_member(), 'm_url' => get_self_url(true), 'm_queued' => $through_queue ? 1 : 0, 'm_template' => $mail_template), false, !$through_queue); // No errors if we don't NEED this to work if ($through_queue) { return NULL; } } if (count($attachments) == 0) { $attachments = NULL; } global $SENDING_MAIL; if ($SENDING_MAIL) { return NULL; } $SENDING_MAIL = true; // To and from, and language $staff_address = get_option('staff_address'); if (is_null($to_email)) { $to_email = array($staff_address); } $to_email_new = array(); foreach ($to_email as $test_address) { if ($test_address != '') { $to_email_new[] = $test_address; } } $to_email = $to_email_new; if ($to_email == array()) { $SENDING_MAIL = false; return NULL; } if ($to_email[0] == $staff_address) { $lang = get_site_default_lang(); } else { $lang = user_lang(); if (method_exists($GLOBALS['FORUM_DRIVER'], 'get_member_from_email_address')) { $member_id = $GLOBALS['FORUM_DRIVER']->get_member_from_email_address($to_email[0]); if (!is_null($member_id)) { $lang = get_lang($member_id); } } } if (is_null($to_name)) { if ($to_email[0] == $staff_address) { $to_name = get_site_name(); } else { $to_name = ''; } } if ($from_email == '') { $from_email = get_option('staff_address'); } if ($from_name == '') { $from_name = get_site_name(); } $from_email = str_replace("\r", '', $from_email); $from_email = str_replace("\n", '', $from_email); $from_name = str_replace("\r", '', $from_name); $from_name = str_replace("\n", '', $from_name); $theme = method_exists($GLOBALS['FORUM_DRIVER'], 'get_theme') ? $GLOBALS['FORUM_DRIVER']->get_theme() : 'default'; if ($theme == 'default') { $theme = $GLOBALS['FORUM_DRIVER']->get_theme(''); // ... So get theme of welcome zone } // Line termination is fiddly. It is safer to rely on sendmail supporting \n than undetectable-qmail/postfix-masquerading-as-sendmail not supporting the correct \r\n /*$sendmail_path=ini_get('sendmail_path'); if ((strpos($sendmail_path,'qmail')!==false) || (strpos($sendmail_path,'sendmail')!==false)) $line_term="\n"; else $line_term="\r\n"; */ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' || get_option('smtp_sockets_use') == '1') { $line_term = "\r\n"; /*} elseif (strtoupper(substr(PHP_OS,0,3))=='MAC') { $line_term="\r";*/ } else { $line_term = "\n"; } // We use the boundary to seperate message parts $_boundary = uniqid('ocPortal', true); $boundary = $_boundary . '_1'; $boundary2 = $_boundary . '_2'; $boundary3 = $_boundary . '_3'; // Our subject $subject = do_template('MAIL_SUBJECT', array('_GUID' => '44a57c666bb00f96723256e26aade9e5', 'SUBJECT_TAG' => $subject_tag), $lang, false, NULL, '.tpl', 'templates', $theme); $tightened_subject = $subject->evaluate($lang); // Note that this is slightly against spec, because characters aren't forced to be printable us-ascii. But it's better we allow this (which works in practice) than risk incompatibility via charset-base64 encoding. $tightened_subject = str_replace(chr(10), '', $tightened_subject); $tightened_subject = str_replace(chr(13), '', $tightened_subject); $regexp = '#^[\\x' . dechex(32) . '-\\x' . dechex(126) . ']*$#'; if (preg_match($regexp, $tightened_subject) == 0) { $tightened_subject = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($tightened_subject) . "?="; } if (preg_match($regexp, $from_name) == 0) { $from_name = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($from_name) . "?="; } if (is_array($to_name)) { foreach ($to_name as $i => $_to_name) { if (preg_match($regexp, $_to_name) == 0) { $to_name[$i] = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($_to_name) . "?="; } } } else { if (preg_match($regexp, $to_name) == 0) { $to_name = '=?' . do_lang('charset', NULL, NULL, NULL, $lang) . '?B?' . base64_encode($to_name) . "?="; } } $simplify_when_can = true; // Used for testing. Not actually needed // Evaluate message. Needs doing early so we know if we have any headers $GLOBALS['NO_LINK_TITLES'] = true; global $LAX_COMCODE; $temp = $LAX_COMCODE; $LAX_COMCODE = true; $html_content = comcode_to_tempcode($message_raw, $as, $as_admin); $LAX_COMCODE = $temp; $GLOBALS['NO_LINK_TITLES'] = false; $attachments = array_merge(is_null($attachments) ? array() : $attachments, $EMAIL_ATTACHMENTS); // Headers $website_email = get_option('website_email'); if ($website_email == '') { $website_email = $from_email; } if (get_value('use_true_from') !== '1') { $headers = 'From: "' . $from_name . '" <' . $website_email . '>' . $line_term; } else { $headers = 'From: <' . $from_email . '>' . $line_term; } $headers .= 'Reply-To: <' . $from_email . '>' . $line_term; $headers .= 'Return-Path: <' . $website_email . '>' . $line_term; $headers .= 'X-Sender: <' . $website_email . '>' . $line_term; $cc_address = $no_cc ? '' : get_option('cc_address'); if ($cc_address != '' && !in_array($cc_address, $to_email)) { $headers .= (get_option('bcc') == '1' ? 'Bcc: <' : 'Cc: <') . $cc_address . '>' . $line_term; } $headers .= 'Message-ID: <' . $_boundary . '@' . get_domain() . '>' . $line_term; $headers .= 'X-Priority: ' . strval($priority) . $line_term; $brand_name = get_value('rebrand_name'); if (is_null($brand_name)) { $brand_name = 'ocPortal'; } $headers .= 'X-Mailer: ' . $brand_name . $line_term; $headers .= 'MIME-Version: 1.0' . $line_term; if (!is_null($attachments) || !$simplify_when_can) { $headers .= 'Content-Type: multipart/mixed;' . "\n\t" . 'boundary="' . $boundary . '"'; } else { $headers .= 'Content-Type: multipart/alternative;' . "\n\t" . 'boundary="' . $boundary2 . '"'; } $sending_message = ''; $sending_message .= 'This is a multi-part message in MIME format.' . $line_term . $line_term; if (!is_null($attachments) || !$simplify_when_can) { $sending_message .= '--' . $boundary . $line_term; $sending_message .= 'Content-Type: multipart/alternative;' . "\n\t" . 'boundary="' . $boundary2 . '"' . $line_term . $line_term . $line_term; } global $CID_IMG_ATTACHMENT; $CID_IMG_ATTACHMENT = array(); // Message starts (actually: it is kind of in header form also as it uses mime multi-part) if (!$in_html) { $_html_content = $html_content->evaluate($lang); $_html_content = preg_replace('#(keep|for)_session=[\\d\\w]*#', 'filtered=1', $_html_content); $message_html = strpos($_html_content, '<html') !== false ? make_string_tempcode($_html_content) : do_template($mail_template, array('_GUID' => 'b23069c20202aa59b7450ebf8d49cde1', 'CSS' => '{CSS}', 'LOGOURL' => get_logo_url(''), 'LANG' => $lang, 'TITLE' => $subject, 'CONTENT' => $_html_content), $lang, false, NULL, '.tpl', 'templates', $theme); $css = css_tempcode(true, true, $message_html->evaluate($lang), $theme); $_css = $css->evaluate($lang); if (get_option('allow_ext_images') != '1') { $_css = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $_css); } $html_evaluated = $message_html->evaluate($lang); $html_evaluated = str_replace('{CSS}', $_css, $html_evaluated); // Cleanup the Comcode a bit $message_plain = comcode_to_clean_text($message_raw); } else { $html_evaluated = $message_raw; } $base64_encode = get_value('base64_emails') === '1'; // More robust, but more likely to be spam-blocked, and some servers can scramble it. // Plain version if (!$in_html) { $sending_message .= '--' . $boundary2 . $line_term; $sending_message .= 'Content-Type: text/plain; charset=' . (preg_match($regexp, $message_plain) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii') . $line_term; // '; name="message.txt"'. Outlook doesn't like: makes it think it's an attachment if ($base64_encode) { $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term; $sending_message .= chunk_split(base64_encode(unixify_line_format($message_plain)) . $line_term, 76, $line_term); } else { $sending_message .= 'Content-Transfer-Encoding: 8bit' . $line_term . $line_term; $sending_message .= wordwrap(str_replace(chr(10), $line_term, unixify_line_format($message_plain)) . $line_term, 998, $line_term); } } // HTML version $sending_message .= '--' . $boundary2 . $line_term; $sending_message .= 'Content-Type: multipart/related;' . "\n\t" . 'type="text/html";' . "\n\t" . 'boundary="' . $boundary3 . '"' . $line_term . $line_term . $line_term; $sending_message .= '--' . $boundary3 . $line_term; $sending_message .= 'Content-Type: text/html; charset=' . (preg_match($regexp, $html_evaluated) == 0 ? do_lang('charset', NULL, NULL, NULL, $lang) : 'us-ascii') . $line_term; // .'; name="message.html"'. Outlook doesn't like: makes it think it's an attachment if (get_option('allow_ext_images') != '1') { $html_evaluated = preg_replace_callback('#<img\\s([^>]*)src="(http://[^"]*)"#U', '_mail_img_rep_callback', $html_evaluated); $matches = array(); foreach (array('#<([^"<>]*\\s)style="([^"]*)"#', '#<style( [^<>]*)?' . '>(.*)</style>#Us') as $over) { $num_matches = preg_match_all($over, $html_evaluated, $matches); for ($i = 0; $i < $num_matches; $i++) { $altered_inner = preg_replace_callback('#url\\(["\']?(http://[^"]*)["\']?\\)#U', '_mail_css_rep_callback', $matches[2][$i]); if ($matches[2][$i] != $altered_inner) { $altered_outer = str_replace($matches[2][$i], $altered_inner, $matches[0][$i]); $html_evaluated = str_replace($matches[0][$i], $altered_outer, $html_evaluated); } } } } if ($base64_encode) { $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term; $sending_message .= chunk_split(base64_encode(unixify_line_format($html_evaluated)) . $line_term, 76, $line_term); } else { $sending_message .= 'Content-Transfer-Encoding: 8bit' . $line_term . $line_term; // Requires RFC 1652 $sending_message .= wordwrap(str_replace(chr(10), $line_term, unixify_line_format($html_evaluated)) . $line_term, 998, $line_term); } $total_filesize = 0; foreach ($CID_IMG_ATTACHMENT as $id => $img) { $sending_message .= '--' . $boundary3 . $line_term; $file_path_stub = convert_url_to_path($img); $mime_type = get_mime_type(get_file_extension($img)); $filename = basename($img); if (!is_null($file_path_stub)) { $total_filesize += @filesize($file_path_stub); if ($total_filesize > 1024 * 1024 * 5) { continue; } // Too large to process into an email $file_contents = @file_get_contents($file_path_stub); } else { $file_contents = http_download_file($img, NULL, false); $total_filesize += strlen($file_contents); if ($total_filesize >= 1024 * 1024 * 5) { continue; } // Too large to process into an email if (!is_null($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'])) { $mime_type = $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE']; } if (!is_null($GLOBALS['HTTP_FILENAME'])) { $filename = $GLOBALS['HTTP_FILENAME']; } } $sending_message .= 'Content-Type: ' . str_replace("\r", '', str_replace("\n", '', $mime_type)) . $line_term; $sending_message .= 'Content-ID: <' . $id . '>' . $line_term; $sending_message .= 'Content-Disposition: inline; filename="' . str_replace("\r", '', str_replace("\n", '', $filename)) . '"' . $line_term; $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term . $line_term; if (is_string($file_contents)) { $sending_message .= chunk_split(base64_encode($file_contents), 76, $line_term); } } $sending_message .= $line_term . '--' . $boundary3 . '--' . $line_term . $line_term; $sending_message .= $line_term . '--' . $boundary2 . '--' . $line_term . $line_term; // Attachments if (!is_null($attachments)) { foreach ($attachments as $path => $filename) { $sending_message .= '--' . $boundary . $line_term; $sending_message .= 'Content-Type: ' . get_mime_type(get_file_extension($filename)) . $line_term; // .'; name="'.str_replace("\r",'',str_replace("\n",'',$filename)).'"' http://www.imc.org/ietf-822/old-archive2/msg02121.html $sending_message .= 'Content-Transfer-Encoding: base64' . $line_term; $sending_message .= 'Content-Disposition: attachment; filename="' . str_replace("\r", '', str_replace("\n", '', $filename)) . '"' . $line_term . $line_term; if (strpos($path, '://') === false) { $sending_message .= chunk_split(base64_encode(file_get_contents($path)), 76, $line_term); } else { require_code('files'); $sending_message .= chunk_split(base64_encode(http_download_file($path)), 76, $line_term); } } $sending_message .= $line_term . '--' . $boundary . '--' . $line_term; } // Support for SMTP sockets rather than PHP mail() $error = NULL; if (get_option('smtp_sockets_use') == '1') { $worked = false; $host = get_option('smtp_sockets_host'); $port = intval(get_option('smtp_sockets_port')); $errno = 0; $errstr = ''; foreach ($to_email as $i => $to) { $socket = @fsockopen($host, $port, $errno, $errstr, 30.0); if ($socket !== false) { $rcv = fread($socket, 1024); $base_url = parse_url(get_base_url()); $domain = $base_url['host']; // Login if necessary $username = get_option('smtp_sockets_username'); $password = get_option('smtp_sockets_password'); if ($username != '') { fwrite($socket, 'EHLO ' . $domain . "\r\n"); $rcv = fread($socket, 1024); fwrite($socket, "AUTH LOGIN\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) == '334') { fwrite($socket, base64_encode($username) . "\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) == '235' || strtolower(substr($rcv, 0, 3)) == '334') { fwrite($socket, base64_encode($password) . "\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) == '235') { } else { $error = do_lang('MAIL_ERROR_CONNECT_PASSWORD') . ' (' . str_replace($password, '*', $rcv) . ')'; } } else { $error = do_lang('MAIL_ERROR_CONNECT_USERNAME') . ' (' . $rcv . ')'; } } else { $error = do_lang('MAIL_ERROR_CONNECT_AUTH') . ' (' . $rcv . ')'; } } else { fwrite($socket, 'HELO ' . $domain . "\r\n"); $rcv = fread($socket, 1024); } if (is_null($error)) { $smtp_from_address = get_option('smtp_from_address'); if ($smtp_from_address == '') { $smtp_from_address = $from_email; } fwrite($socket, 'MAIL FROM:<' . $website_email . ">\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) == '250' || strtolower(substr($rcv, 0, 3)) == '251') { $sent_one = false; fwrite($socket, "RCPT TO:<" . $to_email[$i] . ">\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) != '250' && strtolower(substr($rcv, 0, 3)) != '251') { $error = do_lang('MAIL_ERROR_TO') . ' (' . $rcv . ')' . ' ' . $to_email[$i]; } else { $sent_one = true; } if ($sent_one) { fwrite($socket, "DATA\r\n"); $rcv = fread($socket, 1024); if (strtolower(substr($rcv, 0, 3)) == '354') { $attractive_date = strftime('%d %B %Y %H:%M:%S', time()); $_to_name = preg_replace('#@.*$#', '', is_array($to_name) ? $to_name[$i] : $to_name); // preg_replace is because some servers may reject sending names that look like e-mail addresses. ocP tries this from recommend module. if (count($to_email) == 1) { if ($_to_name == '') { fwrite($socket, 'To: ' . $to_email[$i] . "\r\n"); } else { fwrite($socket, 'To: ' . $_to_name . ' <' . $to_email[$i] . '>' . "\r\n"); } } else { fwrite($socket, 'To: ' . $_to_name . "\r\n"); } fwrite($socket, 'Subject: ' . $tightened_subject . "\r\n"); fwrite($socket, 'Date: ' . $attractive_date . "\r\n"); $headers = preg_replace('#^\\.#m', '..', $headers); $sending_message = preg_replace('#^\\.#m', '..', $sending_message); fwrite($socket, $headers . "\r\n"); fwrite($socket, $sending_message); fwrite($socket, "\r\n.\r\n"); $rcv = fread($socket, 1024); fwrite($socket, "QUIT\r\n"); $rcv = fread($socket, 1024); } else { $error = do_lang('MAIL_ERROR_DATA') . ' (' . $rcv . ')'; } } } else { $error = do_lang('MAIL_ERROR_FROM') . ' (' . $rcv . ')'; } if (@fwrite($socket, "RSET\r\n") === false) { @fclose($socket); $socket = NULL; } else { $rcv = fread($socket, 1024); } } if (!is_null($socket)) { fclose($socket); } if (is_null($error)) { $worked = true; } } else { $error = do_lang('MAIL_ERROR_CONNECT', $host, strval($port)); } } } else { $worked = false; foreach ($to_email as $i => $to) { //exit($headers.chr(10).$sending_message); $GLOBALS['SUPPRESS_ERROR_DEATH'] = true; $additional = ''; if (get_option('enveloper_override') == '1') { $additional = '-f ' . $website_email; } $_to_name = preg_replace('#@.*$#', '', is_array($to_name) ? $to_name[$i] : $to_name); // preg_replace is because some servers may reject sending names that look like e-mail addresses. ocP tries this from recommend module. if ($_to_name == '' || strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $to_line = $to; } else { $to_line = '"' . $_to_name . '" <' . $to . '>'; } //if (function_exists('mb_language')) mb_language('en'); Stop overridden mbstring mail function from messing and base64'ing stuff. Actually we don't need this as we make sure to pass through as headers with blank message, bypassing any filtering. if (str_replace(array('on', 'true', 'yes'), array('1', '1', '1'), strtolower(ini_get('safe_mode'))) == '1') { $worked = mail($to_line, $tightened_subject, $sending_message, $headers); } else { $worked = mail($to_line, $tightened_subject, $sending_message, $headers, $additional); } if (!$worked && isset($php_errormsg)) { $error = $php_errormsg; } $GLOBALS['SUPPRESS_ERROR_DEATH'] = false; } } if (!$worked) { $SENDING_MAIL = false; if (get_param_integer('keep_hide_mail_failure', 0) == 0) { require_code('site'); attach_message(!is_null($error) ? make_string_tempcode($error) : do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address'))), 'warn'); } else { return warn_screen(get_page_title('ERROR_OCCURRED'), do_lang_tempcode('MAIL_FAIL', escape_html(get_option('staff_address')))); } } $SENDING_MAIL = false; return NULL; }
/** * Get a well formed URL equivalent to the current URL. * * @param boolean Whether to evaluate the URL (so as we don't return tempcode) * @param boolean Whether to direct to the default page if there was a POST request leading to where we are now (i.e. to avoid missing post fields when we go to this URL) * @param ?array A map of extra parameters for the URL (NULL: none) * @param boolean Whether to also keep POSTed data, in the GET request (useful if either_param is used to get the data instead of post_param - of course the POST data must be of the not--persistant-state-changing variety) * @param boolean Whether to avoid mod_rewrite (sometimes essential so we can assume the standard URL parameter addition scheme in templates) * @return mixed The URL (tempcode or string) */ function get_self_url($evaluate = false, $root_if_posted = false, $extra_params = NULL, $posted_too = false, $avoid_remap = false) { global $SELF_URL_CACHED; $cacheable = $evaluate && !$root_if_posted && $extra_params === NULL && !$posted_too && !$avoid_remap; if ($cacheable && $SELF_URL_CACHED !== NULL) { return $SELF_URL_CACHED; } if (isset($_SERVER['PHP_SELF']) || isset($_ENV['PHP_SELF'])) { if (running_script('execute_temp')) { return get_self_url_easy(); } } if ($extra_params === NULL) { $extra_params = array(); } if ($posted_too) { $post_array = array(); foreach ($_POST as $key => $val) { if (is_array($val)) { continue; } if (get_magic_quotes_gpc()) { $val = stripslashes($val); } $post_array[$key] = $val; } $extra_params = array_merge($post_array, $extra_params); } $page = '_SELF'; if ($root_if_posted && count($_POST) != 0) { $page = ''; } $params = array('page' => $page); foreach ($extra_params as $key => $val) { if ($val === NULL) { unset($params[$key]); } $params[$key] = $val; } $url = build_url($params, '_SELF', NULL, true, $avoid_remap); if ($evaluate) { $ret = $url->evaluate(); if ($cacheable) { $SELF_URL_CACHED = $ret; } return $ret; } return $url; }
/** * Output whatever arguments are given for debugging. If possible it'll output with plain text, but if output has already started it will attach messages. * * @param array Arguments to output * @param boolean Whether to force text output */ function _inspect($args, $force_plain = false) { $plain = headers_sent() || $force_plain || !running_script('index'); if ($plain) { @ini_set('ocproducts.xss_detect', '0'); $GLOBALS['SCREEN_TEMPLATE_CALLED'] = ''; if (!headers_sent()) { header('Content-type: text/plain; charset=' . get_charset()); header('Content-Disposition: inline'); // Override what might have been set } echo 'DEBUGGING. INSPECTING VARIABLES...' . chr(10); } else { header('Content-type: text/html; charset=' . get_charset()); header('Content-Disposition: inline'); // Override what might have been set } foreach ($args as $arg_name => $arg_value) { if (!is_string($arg_name)) { $arg_name = strval($arg_name + 1); } if ($plain) { echo chr(10) . chr(10) . $arg_name . ' is...' . chr(10); if (is_object($arg_value) && is_a($arg_value, 'ocp_tempcode')) { echo 'Tempcode: ' . $arg_value->evaluate() . ' ('; var_dump($arg_value); echo ')'; } else { var_dump($arg_value); } } else { if (is_object($arg_value) && is_a($arg_value, 'ocp_tempcode')) { attach_message($arg_name . ' is...' . chr(10) . 'Tempcode: ' . $arg_value->evaluate()); } else { attach_message($arg_name . ' is...' . chr(10) . var_export($arg_value, true)); } } } if ($plain) { echo chr(10) . chr(10) . '--------------------' . chr(10) . chr(10) . 'STACK TRACE FOLLOWS...' . chr(10) . chr(10); debug_print_backtrace(); exit; } }
/** * Add a member. * * @param SHORT_TEXT The username. * @param SHORT_TEXT The password. * @param SHORT_TEXT The e-mail address. * @param ?array A list of usergroups (NULL: default/current usergroups). * @param ?integer Day of date of birth (NULL: unknown). * @param ?integer Month of date of birth (NULL: unknown). * @param ?integer Year of date of birth (NULL: unknown). * @param array A map of custom field values (field-id=>value). * @param ?ID_TEXT The member timezone (NULL: auto-detect). * @param ?GROUP The member's primary (NULL: default). * @param BINARY Whether the profile has been validated. * @param ?TIME When the member joined (NULL: now). * @param ?TIME When the member last visited (NULL: now). * @param ID_TEXT The member's default theme. * @param ?URLPATH The URL to the member's avatar (blank: none) (NULL: choose one automatically). * @param LONG_TEXT The member's signature (blank: none). * @param BINARY Whether the member is permanently banned. * @param BINARY Whether posts are previewed before they are made. * @param BINARY Whether the member's age may be shown. * @param SHORT_TEXT The member's title (blank: get from primary). * @param URLPATH The URL to the member's photo (blank: none). * @param URLPATH The URL to the member's photo thumbnail (blank: none). * @param BINARY Whether the member sees signatures in posts. * @param ?BINARY Whether the member automatically is enabled for notifications for content they contribute to (NULL: get default from config). * @param ?LANGUAGE_NAME The member's language (NULL: auto detect). * @param BINARY Whether the member allows e-mails via the site. * @param BINARY Whether the member allows e-mails from staff via the site. * @param LONG_TEXT Personal notes of the member. * @param ?IP The member's IP address (NULL: IP address of current user). * @param SHORT_TEXT The code required before the account becomes active (blank: already entered). * @param boolean Whether to check details for correctness. * @param ?ID_TEXT The compatibility scheme that the password operates in (blank: none) (NULL: none [meaning normal ocPortal salted style] or plain, depending on whether passwords are encrypted). * @param SHORT_TEXT The password salt (blank: password compatibility scheme does not use a salt / auto-generate). * @param BINARY Whether the member likes to view zones without menus, when a choice is available. * @param ?TIME The time the member last made a submission (NULL: set to now). * @param ?AUTO_LINK Force an ID (NULL: don't force an ID) * @param BINARY Whether the member username will be highlighted. * @param SHORT_TEXT Usergroups that may PT the member. * @param LONG_TEXT Rules that other members must agree to before they may start a PT with the member. * @return AUTO_LINK The ID of the new member. */ function ocf_make_member($username, $password, $email_address, $secondary_groups, $dob_day, $dob_month, $dob_year, $custom_fields, $timezone = NULL, $primary_group = NULL, $validated = 1, $join_time = NULL, $last_visit_time = NULL, $theme = '', $avatar_url = NULL, $signature = '', $is_perm_banned = 0, $preview_posts = 0, $reveal_age = 1, $title = '', $photo_url = '', $photo_thumb_url = '', $views_signatures = 1, $auto_monitor_contrib_content = NULL, $language = NULL, $allow_emails = 1, $allow_emails_from_staff = 1, $personal_notes = '', $ip_address = NULL, $validated_email_confirm_code = '', $check_correctness = true, $password_compatibility_scheme = NULL, $salt = '', $zone_wide = 1, $last_submit_time = NULL, $id = NULL, $highlighted_name = 0, $pt_allow = '*', $pt_rules_text = '') { if (is_null($auto_monitor_contrib_content)) { $auto_monitor_contrib_content = get_value('no_auto_notifications') === '1' ? 0 : 1; } if (is_null($password_compatibility_scheme)) { if (get_value('no_password_hashing') === '1') { $password_compatibility_scheme = 'plain'; } else { $password_compatibility_scheme = ''; } } if (is_null($language)) { $language = ''; } if (is_null($signature)) { $signature = ''; } if (is_null($title)) { $title = ''; } if (is_null($timezone)) { $timezone = get_site_timezone(); } if (is_null($allow_emails)) { $allow_emails = 1; } if (is_null($allow_emails_from_staff)) { $allow_emails_from_staff = 1; } if (is_null($personal_notes)) { $personal_notes = ''; } if (is_null($avatar_url)) { if ($GLOBALS['IN_MINIKERNEL_VERSION'] == 1 || !addon_installed('ocf_member_avatars')) { $avatar_url = ''; } else { if (get_option('random_avatars') == '1' && !running_script('stress_test_loader')) { require_code('themes2'); $codes = get_all_image_ids_type('ocf_default_avatars/default_set', false, $GLOBALS['FORUM_DB']); shuffle($codes); $results = array(); foreach ($codes as $code) { if (strpos($code, 'ocp_fanatic') !== false) { continue; } $count = $GLOBALS['FORUM_DB']->query_value_null_ok_full('SELECT SUM(m_cache_num_posts) FROM ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_members WHERE ' . db_string_equal_to('m_avatar_url', find_theme_image($code, false, true))); if (is_null($count)) { $count = 0; } $results[$code] = $count; } @asort($results); // @'d as type checker fails for some odd reason $found_avatars = array_keys($results); $avatar_url = find_theme_image(array_shift($found_avatars), true, true); } if (is_null($avatar_url)) { $GLOBALS['SITE_DB']->query_delete('theme_images', array('id' => 'ocf_default_avatars/default', 'path' => '')); // In case failure cached, gets very confusing $avatar_url = find_theme_image('ocf_default_avatars/default', true, true); if (is_null($avatar_url)) { $avatar_url = ''; } } } } if ($check_correctness) { if (!in_array($password_compatibility_scheme, array('ldap', 'httpauth'))) { ocf_check_name_valid($username, NULL, $password_compatibility_scheme == '' ? $password : NULL); } if (!function_exists('has_actual_page_access') || !has_actual_page_access(get_member(), 'admin_ocf_join')) { require_code('type_validation'); if (!is_valid_email_address($email_address) && $email_address != '') { warn_exit(do_lang_tempcode('_INVALID_EMAIL_ADDRESS', escape_html($email_address))); } } } require_code('ocf_members'); require_code('ocf_groups'); if (is_null($last_submit_time)) { $last_submit_time = time(); } if (is_null($join_time)) { $join_time = time(); } if (is_null($last_visit_time)) { $last_visit_time = time(); } if (is_null($primary_group)) { $primary_group = get_first_default_group(); // This is members } if (is_null($secondary_groups)) { $secondary_groups = ocf_get_all_default_groups(false); } foreach ($secondary_groups as $_g_id => $g_id) { if ($g_id == $primary_group) { unset($secondary_groups[$_g_id]); } } if (is_null($ip_address)) { $ip_address = get_ip_address(); } if ($password_compatibility_scheme == '' && get_value('no_password_hashing') === '1') { $password_compatibility_scheme = 'plain'; $salt = ''; } if ($salt == '' && $password_compatibility_scheme == '') { $salt = produce_salt(); $password_salted = md5($salt . md5($password)); } else { $password_salted = $password; } // Supplement custom field values given with defaults, and check constraints $all_fields = list_to_map('id', ocf_get_all_custom_fields_match($secondary_groups)); require_code('fields'); foreach ($all_fields as $field) { $field_id = $field['id']; if (array_key_exists($field_id, $custom_fields)) { if ($check_correctness && $field[array_key_exists('cf_show_on_join_form', $field) ? 'cf_show_on_join_form' : 'cf_required'] == 0 && $field['cf_owner_set'] == 0 && !has_actual_page_access(get_member(), 'admin_ocf_join')) { access_denied('I_ERROR'); } } else { $custom_fields[$field_id] = ''; } } if (!addon_installed('unvalidated')) { $validated = 1; } $map = array('m_username' => $username, 'm_pass_hash_salted' => $password_salted, 'm_pass_salt' => $salt, 'm_theme' => $theme, 'm_avatar_url' => $avatar_url, 'm_validated' => $validated, 'm_validated_email_confirm_code' => $validated_email_confirm_code, 'm_cache_num_posts' => 0, 'm_cache_warnings' => 0, 'm_max_email_attach_size_mb' => 5, 'm_join_time' => $join_time, 'm_timezone_offset' => $timezone, 'm_primary_group' => $primary_group, 'm_last_visit_time' => $last_visit_time, 'm_last_submit_time' => $last_submit_time, 'm_signature' => insert_lang_comcode($signature, 4, $GLOBALS['FORUM_DB']), 'm_is_perm_banned' => $is_perm_banned, 'm_preview_posts' => $preview_posts, 'm_notes' => $personal_notes, 'm_dob_day' => $dob_day, 'm_dob_month' => $dob_month, 'm_dob_year' => $dob_year, 'm_reveal_age' => $reveal_age, 'm_email_address' => $email_address, 'm_title' => $title, 'm_photo_url' => $photo_url, 'm_photo_thumb_url' => $photo_thumb_url, 'm_views_signatures' => $views_signatures, 'm_auto_monitor_contrib_content' => $auto_monitor_contrib_content, 'm_highlighted_name' => $highlighted_name, 'm_pt_allow' => $pt_allow, 'm_pt_rules_text' => insert_lang_comcode($pt_rules_text, 4, $GLOBALS['FORUM_DB']), 'm_language' => $language, 'm_ip_address' => $ip_address, 'm_zone_wide' => $zone_wide, 'm_allow_emails' => $allow_emails, 'm_allow_emails_from_staff' => $allow_emails_from_staff, 'm_password_change_code' => '', 'm_password_compat_scheme' => $password_compatibility_scheme, 'm_on_probation_until' => NULL); if (!is_null($id)) { $map['id'] = $id; } $member_id = $GLOBALS['FORUM_DB']->query_insert('f_members', $map, true); if ($check_correctness) { // If it was an invite/recommendation, award the referrer if (addon_installed('recommend')) { $inviter = $GLOBALS['FORUM_DB']->query_value_null_ok('f_invites', 'i_inviter', array('i_email_address' => $email_address), 'ORDER BY i_time'); if (!is_null($inviter)) { if (addon_installed('points')) { require_code('points2'); require_lang('recommend'); system_gift_transfer(do_lang('RECOMMEND_SITE_TO', $username, get_site_name()), intval(get_option('points_RECOMMEND_SITE')), $inviter); } if (addon_installed('chat')) { require_code('chat2'); buddy_add($inviter, $member_id); buddy_add($member_id, $inviter); } } } } $value = mixed(); // Store custom fields $row = array('mf_member_id' => $member_id); $all_fields_types = collapse_2d_complexity('id', 'cf_type', $all_fields); foreach ($custom_fields as $field_num => $value) { if (!array_key_exists($field_num, $all_fields_types)) { continue; } // Trying to set a field we're not allowed to (doesn't apply to our group) $ob = get_fields_hook($all_fields_types[$field_num]); list(, , $storage_type) = $ob->get_field_value_row_bits($all_fields[$field_num]); if (strpos($storage_type, '_trans') !== false) { $value = insert_lang($value, 3, $GLOBALS['FORUM_DB']); } $row['field_' . strval($field_num)] = $value; } // Set custom field row $all_fields_regardless = $GLOBALS['FORUM_DB']->query_select('f_custom_fields', array('id', 'cf_type')); foreach ($all_fields_regardless as $field) { if (!array_key_exists('field_' . strval($field['id']), $row)) { $ob = get_fields_hook($field['cf_type']); list(, , $storage_type) = $ob->get_field_value_row_bits($field); $value = ''; if (strpos($storage_type, '_trans') !== false) { $value = insert_lang($value, 3, $GLOBALS['FORUM_DB']); } $row['field_' . strval($field['id'])] = $value; } } $GLOBALS['FORUM_DB']->query_insert('f_member_custom_fields', $row); // Any secondary work foreach ($secondary_groups as $g) { if ($g != $primary_group) { $GLOBALS['FORUM_DB']->query_delete('f_group_members', array('gm_member_id' => $member_id, 'gm_group_id' => $g), '', 1); $GLOBALS['FORUM_DB']->query_insert('f_group_members', array('gm_group_id' => $g, 'gm_member_id' => $member_id, 'gm_validated' => 1)); } } if ($check_correctness) { if (function_exists('decache')) { decache('side_stats'); } } return $member_id; }
/** * Look at the user's browser, and decide if they are viewing on a mobile device or not. * * @param ?string The user agent (NULL: get from environment, current user's browser) * @param boolean Whether to always tell the truth (even if the current page does not have mobile support) * @return boolean Whether the user is using a mobile device */ function is_mobile($user_agent = NULL, $truth = false) { $user_agent_given = $user_agent !== NULL; if ($user_agent === NULL) { $user_agent = ocp_srv('HTTP_USER_AGENT'); } global $IS_MOBILE, $IS_MOBILE_TRUTH; if (!$user_agent_given) { if (($truth ? $IS_MOBILE_TRUTH : $IS_MOBILE) !== NULL) { return $truth ? $IS_MOBILE_TRUTH : $IS_MOBILE; } } if (!function_exists('get_option') || get_option('mobile_support') == '0') { $IS_MOBILE = false; $IS_MOBILE_TRUTH = false; return false; } global $SITE_INFO; if ((!isset($SITE_INFO['assume_full_mobile_support']) || $SITE_INFO['assume_full_mobile_support'] == '0') && isset($GLOBALS['FORUM_DRIVER']) && !$truth && running_script('index') && ($theme = $GLOBALS['FORUM_DRIVER']->get_theme()) != 'default') { $ini_path = ($theme == 'default' ? get_file_base() : get_custom_file_base()) . '/themes/' . $theme . '/theme.ini'; if (is_file($ini_path)) { require_code('files'); $details = better_parse_ini_file($ini_path); if (isset($details['mobile_pages']) && $details['mobile_pages'] != '' && preg_match('#(^|,)\\s*' . str_replace('#', '\\#', preg_quote(get_page_name())) . '\\s*(,|$)#', $details['mobile_pages']) == 0) { $IS_MOBILE = false; return false; } } } if (!$user_agent_given) { $val = get_param_integer('keep_mobile', NULL); if ($val !== NULL) { if (isset($GLOBALS['FORUM_DRIVER'])) { $IS_MOBILE = $val == 1; } $IS_MOBILE_TRUTH = $IS_MOBILE; return $IS_MOBILE; } } // The set of browsers $browsers = array('WML', 'WAP', 'Wap', 'MIDP', 'Mobile', 'Smartphone', 'WebTV', 'Minimo', 'Fennec', 'Mobile Safari', 'Android', 'lynx', 'Links', 'iPhone', 'iPod', 'Opera Mobi', 'Opera Mini', 'BlackBerry', 'Windows Phone', 'Windows CE', 'Symbian', 'nook browser', 'Blazer', 'PalmOS', 'webOS', 'SonyEricsson', 'Nintendo', 'PlayStation Portable', 'UP.Browser', 'UP.Link', 'NetFront', 'Teleca', 'UCWEB', 'DDIPOCKET', 'SEMC-Browser', 'DoCoMo', 'Xda', 'ReqwirelessWeb', 'AvantGo'); $exceptions = array('iPad'); if ((!isset($SITE_INFO['no_extra_mobiles']) || $SITE_INFO['no_extra_mobiles'] == '0') && is_file(get_file_base() . '/text_custom/pdas.txt')) { require_code('files'); $pdas = better_parse_ini_file(get_file_base() . '/text_custom/pdas.txt'); foreach ($pdas as $key => $val) { if ($val == 1) { $browsers[] = $key; } else { $exceptions[] = $key; } } } // The test $result = preg_match('/(' . implode('|', $browsers) . ')/i', $user_agent) != 0 && preg_match('/(' . implode('|', $exceptions) . ')/i', $user_agent) == 0; if (!$user_agent_given) { if (isset($GLOBALS['FORUM_DRIVER'])) { $IS_MOBILE = $result; $IS_MOBILE_TRUTH = $IS_MOBILE; } } return $result; }
/** * This function is a very basic query executor. It shouldn't usually be used by you, as there are abstracted versions available. * * @param string The complete SQL query * @param array A DB connection * @param ?integer The maximum number of rows to affect (NULL: no limit) * @param ?integer The start row to affect (NULL: no specification) * @param boolean Whether to output an error on failure * @param boolean Whether to get the autoincrement ID created for an insert query * @return ?mixed The results (NULL: no results), or the insert ID */ function db_query($query, $db, $max = NULL, $start = NULL, $fail_ok = false, $get_insert_id = false) { if (substr($query, 0, 7) == 'SELECT') { if (!is_null($max) && !is_null($start)) { $query .= ' LIMIT ' . strval(intval($start)) . ',' . strval(intval($max)); } elseif (!is_null($max)) { $query .= ' LIMIT ' . strval(intval($max)); } elseif (!is_null($start)) { $query .= ' LIMIT ' . strval(intval($start)) . ',30000000'; } } $results = @sqlite_query($db, $query); if (($results === false || strtoupper(substr($query, 0, 7)) == 'SELECT ' && $results === true) && !$fail_ok) { $err = sqlite_last_error($db); if (function_exists('ocp_mark_as_escaped')) { ocp_mark_as_escaped($err); } if (!running_script('upgrader') && get_page_name() != 'admin_import') { if (!function_exists('do_lang') || is_null(do_lang('QUERY_FAILED', NULL, NULL, NULL, NULL, false))) { fatal_exit(htmlentities('Query failed: ' . $query . ' : ' . $err)); } fatal_exit(do_lang_tempcode('QUERY_FAILED', escape_html($query), $err)); } else { echo htmlentities('Database query failed: ' . $query . ' [') . $err . htmlentities(']' . '<br />' . chr(10)); return NULL; } } if (strtoupper(substr($query, 0, 7)) == 'SELECT ' && $results !== false && $results !== true) { return $this->db_get_query_rows($results); } if ($get_insert_id) { if (strtoupper(substr($query, 0, 7)) == 'UPDATE ') { return NULL; } return sqlite_last_insert_rowid($db); } return NULL; }
/** * This function is a very basic query executor. It shouldn't usually be used by you, as there are abstracted versions available. * * @param string The complete SQL query * @param array A DB connection * @param ?integer The maximum number of rows to affect (NULL: no limit) * @param ?integer The start row to affect (NULL: no specification) * @param boolean Whether to output an error on failure * @param boolean Whether to get the autoincrement ID created for an insert query * @return ?mixed The results (NULL: no results), or the insert ID */ function db_query($query, $db_parts, $max = NULL, $start = NULL, $fail_ok = false, $get_insert_id = false) { list($db, $db_name) = $db_parts; if (isset($query[500000])) { $test_result = $this->db_query('SHOW VARIABLES LIKE \'max_allowed_packet\'', $db_parts, NULL, NULL, true); if (!is_array($test_result)) { return NULL; } if (intval($test_result[0]['Value']) < intval(strlen($query) * 1.2)) { /*@mysql_query('SET session max_allowed_packet='.strval(intval(strlen($query)*1.3)),$db); Does not work well, as MySQL server has gone away error will likely just happen instead */ if ($get_insert_id) { fatal_exit(do_lang_tempcode('QUERY_FAILED_TOO_BIG', escape_html($query))); } return NULL; } } global $LAST_SELECT_DB; if ($LAST_SELECT_DB[1] != $db_name) { mysqli_select_db($db, $db_name); $LAST_SELECT_DB = array($db, $db_name); } if ($max !== NULL && $start !== NULL) { $query .= ' LIMIT ' . strval($start) . ',' . strval($max); } elseif ($max !== NULL) { $query .= ' LIMIT ' . strval($max); } elseif ($start !== NULL) { $query .= ' LIMIT ' . strval($start) . ',30000000'; } $results = @mysqli_query($db, $query); if ($results === false && (!$fail_ok || strpos(mysqli_error($db), 'is marked as crashed and should be repaired') !== false)) { $err = mysqli_error($db); if (function_exists('mysqli_ping') && $err == 'MySQL server has gone away' && !isset($GLOBALS['REDONE_ONCE'])) { $GLOBALS['REDONE_ONCE'] = true; mysqli_ping($db); $ret = $this->db_query($query, $db_parts, $max, $start, $fail_ok, $get_insert_id); unset($GLOBALS['REDONE_ONCE']); return $ret; } if (function_exists('ocp_mark_as_escaped')) { ocp_mark_as_escaped($err); } if (!running_script('upgrader') && get_page_name() != 'admin_import') { if (!function_exists('do_lang') || is_null(do_lang('QUERY_FAILED', NULL, NULL, NULL, NULL, false))) { fatal_exit(htmlentities('Query failed: ' . $query . ' : ' . $err)); } fatal_exit(do_lang_tempcode('QUERY_FAILED', escape_html($query), $err)); } else { echo htmlentities('Database query failed: ' . $query . ' [') . $err . htmlentities(']' . '<br />' . chr(10)); return NULL; } } if ($results !== true && (strtoupper(substr($query, 0, 7)) == 'SELECT ' || strtoupper(substr($query, 0, 8)) == '(SELECT ' || strtoupper(substr($query, 0, 8)) == 'EXPLAIN ' || strtoupper(substr($query, 0, 9)) == 'DESCRIBE ' || strtoupper(substr($query, 0, 5)) == 'SHOW ') && $results !== false) { return $this->db_get_query_rows($results); } if ($get_insert_id) { if (strtoupper(substr($query, 0, 7)) == 'UPDATE ') { return mysqli_affected_rows($db); } $ins = mysqli_insert_id($db); if ($ins === 0) { $table = substr($query, 12, strpos($query, ' ', 12) - 12); $rows = $this->db_query('SELECT MAX(id) AS x FROM ' . $table, $db_parts, 1, 0, false, false); return $rows[0]['x']; } return $ins; } return NULL; }
/** * Handle flood control for members. * * @param MEMBER The member ID that just got detected */ function ocf_flood_control($id) { global $NON_PAGE_SCRIPT; if ($NON_PAGE_SCRIPT == 1) { return; } global $FLOOD_CONTROL_ONCE; if ($FLOOD_CONTROL_ONCE) { return; } $FLOOD_CONTROL_ONCE = true; if (get_page_name() == 'join') { return; } if (!running_script('index') && !running_script('iframe')) { return; } require_code('ocf_groups'); // Set last visit time session cookie if it doesn't exist if (!array_key_exists('last_visit', $_COOKIE) && $GLOBALS['FORUM_DRIVER']->get_guest_id() != $id) { require_code('users_active_actions'); $lvt = $this->get_member_row_field($id, 'm_last_visit_time'); ocp_setcookie('last_visit', is_null($lvt) ? strval(time()) : strval($lvt), true); $new_visit = true; } else { $new_visit = false; } // Do some flood control $submitting = count($_POST) > 0 && get_param('type', NULL) !== 'ed' && get_param('type', NULL) !== 'ec' && !running_script('preview'); $restrict = $submitting ? 'flood_control_submit_secs' : 'flood_control_access_secs'; $restrict_setting = $submitting ? 'm_last_submit_time' : 'm_last_visit_time'; $restrict_answer = ocf_get_best_group_property($this->get_members_groups($id), $restrict); if (!$submitting && array_key_exists('redirect', $_GET)) { $restrict_answer = 0; } if ($restrict_answer < 0) { $restrict_answer = 0; } $last = $this->get_member_row_field($id, $restrict_setting); if ($last > time()) { $last = time() - $restrict_answer; } // Weird clock problem $wait_time = $restrict_answer - time() + $last; if ($wait_time > 0 && addon_installed('stats')) { require_code('site'); log_stats('/flood', 0); $time_threshold = 30; $count_threshold = 50; $query = 'SELECT COUNT(*) FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'stats WHERE date_and_time>' . strval(time() - $time_threshold) . ' AND date_and_time<' . strval(time()) . ' AND ' . db_string_equal_to('ip', get_ip_address()); $count = $GLOBALS['SITE_DB']->query_value_null_ok_full($query); if ($count >= $count_threshold && addon_installed('securitylogging')) { $ip = get_ip_address(); require_code('failure'); add_ip_ban($ip); require_code('notifications'); dispatch_notification('auto_ban', NULL, do_lang('AUTO_BAN_SUBJECT', $ip, NULL, NULL, get_site_default_lang()), do_lang('AUTO_BAN_DOS_MESSAGE', $ip, integer_format($count_threshold), integer_format($time_threshold), get_site_default_lang()), NULL, A_FROM_SYSTEM_PRIVILEGED); } if (!function_exists('require_lang')) { require_code('lang'); } if (!function_exists('do_lang_tempcode')) { require_code('tempcode'); } require_lang('ocf'); warn_exit(do_lang_tempcode('FLOOD_CONTROL_RESTRICT', integer_format($wait_time))); } $extra = $submitting ? array('m_last_submit_time' => time()) : array(); $dif = time() - $this->get_member_row_field($id, 'm_last_visit_time'); if ($dif < 0) { $dif = 0; } // can happen if system clock changes if (is_guest($id)) { if (get_value('session_prudence') !== '1') { global $SESSION_CACHE; $num_guests = 0; foreach ($SESSION_CACHE as $c) { if (!array_key_exists('the_user', $c)) { continue; } // Workaround to HipHop PHP weird bug if ($c['last_activity'] > time() - 60 * 4 && is_guest($c['the_user'])) { $num_guests++; } } $dif *= $num_guests; } else { $restrict_answer = 0; } } if ($submitting || count($_POST) == 0 && $dif > $wait_time) { if ($restrict_answer != 0 || $dif > 180 || $new_visit) { $old_ip = $this->get_member_row_field($id, 'm_ip_address'); $change_map = array('m_last_visit_time' => time()); if (get_ip_address() != $old_ip) { $change_map['m_ip_address'] = get_ip_address(); } if (get_db_type() != 'xml') { $this->connection->query_update('f_members', $change_map + $extra, array('id' => $id), '', 1, NULL, false, true); } } } }
/** * This is it - the start of rendering of a website page. * Take in all inputs, sends them to the correct functions to process, gathers up all the outputs, sticks them together and echoes them. */ function do_site() { // More SEO redirection (monikers) // Does this URL arrangement support monikers? $url_id = get_param('id', NULL, true); if ($url_id !== NULL && url_monikers_enabled()) { $type = get_param('type', 'misc'); $looking_for = '_SEARCH:' . get_page_name() . ':' . $type . ':_WILD'; $hooks = find_all_hooks('systems', 'content_meta_aware'); $ob_info = NULL; foreach (array_keys($hooks) as $hook) { require_code('hooks/systems/content_meta_aware/' . filter_naughty($hook)); $ob = object_factory('Hook_content_meta_aware_' . $hook, true); if ($ob === NULL) { continue; } $ob_info = $ob->info(); $ob_info['view_pagelink_pattern'] = preg_replace('#:[^:]*$#', ':_WILD', $ob_info['view_pagelink_pattern']); if ($ob_info['view_pagelink_pattern'] == $looking_for && $ob_info['support_url_monikers']) { if (is_numeric($url_id)) { $correct_moniker = find_id_moniker(array('page' => get_page_name(), 'type' => get_param('type', 'misc'), 'id' => $url_id)); if ($correct_moniker !== NULL && $correct_moniker != $url_id && count($_POST) == 0) { header('HTTP/1.0 301 Moved Permanently'); $_new_url = build_url(array('page' => '_SELF', 'id' => $correct_moniker), '_SELF', NULL, true); $new_url = $_new_url->evaluate(); header('Location: ' . $new_url); exit; } } else { // See if it is deprecated if (strpos(get_db_type(), 'mysql') !== false) { $monikers = $GLOBALS['SITE_DB']->query_select('url_id_monikers USE INDEX (uim_moniker)', array('m_resource_id', 'm_deprecated'), array('m_resource_page' => get_page_name(), 'm_resource_type' => get_param('type', 'misc'), 'm_moniker' => $url_id)); } else { $monikers = $GLOBALS['SITE_DB']->query_select('url_id_monikers', array('m_resource_id', 'm_deprecated'), array('m_resource_page' => get_page_name(), 'm_resource_type' => get_param('type', 'misc'), 'm_moniker' => $url_id)); } if (!array_key_exists(0, $monikers)) { warn_exit(do_lang_tempcode('MISSING_RESOURCE')); } $deprecated = $monikers[0]['m_deprecated'] == 1; if ($deprecated && count($_POST) == 0) { $correct_moniker = find_id_moniker(array('page' => get_page_name(), 'type' => get_param('type', 'misc'), 'id' => $monikers[0]['m_resource_id'])); header('HTTP/1.0 301 Moved Permanently'); $_new_url = build_url(array('page' => '_SELF', 'id' => $correct_moniker), '_SELF', NULL, true); $new_url = $_new_url->evaluate(); header('Location: ' . $new_url); exit; } else { $_GET['id'] = $monikers[0]['m_resource_id']; // We need to know the ID number rather than the moniker } } break; } } } // Any messages to output? if (get_param_integer('redirected', 0) == 1) { $messages = $GLOBALS['SITE_DB']->query_select('messages_to_render', array('r_message', 'r_type'), array('r_session_id' => get_session_id()), 'ORDER BY r_time DESC'); foreach ($messages as $message) { if ($GLOBALS['XSS_DETECT']) { ocp_mark_as_escaped($message['r_message']); } attach_message(protect_from_escaping($message['r_message']), $message['r_type']); } if (count($messages) != 0) { $GLOBALS['SITE_DB']->query('DELETE FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'messages_to_render WHERE r_session_id=' . strval((int) get_session_id()) . ' OR r_time<' . strval(time() - 60 * 60)); } } if (in_safe_mode()) { $disable_safe_mode_url = get_self_url(true, true, array('keep_safe_mode' => NULL)); attach_message(do_lang_tempcode('CURRENTLY_HAS_KEEP_SAFE_MODE', escape_html($disable_safe_mode_url)), 'notice'); } if (get_param_integer('keep_fatalistic', 0) == 1) { $disable_fatalistic_url = get_self_url(true, true, array('keep_fatalistic' => NULL)); attach_message(do_lang_tempcode('CURRENTLY_HAS_KEEP_FATALISTIC', escape_html($disable_fatalistic_url)), 'notice'); } $special_page_type = get_param('special_page_type', 'view'); global $ZONE; $keep_markers = get_param_integer('keep_markers', 0); $show_edit_links = get_param_integer('show_edit_links', 0); global $KEEP_MARKERS, $SHOW_EDIT_LINKS; $KEEP_MARKERS = $keep_markers == 1 || $special_page_type == 'show_markers'; if ($KEEP_MARKERS && !headers_sent()) { header('Content-type: text/html; charset=' . get_charset()); } $SHOW_EDIT_LINKS = $show_edit_links == 1 || $special_page_type == 'show_edit_links'; $out_evaluated = NULL; if ($special_page_type != 'view' && $special_page_type != 'show_markers') { require_code('view_modes'); initialise_special_page_types($special_page_type); } // Set up Xdebug profiling if ($special_page_type == 'profile') { if (function_exists('xdebug_start_profiling')) { xdebug_start_profiling(); } // xdebug 1 style if (ini_get('xdebug.profiler_enable') != '1') { attach_message(escape_html('Profiling must be enabled in php.ini'), 'warn'); } // xdebug 2 style if (!is_writable_wrap(ini_get('xdebug.profiler_output_dir'))) { attach_message(escape_html('xdebug.profiler_output_dir needs setting to a writable directory'), 'warn'); } } // Allow the site to be closed $site_closed = get_option('site_closed'); if ($site_closed == '1' && !has_specific_permission(get_member(), 'access_closed_site') && !$GLOBALS['IS_ACTUALLY_ADMIN']) { require_code('site2'); closed_site(); } // Work out which page we're viewing global $PAGE; $PAGE = get_page_name(); $doing_special_page_type = $special_page_type != 'view' && $special_page_type != 'show_markers' && $special_page_type != 'show_edit_links' && $special_page_type != 'memory' && (has_specific_permission(get_member(), 'view_profiling_modes') || $GLOBALS['IS_ACTUALLY_ADMIN']); // Load up our frames into strings. Note that the header and the footer are fixed already. $middle = request_page($PAGE, true); global $CYCLES; $CYCLES = array(); // Here we reset some Tempcode environmental stuff, because template compilation or preprocessing may have dirtied things if ($middle === NULL || $middle->is_definitely_empty()) { $GLOBALS['HTTP_STATUS_CODE'] = '404'; if (!headers_sent()) { if (!browser_matches('ie') && strpos(ocp_srv('SERVER_SOFTWARE'), 'IIS') === false) { header('HTTP/1.0 404 Not Found'); } } $title = get_page_title('ERROR_OCCURRED'); $text = do_lang_tempcode('NO_PAGE_OUTPUT'); $middle = warn_screen($title, $text, false); } // Extra stuff we can tag on (like messages) $additional = new ocp_tempcode(); $site_closed = get_option('site_closed'); // May have been JUST changed in page load - think Setup Wizard if ($site_closed == '1' && $PAGE != 'login' && $PAGE != 'join' && get_param_integer('wide_high', 0) == 0) { $additional->attach(do_template('ADDITIONAL', array('_GUID' => '03a41a91606b3ad05330e7d6f3e741c1', 'TYPE' => 'notice', 'MESSAGE' => do_lang_tempcode(has_specific_permission(get_member(), 'access_closed_site') ? 'SITE_SPECIAL_ACCESS' : 'SITE_SPECIAL_ACCESS_SU')))); } if ($GLOBALS['IS_ACTUALLY_ADMIN']) { $unsu_link = get_self_url(true, true, array('keep_su' => NULL)); $su_username = $GLOBALS['FORUM_DRIVER']->get_username(get_member()); $additional->attach(do_template('ADDITIONAL', array('_GUID' => '13a41a91606b3ad05330e7d6f3e741c1', 'TYPE' => 'notice', 'MESSAGE' => do_lang_tempcode('USING_SU', escape_html($unsu_link), escape_html($su_username))))); } $out = new ocp_tempcode(); // This is important - it makes sure the tempcode tree appears nicely $middle->handle_symbol_preprocessing(); // Due to the '->evaluate()' below, plus so that some symbol preprocessing can be passed into header $out->attach(do_header()); if (function_exists('memory_get_usage') && get_param('special_page_type', '') == 'memory') { if (function_exists('memory_get_peak_usage')) { $memory_usage = memory_get_peak_usage(); } else { $memory_usage = memory_get_usage(); } $additional->attach(do_template('ADDITIONAL', array('_GUID' => 'd605c0d111742a8cd2d4ef270a1e5fe1', 'TYPE' => 'inform', 'MESSAGE' => do_lang_tempcode('MEMORY_USAGE', float_format(round(floatval($memory_usage) / 1024.0 / 1024.0, 2)))))); } // Whack it into our global template global $ATTACHED_MESSAGES; $global_template = 'GLOBAL'; if (get_option('show_docs') == '0') { $GLOBALS['HELPER_PANEL_TUTORIAL'] = ''; } $helper_panel_pic = $GLOBALS['HELPER_PANEL_PIC']; if ($helper_panel_pic != '') { if (find_theme_image($helper_panel_pic, true) == '') { $helper_panel_pic = ''; } } $global = do_template($global_template, array('HELPER_PANEL_TUTORIAL' => $GLOBALS['HELPER_PANEL_TUTORIAL'], 'HELPER_PANEL_HTML' => $GLOBALS['HELPER_PANEL_HTML'], 'HELPER_PANEL_TEXT' => $GLOBALS['HELPER_PANEL_TEXT'], 'HELPER_PANEL_PIC' => $helper_panel_pic, 'MIDDLE' => $doing_special_page_type ? $middle : $middle->evaluate(), 'MESSAGE_TOP' => $ATTACHED_MESSAGES, 'MESSAGE' => $additional, 'BREADCRUMBS' => breadcrumbs())); unset($middle); $out->attach($global); $out->attach(do_footer()); $out->handle_symbol_preprocessing(); if (get_value('xhtml_strict') === '1') { $out = make_xhtml_strict($out); } // Validation $novalidate = get_param_integer('keep_novalidate', get_param_integer('novalidate', 0)); $show_edit_links = get_param_integer('show_edit_links', 0); if ((in_array(ocp_srv('HTTP_HOST'), array('localhost', 'test.ocportal.com')) || $GLOBALS['FORUM_DRIVER']->is_staff(get_member())) && ($special_page_type == 'code' || $novalidate == 0 && get_option('validation') == '1') && $GLOBALS['REFRESH_URL'][0] == '' && $show_edit_links == 0) { require_code('view_modes'); $out_evaluated = $out->evaluate(NULL, false); do_xhtml_validation($out_evaluated, $special_page_type == 'code' && get_param_integer('preview_mode', NULL) === NULL, get_param_integer('preview_mode', 0)); } // Cacheing for spiders if (running_script('index') && count($_POST) == 0 && isset($GLOBALS['SITE_INFO']['fast_spider_cache']) && $GLOBALS['SITE_INFO']['fast_spider_cache'] == '1' && is_guest()) { $bot_type = get_bot_type(); if (($bot_type !== NULL || isset($GLOBALS['SITE_INFO']['any_guest_cached_too']) && $GLOBALS['SITE_INFO']['any_guest_cached_too'] == '1') && can_fast_spider_cache()) { $fast_cache_path = get_custom_file_base() . '/persistant_cache/' . md5(serialize(get_self_url_easy())); if ($bot_type === NULL) { $fast_cache_path .= '__non-bot'; } if (!array_key_exists('js_on', $_COOKIE)) { $fast_cache_path .= '__no-js'; } if (is_mobile()) { $fast_cache_path .= '_mobile'; } $fast_cache_path .= '.gcd'; if (!is_dir(get_custom_file_base() . '/persistant_cache/')) { if (@mkdir(get_custom_file_base() . '/persistant_cache/', 0777)) { fix_permissions(get_custom_file_base() . '/persistant_cache/', 0777); sync_file(get_custom_file_base() . '/persistant_cache/'); } else { intelligent_write_error($fast_cache_path); } } $out_evaluated = $out->evaluate(NULL, false); $myfile = @fopen($fast_cache_path, 'wb') or intelligent_write_error($fast_cache_path); if (function_exists('gzencode')) { fwrite($myfile, gzencode($out_evaluated, 9)); } else { fwrite($myfile, $out_evaluated); } fclose($myfile); fix_permissions($fast_cache_path); sync_file($fast_cache_path); } } if ($doing_special_page_type) { special_page_types($special_page_type, $out, $out_evaluated); } // We calculated the time before outputting so that latency and bandwidth do not adversely affect the result global $PAGE_START_TIME, $PAGE_STRING; $page_generation_time = microtime_diff($PAGE_START_TIME, microtime(false)); if (!$GLOBALS['QUICK_REDIRECT']) { if ($out_evaluated !== NULL) { echo $out_evaluated; } else { $GLOBALS['FINISHING_OUTPUT'] = true; $out->evaluate_echo(); } } // Finally, stats if ($PAGE_STRING !== NULL) { log_stats($PAGE_STRING, intval($page_generation_time)); } // When someone hits the Admin Zone front page. if ($ZONE['zone_name'] == 'adminzone' && get_page_name() == 'start') { // Security feature admins can turn on require_code('notifications'); $current_username = $GLOBALS['FORUM_DRIVER']->get_username(get_member()); $subject = do_lang('AFA_NOTIFICATION_MAIL_SUBJECT', $current_username, get_site_name(), get_ip_address()); $mail = do_lang('AFA_NOTIFICATION_MAIL', comcode_escape(get_site_name()), comcode_escape($current_username), comcode_escape(get_ip_address())); dispatch_notification('adminzone_frontpage_accessed', NULL, $subject, $mail); // Track very basic details of what sites use ocPortal. You can remove if you like. if (preg_match('#^localhost[\\.\\:$]?#', ocp_srv('HTTP_HOST')) == 0) { global $EXPIRE, $KEY; $timeout_before = @ini_get('default_socket_timeout'); @ini_set('default_socket_timeout', '3'); http_download_file('http://ocportal.com/user.php?url=' . urlencode(get_base_url()) . '&name=' . urlencode(get_site_name()) . '®istered=2&key=' . ($KEY === NULL ? '' : strval($KEY)) . '&expire=' . ($EXPIRE === NULL ? '' : strval($EXPIRE)) . '&version=' . urlencode(ocp_version_full()), NULL, false); @ini_set('default_socket_timeout', $timeout_before); } } // Little disk space check $last_space_check = get_value('last_space_check'); if ($last_space_check === NULL || intval($last_space_check) < time() - 60 * 60 * 3) { set_value('last_space_check', strval(time())); $low_space_check = intval(get_option('low_space_check')) * 1024 * 1024; $disk_space = @disk_free_space(get_file_base()); if (is_integer($disk_space) && $disk_space < $low_space_check) { require_code('notifications'); $subject = do_lang('LOW_DISK_SPACE_SUBJECT', NULL, NULL, NULL, get_site_default_lang()); $message = do_lang('LOW_DISK_SPACE_MAIL', strval(intval(round($disk_space / 1024 / 1024))), NULL, NULL, get_site_default_lang()); dispatch_notification('low_disk_space', NULL, $subject, $message, NULL, A_FROM_SYSTEM_PRIVILEGED); } } //exit(); }
/** * Deletes a file (NOT a directory) on the open AFM connection. * * @param PATH The path to the file we are deleting. */ function afm_delete_file($basic_path) { $path = _rescope_path($basic_path); $conn = _ftp_info(); if ($conn !== false) { $success = @ftp_delete($conn, $path); if (!$success) { if (running_script('upgrader')) { echo @strval($php_errormsg); return; } warn_exit(protect_from_escaping(@strval($php_errormsg))); } clearstatcache(); sync_file(get_custom_file_base() . '/' . $basic_path); } else { if (!file_exists($path)) { return; } @unlink($path) or intelligent_write_error($path); sync_file($path); } }
/** * Add comments to the specified resource. * * @param boolean Whether this resource allows comments (if not, this function does nothing - but it's nice to move out this common logic into the shared function) * @param ID_TEXT The type (download, etc) that this commenting is for * @param ID_TEXT The ID of the type that this commenting is for * @param mixed The URL to where the commenting will pass back to (to put into the comment topic header) (URLPATH or Tempcode) * @param ?string The title to where the commenting will pass back to (to put into the comment topic header) (NULL: don't know, but not first post so not important) * @param ?string The name of the forum to use (NULL: default comment forum) * @param boolean Whether to not require a captcha * @param ?BINARY Whether the post is validated (NULL: unknown, find whether it needs to be marked unvalidated initially). This only works with the OCF driver (hence is the last parameter). * @param boolean Whether to force allowance * @param boolean Whether to skip a success message * @param boolean Whether posts made should not be shared * @return boolean Whether a hidden post has been made */ function actualise_post_comment($allow_comments, $content_type, $content_id, $content_url, $content_title, $forum = NULL, $avoid_captcha = false, $validated = NULL, $explicit_allow = false, $no_success_message = false, $private = false) { if (!$explicit_allow) { if (get_option('is_on_comments') == '0' || !$allow_comments) { return false; } if (!has_specific_permission(get_member(), 'comment', get_page_name())) { return false; } } if (running_script('preview')) { return false; } $forum_tie = get_option('is_on_strong_forum_tie') == '1'; if (addon_installed('captcha')) { if (array_key_exists('post', $_POST) && $_POST['post'] != '' && !$avoid_captcha) { require_code('captcha'); enforce_captcha(); } } $post_title = post_param('title', NULL); if (is_null($post_title) && !$forum_tie) { return false; } $post = post_param('post', NULL); if ($post == do_lang('POST_WARNING')) { $post = ''; } if ($post == do_lang('THREADED_REPLY_NOTICE', do_lang('POST_WARNING'))) { $post = ''; } if ($post == '' && $post_title !== '') { $post = $post_title; $post_title = ''; } if ($post === '') { warn_exit(do_lang_tempcode('NO_PARAMETER_SENT', 'post')); } if (is_null($post)) { $post = ''; } $email = trim(post_param('email', '')); if ($email != '') { $body = '> ' . str_replace(chr(10), chr(10) . '> ', $post); if (substr($body, -2) == '> ') { $body = substr($body, 0, strlen($body) - 2); } if (get_page_name() != 'tickets') { $post .= '[staff_note]'; } $post .= "\n\n" . '[email subject="Re: ' . comcode_escape($post_title) . ' [' . get_site_name() . ']" body="' . comcode_escape($body) . '"]' . $email . '[/email]' . "\n\n"; if (get_page_name() != 'tickets') { $post .= '[/staff_note]'; } } $content_title = strip_comcode($content_title); if (is_null($forum)) { $forum = get_option('comments_forum_name'); } $content_url_flat = is_object($content_url) ? $content_url->evaluate() : $content_url; $_parent_id = post_param('parent_id', ''); $parent_id = $_parent_id == '' ? NULL : intval($_parent_id); $poster_name_if_guest = post_param('poster_name_if_guest', ''); list($topic_id, $is_hidden) = $GLOBALS['FORUM_DRIVER']->make_post_forum_topic($forum, $content_type . '_' . $content_id, get_member(), $post_title, $post, $content_title, do_lang('COMMENT'), $content_url_flat, NULL, NULL, $validated, $explicit_allow ? 1 : NULL, $explicit_allow, $poster_name_if_guest, $parent_id, false, !$private && $post != '' ? 'comment_posted' : NULL, !$private && $post != '' ? $content_type . '_' . $content_id : NULL); if (!is_null($topic_id)) { if (!is_integer($forum)) { $forum_id = $GLOBALS['FORUM_DRIVER']->forum_id_from_name($forum); } else { $forum_id = (int) $forum; } if (get_forum_type() == 'ocf' && !is_null($GLOBALS['LAST_POST_ID'])) { $extra_review_ratings = array(); global $REVIEWS_STRUCTURE; if (array_key_exists($content_type, $REVIEWS_STRUCTURE)) { $reviews_rating_criteria = $REVIEWS_STRUCTURE[$content_type]; } else { $reviews_rating_criteria[] = ''; } foreach ($reviews_rating_criteria as $rating_type) { // Has there actually been any rating? $rating = post_param_integer('review_rating__' . fix_id($rating_type), NULL); if (!is_null($rating)) { if ($rating > 10 || $rating < 1) { log_hack_attack_and_exit('VOTE_CHEAT'); } $GLOBALS['SITE_DB']->query_insert('review_supplement', array('r_topic_id' => $GLOBALS['LAST_TOPIC_ID'], 'r_post_id' => $GLOBALS['LAST_POST_ID'], 'r_rating_type' => $rating_type, 'r_rating_for_type' => $content_type, 'r_rating_for_id' => $content_id, 'r_rating' => $rating)); } } } } if (!$private && $post != '') { list(, $submitter, , $safe_content_url, $cma_info) = get_details_behind_feedback_code($content_type, $content_id); $content_type_title = $content_type; if (!is_null($cma_info) && isset($cma_info['content_type_label'])) { $content_type_title = do_lang($cma_info['content_type_label']); } // Notification require_code('notifications'); $username = $GLOBALS['FORUM_DRIVER']->get_username(get_member()); $subject = do_lang('NEW_COMMENT_SUBJECT', get_site_name(), $content_title == '' ? ocp_mb_strtolower($content_type_title) : $content_title, array($post_title, $username), get_site_default_lang()); $username = $GLOBALS['FORUM_DRIVER']->get_username(get_member()); $message_raw = do_lang('NEW_COMMENT_BODY', comcode_escape(get_site_name()), comcode_escape($content_title == '' ? ocp_mb_strtolower($content_type_title) : $content_title), array($post_title == '' ? do_lang('NO_SUBJECT') : $post_title, post_param('post'), comcode_escape($content_url_flat), comcode_escape($username)), get_site_default_lang()); dispatch_notification('comment_posted', $content_type . '_' . $content_id, $subject, $message_raw); // Is the user gonna automatically enable notifications for this? if (get_forum_type() == 'ocf') { $auto_monitor_contrib_content = $GLOBALS['OCF_DRIVER']->get_member_row_field(get_member(), 'm_auto_monitor_contrib_content'); if ($auto_monitor_contrib_content == 1) { enable_notifications('comment_posted', $content_type . '_' . $content_id); } } // Activity $real_content_type = convert_ocportal_type_codes('feedback_type_code', $content_type, 'cma_hook'); if (may_view_content_behind_feedback_code($GLOBALS['FORUM_DRIVER']->get_guest_id(), $real_content_type, $content_id)) { if (is_null($submitter)) { $submitter = $GLOBALS['FORUM_DRIVER']->get_guest_id(); } $activity_type = is_null($submitter) || is_guest($submitter) ? '_ADDED_COMMENT_ON' : 'ADDED_COMMENT_ON'; if ($content_title == '') { syndicate_described_activity($activity_type . '_UNTITLED', ocp_mb_strtolower($content_type_title), $content_type_title, '', url_to_pagelink(is_object($safe_content_url) ? $safe_content_url->evaluate() : $safe_content_url), '', '', convert_ocportal_type_codes('feedback_type_code', $content_type, 'addon_name'), 1, NULL, false, $submitter); } else { syndicate_described_activity($activity_type, $content_title, ocp_mb_strtolower($content_type_title), $content_type_title, url_to_pagelink(is_object($safe_content_url) ? $safe_content_url->evaluate() : $safe_content_url), '', '', convert_ocportal_type_codes('feedback_type_code', $content_type, 'addon_name'), 1, NULL, false, $submitter); } } } if ($post != '' && $forum_tie && !$no_success_message) { require_code('site2'); assign_refresh($GLOBALS['FORUM_DRIVER']->topic_url($GLOBALS['FORUM_DRIVER']->find_topic_id_for_topic_identifier($forum, $content_type . '_' . $content_id), $forum), 0.0); } if ($post != '' && !$no_success_message) { attach_message(do_lang_tempcode('SUCCESS')); } return $is_hidden; }
/** * Get the current session ID. * * @return integer The current session ID */ function get_session_id() { if (!isset($_COOKIE['ocp_session']) || $GLOBALS['DEBUG_MODE'] && running_script('occle')) { if (array_key_exists('keep_session', $_GET)) { return get_param_integer('keep_session'); } return -1; } return intval($_COOKIE['ocp_session']); // No need to stripslashes as it's numeric }
function handle_facebook_connection_login($current_logged_in_member) { if (!class_exists('ocp_tempcode')) { return NULL; } if (is_guest($current_logged_in_member)) { $current_logged_in_member = NULL; // We are not a normal cookie login so ocPortal has loaded up a Guest session already in the expectation of keeping it. Unsetting it will force a rebind (existing session may be reused though) require_code('users_inactive_occasionals'); set_session_id(-1); } // If already session-logged-in onto a Facebook account, don't bother doing anything if (!is_null($current_logged_in_member) && $GLOBALS['FORUM_DRIVER']->get_member_row_field($current_logged_in_member, 'm_password_compat_scheme') == 'facebook') { return $current_logged_in_member; } // Who is this user, from Facebook's point of view? global $FACEBOOK_CONNECT; $facebook_uid = $FACEBOOK_CONNECT->getUser(); if (is_null($facebook_uid)) { return $current_logged_in_member; } try { $details = $FACEBOOK_CONNECT->api('/me'); } catch (Exception $e) { return $current_logged_in_member; } $details2 = $FACEBOOK_CONNECT->api('/me', array('fields' => 'picture', 'type' => 'normal')); if (!is_array($details) || !is_array($details2)) { return $current_logged_in_member; } $details = array_merge($details, $details2); if (!isset($details['name'])) { return $current_logged_in_member; } $username = $details['name']; $photo_url = array_key_exists('picture', $details) ? $details['picture'] : ''; if (is_array($photo_url)) { $photo_url = $photo_url['data']['url']; } if ($photo_url != '') { $photo_url = 'http://graph.facebook.com/' . strval($facebook_uid) . '/picture?type=large'; // In case URL changes } $avatar_url = $photo_url == '' ? mixed() : $photo_url; $photo_thumb_url = ''; if ($photo_url != '') { $photo_thumb_url = $photo_url; } $email_address = array_key_exists('email', $details) ? $details['email'] : ''; $timezone = mixed(); if (isset($details['timezone'])) { require_code('temporal'); $timezone = convert_timezone_offset_to_formal_timezone($details['timezone']); } $language = mixed(); if (isset($details['locale'])) { $language = strtoupper($details['locale']); } if ($language !== NULL) { if (!file_exists(get_custom_file_base() . '/lang_custom/' . $language)) { $language = preg_replace('#\\_.*$#', '', $language); if (!file_exists(get_custom_file_base() . '/lang_custom/' . $language)) { $language = ''; } } } $dob = array_key_exists('birthday', $details) ? $details['birthday'] : ''; $dob_day = mixed(); $dob_month = mixed(); $dob_year = mixed(); if ($dob != '') { $_dob = explode('/', $dob); $dob_day = intval($_dob[1]); $dob_month = intval($_dob[0]); $dob_year = intval($_dob[2]); } // See if they have logged in before - i.e. have a synched account $member_row = $GLOBALS['FORUM_DB']->query_select('f_members', array('*'), array('m_password_compat_scheme' => 'facebook', 'm_pass_hash_salted' => $facebook_uid), 'ORDER BY id DESC', 1); $member = array_key_exists(0, $member_row) ? $member_row[0]['id'] : NULL; if (is_guest($member)) { $member = NULL; } /*if (!is_null($member)) // Useful for debugging { require_code('ocf_members_action2'); ocf_delete_member($member); $member=NULL; }*/ // If logged in before using Facebook, see if they've changed their name or email or timezone on Facebook -- if so, try and update locally to match if (!is_null($member)) { if (!is_null($current_logged_in_member) && $current_logged_in_member !== NULL && !is_guest($current_logged_in_member) && $current_logged_in_member != $member) { return $current_logged_in_member; } // User has an active login, and the Facebook account is bound to a DIFFERENT login. Take precedence to the other login that is active on top of this $last_visit_time = $member[0]['m_last_visit_time']; if ($timezone !== NULL) { if (tz_time(time(), $timezone) == tz_time(time(), $member[0]['m_timezone_offset'])) { $timezone = $member[0]['m_timezone_offset']; } // If equivalent, don't change } $test = $GLOBALS['FORUM_DB']->query_value_null_ok('f_members', 'id', array('m_username' => $username)); if (!is_null($test)) { $update_map = array('m_username' => $username, 'm_dob_day' => $dob_day, 'm_dob_month' => $dob_month, 'm_dob_year' => $dob_year); if ($email_address != '') { $update_map['m_email_address'] = $email_address; } if ($avatar_url !== NULL && ($test == '' || strpos($test, 'facebook') !== false || strpos($test, 'fbcdn') !== false)) { if ($timezone !== NULL) { $update_map['m_timezone_offset'] = $timezone; } $update_map['m_avatar_url'] = $avatar_url; $update_map['m_photo_url'] = $photo_url; $update_map['m_photo_thumb_url'] = $photo_thumb_url; } $GLOBALS['FORUM_DB']->query_update('f_members', $update_map, array('m_password_compat_scheme' => 'facebook', 'm_pass_hash_salted' => strval($facebook_uid)), '', 1); if ($username != $member[0]['m_username']) { // Fix cacheing for usernames $to_fix = array('f_forums/f_cache_last_username', 'f_posts/p_poster_name_if_guest', 'f_topics/t_cache_first_username', 'f_topics/t_cache_last_username'); foreach ($to_fix as $fix) { list($table, $field) = explode('/', $fix); $GLOBALS['FORUM_DB']->query_update($table, array($field => $username), array($field => $member[0]['m_username'])); } } } } // Not logged in before using Facebook, so we need to create an account, or bind to the active ocPortal login if there is one $in_a_sane_place = get_page_name() != 'login' && (running_script('index') || running_script('execute_temp')); // If we're in some weird script, or the login module UI, it's not a sane place, don't be doing account creation yet if (is_null($member) && $in_a_sane_place) { // Bind to existing ocPortal login? if (!is_null($current_logged_in_member)) { /*if (post_param_integer('associated_confirm',0)==0) Won't work because Facebook is currently done in JS and cookies force this. If user wishes to cancel they must go to http://www.facebook.com/settings?tab=applications and remove the app, then run a lost password reset. { $title=get_page_title('LOGIN_FACEBOOK_HEADER'); $message=do_lang_tempcode('LOGGED_IN_SURE_FACEBOOK',escape_html($GLOBALS['FORUM_DRIVER']->get_username($current_logged_in_member))); $middle=do_template('YESNO_SCREEN',array('TITLE'=>$title,'TEXT'=>$message,'HIDDEN'=>form_input_hidden('associated_confirm','1'),'URL'=>get_self_url_easy())); $tpl=globalise($middle,NULL,'',true); $tpl->evaluate_echo(); exit(); }*/ $GLOBALS['FORUM_DB']->query_update('f_members', array('m_password_compat_scheme' => 'facebook', 'm_pass_hash_salted' => $facebook_uid), array('id' => $current_logged_in_member), '', 1); require_code('site'); require_lang('facebook'); attach_message(do_lang_tempcode('FACEBOOK_ACCOUNT_CONNECTED', escape_html(get_site_name()), escape_html($GLOBALS['FORUM_DRIVER']->get_username($current_logged_in_member)), array(escape_html($username))), 'inform'); return $current_logged_in_member; } // If we're still here, we have to create a new account... // ------------------------------------------------------- $completion_form_submitted = post_param('email_address', '') != ''; // If there's a conflicting username, we may need to change it (suffix a number) require_code('ocf_members_action2'); $username = get_username_from_human_name($username); // Ask ocP to finish off the profile from the information presented in the POST environment (a standard mechanism in ocPortal, for third party logins of various kinds) require_lang('ocf'); require_code('ocf_members'); require_code('ocf_groups'); require_code('ocf_members2'); require_code('ocf_members_action'); $_custom_fields = ocf_get_all_custom_fields_match(ocf_get_all_default_groups(true), NULL, NULL, NULL, 1); if (!$completion_form_submitted && count($_custom_fields) != 0 && get_value('no_finish_profile') !== '1') { $GLOBALS['FACEBOOK_FINISHING_PROFILE'] = true; $middle = ocf_member_external_linker_ask($username, 'facebook', $email_address, $dob_day, $dob_month, $dob_year); $tpl = globalise($middle, NULL, '', true); $tpl->evaluate_echo(); exit; } else { $username = post_param('username', $username); if (count($_custom_fields) != 0 && get_value('no_finish_profile') !== '1') { // Was not auto-generated, so needs to be checked ocf_check_name_valid($username, NULL, NULL); } $member = ocf_member_external_linker($username, $facebook_uid, 'facebook', false, $email_address, $dob_day, $dob_month, $dob_year, $timezone, $language, $avatar_url, $photo_url, $photo_thumb_url); } } if (!is_null($member)) { require_code('users_inactive_occasionals'); create_session($member, 1, isset($_COOKIE[get_member_cookie() . '_invisible']) && $_COOKIE[get_member_cookie() . '_invisible'] == '1'); // This will mark it as confirmed } return $member; }
/** * Show an actual poll block. * * @param boolean Whether to show results (if we've already voted, this'll be overrided) * @param array The poll row * @param ID_TEXT The zone our poll module is in * @return tempcode The block */ function show_poll($results, $myrow, $zone) { $ip = get_ip_address(); if (!may_vote_in_poll($myrow)) { $results = true; } // Count our total votes $num_options = $myrow['num_options']; $totalvotes = 0; for ($i = 1; $i <= $num_options; $i++) { if (!array_key_exists('votes' . strval($i), $myrow)) { $myrow['votes' . strval($i)] = 0; } $totalvotes += $myrow['votes' . strval($i)]; } // Sort by results $orderings = array(); for ($i = 1; $i <= $num_options; $i++) { $orderings[$i] = $myrow['votes' . strval($i)]; } if ($results) { asort($orderings); } if (running_script('poll')) { $keep = symbol_tempcode('KEEP'); $vote_url = find_script('poll') . '?poll_id=' . strval($myrow['id']) . '&show_poll_results_' . strval($myrow['id']) . '=1¶m=' . urlencode(strval($myrow['id'])) . '&zone=' . urlencode(get_param('zone', get_module_zone('polls'))) . $keep->evaluate(); if (get_param_integer('in_panel', 0) == 1) { $vote_url .= '&in_panel=1'; } if (get_param_integer('interlock', 0) == 1) { $vote_url .= '&interlock=1'; } $result_url = $results ? '' : $vote_url; } else { $poll_results = 'show_poll_results_' . strval($myrow['id']); $vote_url = get_self_url(false, true, array('poll_id' => $myrow['id'], $poll_results => 1, 'utheme' => NULL)); $result_url = $results ? '' : get_self_url(false, true, array($poll_results => 1, 'utheme' => NULL)); } if (get_param('utheme', '') != '') { if (is_object($result_url)) { if (!$result_url->is_empty()) { $result_url->attach('&utheme=' . get_param('utheme')); } } else { if ($result_url != '') { $result_url .= '&utheme=' . get_param('utheme'); } } if (is_object($vote_url)) { if (!$vote_url->is_empty()) { $vote_url->attach('&utheme=' . get_param('utheme')); } } else { if ($vote_url != '') { $vote_url .= '&utheme=' . get_param('utheme'); } } } // Our questions templated $tpl = new ocp_tempcode(); for ($i = 1; $i <= $num_options; $i++) { $answer = get_translated_tempcode($myrow['option' . strval($i)]); $answer_plain = get_translated_text($myrow['option' . strval($i)]); if (!$results) { $tpl->attach(do_template('POLL_ANSWER', array('_GUID' => 'bc9c2e818f2e7031075d8d7b01d79cd5', 'PID' => strval($myrow['id']), 'I' => strval($i), 'CAST' => strval($i), 'VOTE_URL' => $vote_url, 'ANSWER' => $answer, 'ANSWER_PLAIN' => $answer_plain))); } else { $votes = $myrow['votes' . strval($i)]; if (!is_numeric($votes)) { $votes = 0; } if ($totalvotes != 0) { $width = intval(round(70.0 * floatval($votes) / floatval($totalvotes))); } else { $width = 0; } $tpl->attach(do_template('POLL_ANSWER_RESULT', array('_GUID' => '887ea0ed090c48305eb84500865e5178', 'PID' => strval($myrow['id']), 'I' => strval($i), 'VOTE_URL' => $vote_url, 'ANSWER' => $answer, 'ANSWER_PLAIN' => $answer_plain, 'WIDTH' => strval($width), 'VOTES' => integer_format($votes)))); } } if (has_actual_page_access(NULL, 'cms_polls', NULL, NULL) && has_submit_permission('mid', get_member(), get_ip_address(), 'cms_polls')) { $submit_url = build_url(array('page' => 'cms_polls', 'type' => 'ad', 'redirect' => running_script('index') ? get_self_url(true, true, array()) : NULL), get_module_zone('cms_polls')); } else { $submit_url = new ocp_tempcode(); } // Do our final template $question = get_translated_tempcode($myrow['question']); $question_plain = get_translated_text($myrow['question']); $archive_url = build_url(array('page' => 'polls', 'type' => 'misc'), $zone); $full_url = new ocp_tempcode(); if (get_page_name() != 'polls' || get_param('type', '') != 'view') { $full_url = build_url(array('page' => 'polls', 'type' => 'view', 'id' => $myrow['id']), $zone); } $map2 = array('_GUID' => '4c6b026f7ed96f0b5b8408eb5e5affb5', 'VOTE_URL' => $vote_url, 'SUBMITTER' => strval($myrow['submitter']), 'PID' => strval($myrow['id']), 'FULL_URL' => $full_url, 'CONTENT' => $tpl, 'QUESTION' => $question, 'QUESTION_PLAIN' => $question_plain, 'SUBMIT_URL' => $submit_url, 'ARCHIVE_URL' => $archive_url, 'RESULT_URL' => $result_url, 'ZONE' => $zone); if (get_option('is_on_comments') == '1' && !has_no_forum() && $myrow['allow_comments'] >= 1) { $map2['COMMENT_COUNT'] = '1'; } return do_template('POLL', $map2); }
/** * This function is a very basic query executor. It shouldn't usually be used by you, as there are abstracted versions available. * * @param string The complete SQL query * @param array A DB connection * @param ?integer The maximum number of rows to affect (NULL: no limit) * @param ?integer The start row to affect (NULL: no specification) * @param boolean Whether to output an error on failure * @param boolean Whether to get the autoincrement ID created for an insert query * @return ?mixed The results (NULL: no results), or the insert ID */ function db_query($query, $db, $max = NULL, $start = NULL, $fail_ok = false, $get_insert_id = false) { if (!is_null($max)) { if (is_null($start)) { $max += $start; } if (strtoupper(substr($query, 0, 7)) == 'SELECT ') { $query .= ' FETCH FIRST ' . strval($max + $start) . ' ROWS ONLY'; } } $results = @odbc_exec($db, $query); if ($results === false && !$fail_ok) { $err = odbc_errormsg($db); if (function_exists('ocp_mark_as_escaped')) { ocp_mark_as_escaped($err); } if (!running_script('upgrader') && get_page_name() != 'admin_import') { if (!function_exists('do_lang') || is_null(do_lang('QUERY_FAILED', NULL, NULL, NULL, NULL, false))) { fatal_exit(htmlentities('Query failed: ' . $query . ' : ' . $err)); } fatal_exit(do_lang_tempcode('QUERY_FAILED', escape_html($query), $err)); } else { echo htmlentities('Database query failed: ' . $query . ' [') . $err . htmlentities(']' . '<br />' . chr(10)); return NULL; } } if (strtoupper(substr($query, 0, 7)) == 'SELECT ' && !$results !== false) { return $this->db_get_query_rows($results); } if ($get_insert_id) { if (strtoupper(substr($query, 0, 7)) == 'UPDATE ') { return NULL; } $pos = strpos($query, '('); $table_name = substr($query, 12, $pos - 13); $res2 = odbc_exec($db, 'SELECT MAX(id) FROM ' . $table_name); $ar2 = odbc_fetch_row($res2); return $ar2[0]; } return NULL; }
/** * A template has not been structurally cached, so compile it and store in the cache. * * @param ID_TEXT The theme the template is in the context of * @param PATH The path to the template file * @param ID_TEXT The codename of the template (e.g. foo) * @param ID_TEXT The actual codename to use for the template (e.g. foo_mobile) * @param LANGUAGE_NAME The language the template is in the context of * @param string File type suffix of template file (e.g. .tpl) * @param ?ID_TEXT The theme to cache in (NULL: main theme) * @return tempcode The compiled tempcode */ function _do_template($theme, $path, $codename, $_codename, $lang, $suffix, $theme_orig = NULL) { if (is_null($theme_orig)) { $theme_orig = $theme; } if (is_null($GLOBALS['CURRENT_SHARE_USER'])) { $base_dir = ($theme == 'default' && ($suffix != '.css' || strpos($path, '/css_custom') === false) ? get_file_base() : get_custom_file_base()) . '/themes/'; } else { $base_dir = get_custom_file_base() . '/themes/'; if (!is_file($base_dir . $theme . $path . $codename . $suffix)) { $base_dir = get_file_base() . '/themes/'; } } global $CACHE_TEMPLATES, $FILE_ARRAY, $TEMPLATE_PREVIEW_OP, $MEM_CACHE; if (isset($FILE_ARRAY)) { $html = unixify_line_format(file_array_get('themes/' . $theme . $path . $codename . $suffix)); } else { $html = unixify_line_format(file_get_contents($base_dir . filter_naughty($theme . $path . $codename) . $suffix, FILE_TEXT)); } if ($GLOBALS['SEMI_DEBUG_MODE'] && strpos($html, '.innerHTML') !== false && !running_script('install') && strpos($html, 'Parser hint: .innerHTML okay') === false) { attach_message('Do not use the .innerHTML property in your Javascript because it will not work in true XHTML (when the browsers real XML parser is in action). Use ocPortal\'s global setInnerHTML/getInnerHTML functions.', 'warn'); } // Strip off trailing final lines from single lines templates. Editors often put these in, and it causes annoying "visible space" issues if (substr($html, -1, 1) == chr(10) && substr_count($html, chr(10)) == 1) { $html = substr($html, 0, strlen($html) - 1); } if ($TEMPLATE_PREVIEW_OP) { $test = post_param($codename, NULL); if (!is_null($test)) { $html = post_param($test . '_new'); } } $result = template_to_tempcode($html, 0, false, $suffix != '.tpl' ? '' : $codename, $theme_orig, $lang); if ($CACHE_TEMPLATES && !$TEMPLATE_PREVIEW_OP && ($suffix == '.tpl' || $codename == 'no_cache')) { $path2 = get_custom_file_base() . '/themes/' . $theme_orig . '/templates_cached/' . filter_naughty($lang) . '/'; $myfile = @fopen($path2 . filter_naughty($_codename) . $suffix . '.tcp', 'wb'); if ($myfile === false) { @mkdir(dirname($path2), 0777); fix_permissions(dirname($path2), 0777); sync_file(dirname($path2)); if (@mkdir($path2, 0777)) { fix_permissions($path2, 0777); sync_file($path2); } else { if ($codename == 'SCREEN_TITLE') { critical_error('PASSON', do_lang('WRITE_ERROR', escape_html($path2 . filter_naughty($_codename) . $suffix . '.tcp'))); } // Bail out hard if would cause a loop intelligent_write_error($path2 . filter_naughty($_codename) . $suffix . '.tcp'); } } else { $data_to_write = '<' . '?php' . chr(10) . $result->to_assembly($lang) . chr(10) . '?' . '>'; if (fwrite($myfile, $data_to_write) >= strlen($data_to_write)) { // Success fclose($myfile); require_code('files'); fix_permissions($path2 . filter_naughty($_codename) . $suffix . '.tcp'); } else { // Failure fclose($myfile); @unlink($path2 . filter_naughty($_codename) . $suffix . '.tcp'); // Can't leave this around, would cause problems } } } return $result; }