/** * Returns possible matches for the string input * * @return @e void Outputs to screen */ protected function _getMembers() { //----------------------------------------- // INIT //----------------------------------------- $name = IPSText::convertUnicode($this->convertAndMakeSafe($this->request['name'], 0), true); $name = IPSText::convertCharsets($name, 'utf-8', IPS_DOC_CHAR_SET); //----------------------------------------- // Check length //----------------------------------------- if (IPSText::mbstrlen($name) < 3) { $this->returnJsonError('requestTooShort'); } //----------------------------------------- // Try query... //----------------------------------------- $this->DB->build(array('select' => 'm.members_display_name, m.member_id, m.members_seo_name, m.member_group_id', 'from' => array('members' => 'm'), 'where' => "m.members_l_display_name LIKE '" . $this->DB->addSlashes(strtolower($name)) . "%'", 'order' => $this->DB->buildLength('m.members_display_name') . ' ASC', 'limit' => array(0, 15), 'add_join' => array(array('select' => 'p.*', 'from' => array('profile_portal' => 'p'), 'where' => 'p.pp_member_id=m.member_id', 'type' => 'left')))); $this->DB->execute(); //----------------------------------------- // Got any results? //----------------------------------------- if (!$this->DB->getTotalRows()) { $this->returnJsonArray(array()); } $return = array(); while ($r = $this->DB->fetch()) { $url = $this->registry->output->buildSEOUrl("app=core&module=modcp&do=editmember&mid={$r['member_id']}", 'public'); $photo = IPSMember::buildProfilePhoto($r); $group = IPSMember::makeNameFormatted('', $r['member_group_id']); $return[$r['member_id']] = array('name' => $r['members_display_name'], 'showas' => '<strong>' . $r['members_display_name'] . '</strong> (' . $group . ')', 'img' => $photo['pp_thumb_photo'], 'img_w' => $photo['pp_mini_width'], 'img_h' => $photo['pp_mini_height'], 'url' => $url); } $this->returnJsonArray($return); }
/** * Handles the live search * * @return @e void */ public function doSearchRequest() { //----------------------------------------- // Init //----------------------------------------- $search_term = IPSText::convertCharsets($this->request['search_term'], 'utf-8', IPS_DOC_CHAR_SET); $results = array(); $results = array('members' => array(), 'groups' => array(), 'groupLangs' => false, 'settings' => array(), 'forums' => array(), 'location' => array()); if (IPSLib::appIsInstalled('nexus')) { $results['nexus'] = array(); } //----------------------------------------- // Search //----------------------------------------- $results = $this->_getSettings($search_term, $results); $results = $this->_getFromXML($search_term, $results); $results = $this->_getMembers($search_term, $results); $results = $this->_checkGroups($search_term, $results); $results = $this->_checkForums($search_term, $results); if (IPSLib::appIsInstalled('nexus')) { $results = $this->_checkNexus($search_term, $results); } //----------------------------------------- // Output //----------------------------------------- $this->returnJsonArray($results); }
/** * Redirect to Twitter * Exciting, isn't it. * * @access private * @param string Plug in * @note Removed utf8_encode() call around the title due to the linked bug report * @link http://community.invisionpower.com/resources/bugs.html/_/ip-board/twitter-share-buttonbox-r41010 */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $hashMan = $this->settings['twitter_hashtag']; if ($hashMan && substr($hashMan, 0, 1) != '#') { $hashMan = urlencode('#' . $hashMan); } $hashMan = $hashMan ? '%20' . $hashMan : ''; $url = "http://twitter.com/intent/tweet?status=" . urlencode($title) . '%20-%20' . urlencode($url) . $hashMan; $this->registry->output->silentRedirect($url); }
/** * Send API Call * * @param string Method * @param array Arguments * @return stdClass Object from returned JSON */ public function __call($method, $args) { $send = array_merge(array('key' => $this->api_key), (isset($args[0]) and is_array($args[0])) ? $args[0] : array()); if (IPS_DOC_CHAR_SET != 'UTF-8') { $send['message']['html'] = IPSText::convertCharsets($send['message']['html'], IPS_DOC_CHAR_SET, 'utf-8'); } $response = $this->cfm->postFileContents(self::URL . str_replace('_', '/', $method) . '.json', json_encode($send)); if ($json = json_decode($response)) { return $json; } return NULL; }
/** * Redirect to Print * Exciting, isn't it. * * @access private * @param string Title * @param string URL */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $_qmCount = substr_count($url, '?'); $_count = $this->settings['url_type'] == 'query_string' ? 1 : 0; if ($_qmCount > $_count) { #?/furl?s=xxxx $url .= '&forceDownload=1'; } else { $url .= '?forceDownload=1'; } $url .= '&_k=' . $this->member->form_hash; $this->registry->output->silentRedirect($url); }
/** * Return a JSON array * * @param array Single dimensional array of key => value fields * @return void [Outputs JSON string and exits] */ public function returnJsonArray($json = array()) { @header("Content-type: application/json;charset=" . IPS_DOC_CHAR_SET); $this->printNocacheHeaders(); /* Always return as UTF-8 */ array_walk_recursive($json, create_function('&$value, $key', '$value = IPSText::convertCharsets($value, "' . IPS_DOC_CHAR_SET . '", "UTF-8");')); $result = json_encode($json); $result = IPSText::convertCharsets($result, "UTF-8", IPS_DOC_CHAR_SET); print $result; exit; }
/** * Fetches the output * * @access public * @param string Output gathered * @param string Title of the document * @param array Navigation gathered * @param array Array of document head items * @param array Array of JS loader items * @param array Array of extra data * @return string Output to be printed to the client */ public function fetchOutput($output, $title, $navigation, $documentHeadItems, $jsLoaderItems, $extraData = array()) { //----------------------------------------- // INIT //----------------------------------------- $system_vars_cache = $this->caches['systemvars']; $showPMBox = ''; $currentCharSet = $this->settings['gb_char_set']; /* Force UTF-8 for the skin */ $this->settings['gb_char_set'] = 'UTF-8'; //----------------------------------------- // NORMAL //----------------------------------------- if ($this->_outputType == 'normal') { //----------------------------------------- // Grab output //----------------------------------------- $finalOutput = $this->output->getTemplate('global')->globalTemplate($output, $documentHeadItems, $this->_css, $jsLoaderItems, $this->_metaTags, array('title' => $title, 'applications' => $this->core_fetchApplicationData(), 'page' => $this->_current_page_title), array('navigation' => $navigation), array('time' => $this->registry->getClass('class_localization')->getDate(time(), 'SHORT', 1), 'lang_chooser' => $this->html_buildLanguageDropDown(), 'skin_chooser' => $this->html_fetchSetsDropDown(), 'stats' => $this->html_showDebugInfo(), 'copyright' => $this->html_fetchCopyright()), array('ex_time' => sprintf("%.4f", IPSDebug::endTimer()), 'gzip_status' => $this->settings['disable_gzip'] == 1 ? $this->lang->words['gzip_off'] : $this->lang->words['gzip_on'], 'server_load' => ipsRegistry::$server_load, 'queries' => $this->DB->getQueryCount())); } else { if ($this->_outputType == 'redirect') { # SEO? if ($extraData['seoTitle']) { $extraData['url'] = $this->output->buildSEOUrl($extraData['url'], 'none', $extraData['seoTitle']); $extraData['full'] = 1; } $finalOutput = $this->output->getTemplate('global')->redirectTemplate($documentHeadItems, $this->_css, $jsLoaderItems, $extraData['text'], $extraData['url'], $extraData['full']); } else { if ($this->_outputType == 'popup') { $finalOutput = $this->output->getTemplate('global')->displayPopUpWindow($documentHeadItems, $this->_css, $jsLoaderItems, $title, $output); } } } //----------------------------------------- // Return //----------------------------------------- $finalOutput = $this->parseIPSTags($finalOutput); /* Attempt to clean HTML */ return IPSText::stripNonUtf8(IPSText::convertCharsets($finalOutput, $currentCharSet, 'UTF-8')); }
/** * Redirect to Twitter * Exciting, isn't it. * * @access private * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://del.icio.us/post?v=2&url=" . urlencode($url) . "&title=" . urlencode($title); $this->registry->output->silentRedirect($url); }
/** * Redirect to Twitter * Exciting, isn't it. * * @access private * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://memori.ru/link/?sm=1&u_data[url]=" . urlencode($url) . '&u_data[name]=' . urlencode($title); $this->registry->output->silentRedirect($url); }
/** * Redirect to Google * Exciting, isn't it. * * @access private * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://www.google.com/buzz/post?url=" . urlencode($url) . "&title=" . urlencode($title) . "&type=normal-count"; $this->registry->output->silentRedirect($url); }
/** * Execute the feed and return the HTML to show on the page. * Can be called from ACP or front end, so the plugin needs to setup any appropriate lang files, skin files, etc. * * @access public * @param array Block data * @return string Block HTML to display or cache */ public function executeFeed($block) { $this->lang->loadLanguageFile(array('public_ccs'), 'ccs'); $config = unserialize($block['block_config']); //----------------------------------------- // Init RSS kernel library //----------------------------------------- if (!is_object($this->class_rss)) { require_once IPS_KERNEL_PATH . 'classRss.php'; $this->class_rss = new classRss(); $this->class_rss->use_sockets = ipsRegistry::$settings['enable_sockets']; $this->class_rss->doc_type = IPS_DOC_CHAR_SET; } $this->class_rss->feed_charset = $config['filters']['rss_charset']; if (strtolower($config['rss_charset']) != IPS_DOC_CHAR_SET) { $this->class_rss->convert_charset = 1; $this->class_rss->destination_charset = $this->class_rss->doc_type; } else { $this->class_rss->convert_charset = 0; } $this->class_rss->errors = array(); $this->class_rss->rss_items = array(); $this->class_rss->auth_req = ''; $this->class_rss->auth_user = ''; $this->class_rss->auth_pass = ''; $this->class_rss->rss_count = 0; $this->class_rss->rss_max_show = $config['filters']['rss_limit']; //----------------------------------------- // Get feed //----------------------------------------- $this->class_rss->parseFeedFromUrl($config['filters']['rss_feed']); //----------------------------------------- // Error checking //----------------------------------------- if (is_array($this->class_rss->errors) and count($this->class_rss->errors)) { return ''; } if (!is_array($this->class_rss->rss_channels) or !count($this->class_rss->rss_channels)) { return ''; } if (!is_array($this->class_rss->rss_items) or !count($this->class_rss->rss_items)) { return ''; } //----------------------------------------- // Loop over items and put into array //----------------------------------------- $content = array(); foreach ($this->class_rss->rss_channels as $channel_id => $channel_data) { if (is_array($this->class_rss->rss_items[$channel_id]) and count($this->class_rss->rss_items[$channel_id])) { foreach ($this->class_rss->rss_items[$channel_id] as $item_data) { //----------------------------------------- // Check basic data //----------------------------------------- $item_data['content'] = $item_data['content'] ? $item_data['content'] : $item_data['description']; $item_data['url'] = $item_data['link']; $item_data['date'] = intval($item_data['unixdate']) ? intval($item_data['unixdate']) : time(); //----------------------------------------- // Convert charset //----------------------------------------- if ($config['rss_charset'] and strtolower(IPS_DOC_CHAR_SET) != strtolower($config['filters']['rss_charset'])) { $item_data['title'] = IPSText::convertCharsets($item_data['title'], $config['filters']['rss_charset'], IPS_DOC_CHAR_SET); $item_data['content'] = IPSText::convertCharsets($item_data['content'], $config['filters']['rss_charset'], IPS_DOC_CHAR_SET); } //----------------------------------------- // Dates //----------------------------------------- if ($item_data['date'] < 1) { $item_data['date'] = time(); } else { if ($item_data['date'] > time()) { $item_data['date'] = time(); } } //----------------------------------------- // Got stuff? //----------------------------------------- if (!$item_data['title'] or !$item_data['content']) { continue; } //----------------------------------------- // Strip html if needed //----------------------------------------- if ($config['filters']['rss_html']) { $item_data['title'] = strip_tags($item_data['title']); $item_data['content'] = strip_tags($item_data['content']); } $content[] = $item_data; } } } //----------------------------------------- // Return formatted content //----------------------------------------- $feedConfig = $this->returnFeedInfo(); $templateBit = $feedConfig['templateBit'] . '_' . $block['block_id']; if ($config['hide_empty'] and !count($content)) { return ''; } return $this->registry->output->getTemplate('ccs')->{$templateBit}($block['block_name'], $content); }
/** * Uploads and saves file * * @return mixed void, or the new insert id */ public function processUpload() { //----------------------------------------- // INIT //----------------------------------------- $this->error = ''; $this->getUploadFormSettings(); //----------------------------------------- // Check upload dir //----------------------------------------- if (!$this->checkUploadDirectory()) { if ($this->error) { return; } } //----------------------------------------- // Can upload? //----------------------------------------- if (!$this->attach_stats['allow_uploads']) { $this->error = 'upload_failed'; return; } //----------------------------------------- // Got attachment types? //----------------------------------------- if (!$this->registry->cache()->getCache('attachtypes') or !is_array($this->registry->cache()->getCache('attachtypes'))) { $attachtypes = array(); $this->DB->build(array('select' => 'atype_extension,atype_mimetype,atype_post,atype_img', 'from' => 'attachments_type', 'where' => "atype_post=1")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $attachtypes[$r['atype_extension']] = $r; } $this->registry->cache()->updateCacheWithoutSaving('attachtypes', $attachtypes); } //----------------------------------------- // Set up array //----------------------------------------- $attach_data = array('attach_ext' => "", 'attach_file' => "", 'attach_location' => "", 'attach_thumb_location' => "", 'attach_hits' => 0, 'attach_date' => time(), 'attach_post_key' => $this->attach_post_key, 'attach_member_id' => $this->memberData['member_id'], 'attach_rel_id' => $this->attach_rel_id, 'attach_rel_module' => $this->type, 'attach_filesize' => 0); //----------------------------------------- // Load the library //----------------------------------------- require_once IPS_KERNEL_PATH . 'classUpload.php'; /*noLibHook*/ $upload = new classUpload(); //----------------------------------------- // Set up the variables //----------------------------------------- $upload->out_file_name = $this->type . '-' . $this->memberData['member_id'] . '-' . str_replace(array('.', ' '), '-', microtime()); $upload->out_file_dir = $this->upload_path; $upload->max_file_size = $this->attach_stats['max_single_upload'] ? $this->attach_stats['max_single_upload'] : 1000000000; $upload->make_script_safe = 1; $upload->force_data_ext = 'ipb'; //----------------------------------------- // Populate allowed extensions //----------------------------------------- if (is_array($this->registry->cache()->getCache('attachtypes')) and count($this->registry->cache()->getCache('attachtypes'))) { /* SKINNOTE: I had to add [attachtypes] to this cache to make it work, may need fixing? */ //$tmp = $this->registry->cache()->getCache('attachtypes'); foreach ($this->registry->cache()->getCache('attachtypes') as $idx => $data) { if ($data['atype_post']) { $upload->allowed_file_ext[] = $data['atype_extension']; } } } //----------------------------------------- // Upload... //----------------------------------------- $upload->process(); //----------------------------------------- // Error? //----------------------------------------- if ($upload->error_no) { switch ($upload->error_no) { case 1: // No upload $this->error = 'upload_no_file'; return $attach_data; break; case 2: // Invalid file ext $this->error = 'invalid_mime_type'; return $attach_data; break; case 3: // Too big... $this->error = 'upload_too_big'; return $attach_data; break; case 4: // Cannot move uploaded file $this->error = 'upload_failed'; return $attach_data; break; case 5: // Possible XSS attack (image isn't an image) $this->error = 'upload_failed'; return $attach_data; break; } } //----------------------------------------- // Still here? //----------------------------------------- if ($upload->saved_upload_name and @is_file($upload->saved_upload_name)) { //----------------------------------------- // Strip off { } and [ ] //----------------------------------------- $upload->original_file_name = str_replace(array('[', ']', '{', '}'), "", $upload->original_file_name); $attach_data['attach_filesize'] = @filesize($upload->saved_upload_name); $attach_data['attach_location'] = $this->upload_dir . $upload->parsed_file_name; if (IPSText::isUTF8($upload->original_file_name)) { $attach_data['attach_file'] = IPSText::convertCharsets($upload->original_file_name, "UTF-8", IPS_DOC_CHAR_SET); } else { $attach_data['attach_file'] = $upload->original_file_name; } $attach_data['attach_is_image'] = $upload->is_image; $attach_data['attach_ext'] = $upload->real_file_extension; if ($attach_data['attach_is_image'] == 1) { require_once IPS_KERNEL_PATH . 'classImage.php'; /*noLibHook*/ require_once IPS_KERNEL_PATH . 'classImageGd.php'; /*noLibHook*/ /* Main attachment */ if (!empty($this->settings['attach_img_max_w']) and !empty($this->settings['attach_img_max_h'])) { $image = new classImageGd(); $image->init(array('image_path' => $this->upload_path, 'image_file' => $upload->parsed_file_name)); $image->force_resize = false; if ($imgData = $image->resizeImage($this->settings['attach_img_max_w'], $this->settings['attach_img_max_h'], false, true)) { if (!$imgData['noResize']) { $image->writeImage($this->upload_path . '/' . $upload->parsed_file_name); } if (is_array($imgData)) { $attach_data['attach_img_width'] = $imgData['newWidth']; $attach_data['attach_img_height'] = $imgData['newHeight']; } $attach_data['attach_filesize'] = @filesize($this->upload_path . '/' . $upload->parsed_file_name); } } /* Thumb nail */ $image = new classImageGd(); $image->force_resize = true; $image->init(array('image_path' => $this->upload_path, 'image_file' => $upload->parsed_file_name)); if (TRUE) { if ($this->attach_settings['siu_width'] < $attach_data['attach_img_width'] or $this->attach_settings['siu_height'] < $attach_data['attach_img_height']) { $_thumbName = preg_replace('#^(.*)\\.(\\w+?)$#', "\\1_thumb.\\2", $upload->parsed_file_name); if ($thumb_data = $image->resizeImage($this->attach_settings['siu_width'], $this->attach_settings['siu_height'])) { $image->writeImage($this->upload_path . '/' . $_thumbName); if (is_array($thumb_data)) { $thumb_data['thumb_location'] = $_thumbName; } } } else { /* Instead of building a thumb the same size as the main image, just copy the details */ $thumb_data = array('thumb_location' => $upload->parsed_file_name, 'newWidth' => $attach_data['attach_img_width'], 'newHeight' => $attach_data['attach_img_height']); } } if ($thumb_data['thumb_location']) { $attach_data['attach_img_width'] = $thumb_data['originalWidth']; $attach_data['attach_img_height'] = $thumb_data['originalHeight']; $attach_data['attach_thumb_width'] = $thumb_data['newWidth']; $attach_data['attach_thumb_height'] = $thumb_data['newHeight']; $attach_data['attach_thumb_location'] = $this->upload_dir . $thumb_data['thumb_location']; } } //----------------------------------------- // Make sure we send integers // @link http://community.invisionpower.com/tracker/issue-32511-attachments-mysql-strict-mode //----------------------------------------- $attach_data['attach_img_width'] = intval($attach_data['attach_img_width']); $attach_data['attach_img_height'] = intval($attach_data['attach_img_height']); $attach_data['attach_thumb_width'] = intval($attach_data['attach_thumb_width']); $attach_data['attach_thumb_height'] = intval($attach_data['attach_thumb_height']); //----------------------------------------- // Add into Database //----------------------------------------- $this->DB->insert('attachments', $attach_data); $newid = $this->DB->getInsertId(); return $newid; } }
/** * Completes the connection * * @access public * @return redirect */ public function finishLogin() { /* From reg flag */ if ($_REQUEST['code']) { /* Load oAuth */ require_once IPS_KERNEL_PATH . 'facebook/facebookoauth.php'; /*noLibHook*/ $this->_oauth = new FacebookOAuth(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CALLBACK, $this->extendedPerms); /* Load API */ require_once IPS_KERNEL_PATH . 'facebook/facebook.php'; /*noLibHook*/ $this->_api = new Facebook(array('appId' => FACEBOOK_APP_ID, 'secret' => FACEBOOK_APP_SECRET, 'cookie' => true)); /* Ensure URL is correct */ $_urlExtra = ''; if ($_REQUEST['key']) { $_urlExtra .= '&key=' . $_REQUEST['key']; } if ($_REQUEST['_reg']) { $_urlExtra .= '&_reg=1'; } /* Update callback url */ $this->_oauth->setCallBackUrl(FACEBOOK_CALLBACK . $_urlExtra); /* Generate oAuth token */ $rToken = $this->_oauth->getAccessToken($_REQUEST['code']); if (is_string($rToken)) { try { $_userData = $this->_api->api('me', array('access_token' => $rToken)); } catch (Exception $e) { /* Try re-authorising */ if (stristr($e->getMessage(), 'invalid')) { $this->redirectToConnectPage(); } } /* A little gymnastics */ $this->_userData = $_userData; $_userData = $this->fetchUserData($rToken); /* Got a member linked already? */ $_member = IPSMember::load($_userData['id'], 'all', 'fb_uid'); /* Not connected, check email address */ if (!$_member['member_id'] and $_userData['email']) { $_member = IPSMember::load($_userData['email'], 'all', 'email'); /* We do have an existing account, so trash email forcing user to sign up with new */ if ($_member['member_id']) { /* Update row */ IPSMember::save($_member['member_id'], array('core' => array('fb_uid' => $_userData['id'], 'fb_token' => $rToken))); } } if ($_member['member_id']) { $memberData = $_member; /* Ensure user's row is up to date */ IPSMember::save($memberData['member_id'], array('core' => array('fb_token' => $rToken))); /* Here, so log us in!! */ /* changed by denchu 26/12/12 */ $r = $this->_login()->loginWithoutCheckingCredentials($memberData['member_id'], TRUE); if (is_array($r)) { if (isset($r[1])) { $this->registry->getClass('output')->redirectScreen($r[0], $r[1]); $this->registry->getClass('output')->silentRedirect($r[1]); } else { $this->registry->getClass('output')->silentRedirect($r[0]); } } elseif (!$r) { throw new Exception('LINKED_MEMBER_LOGIN_FAIL'); } else { $this->registry->getClass('output')->silentRedirect($this->settings['base_url']); } } else { /* No? Create a new member */ foreach (array('fbc_s_pic', 'fbc_s_status', 'fbc_s_aboutme') as $field) { $toSave[$field] = 1; } $fb_bwoptions = IPSBWOptions::freeze($toSave, 'facebook'); $safeFBName = IPS_DOC_CHAR_SET != 'UTF-8' ? IPSText::utf8ToEntities($_userData['name']) : $_userData['name']; /* Make sure usernames are safe */ if ($this->settings['username_characters']) { $check_against = preg_quote($this->settings['username_characters'], "/"); $check_against = str_replace('\\-', '-', $check_against); $safeFBName = preg_replace('/[^' . $check_against . ']+/i', '', $safeFBName); } /* Check ban filters? */ if (IPSMember::isBanned('email', $_userData['email']) or IPSMember::isBanned('name', $safeFBName)) { $this->registry->output->showError('you_are_banned', 1090003); } $displayName = $this->settings['fb_realname'] == 'enforced' ? $safeFBName : ''; /* From reg, so create new account properly */ $toSave = array('core' => array('name' => IPSText::parseCleanValue($safeFBName), 'members_display_name' => IPSText::parseCleanValue($displayName), 'members_created_remote' => 1, 'member_group_id' => $this->settings['fbc_mgid'] ? $this->settings['fbc_mgid'] : $this->settings['member_group'], 'email' => $_userData['email'], 'fb_uid' => $_userData['id'], 'time_offset' => $_userData['timezone'], 'members_auto_dst' => 1, 'fb_token' => $rToken), 'extendedProfile' => array('pp_about_me' => IPSText::getTextClass('bbcode')->stripBadWords(IPSText::convertCharsets($_userData['about'], 'utf-8', IPS_DOC_CHAR_SET)), 'fb_bwoptions' => $fb_bwoptions)); $memberData = IPSMember::create($toSave, FALSE, FALSE, TRUE); if (!$memberData['member_id']) { throw new Exception('CREATION_FAIL'); } /* Sync up photo */ $this->syncMember($memberData['member_id']); $pmember = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'members_partial', 'where' => "partial_member_id=" . $memberData['member_id'])); if ($pmember['partial_member_id']) { $this->registry->getClass('output')->silentRedirect($this->settings['base_url'] . 'app=core&module=global§ion=register&do=complete_login&mid=' . $memberData['member_id'] . '&key=' . $pmember['partial_date']); } else { /* Already got a display name */ if ($displayName) { /* Here, so log us in!! */ $r = $this->_login()->loginWithoutCheckingCredentials($memberData['member_id'], TRUE); IPSLib::runMemberSync('onCompleteAccount', $memberData); if ($this->settings['new_reg_notify']) { $this->registry->class_localization->loadLanguageFile(array('public_register'), 'core'); IPSText::getTextClass('email')->setPlainTextTemplate(IPSText::getTextClass('email')->getTemplate("admin_newuser")); IPSText::getTextClass('email')->buildMessage(array('DATE' => $this->registry->getClass('class_localization')->getDate(time(), 'LONG', 1), 'LOG_IN_NAME' => $safeFBName, 'EMAIL' => $_userData['email'], 'IP' => $this->member->ip_address, 'DISPLAY_NAME' => $displayName)); IPSText::getTextClass('email')->subject = sprintf($this->lang->words['new_registration_email'], $this->settings['board_name']); IPSText::getTextClass('email')->to = $this->settings['email_in']; IPSText::getTextClass('email')->sendMail(); } if (is_array($r)) { if (isset($r[1])) { $this->registry->getClass('output')->redirectScreen($r[0], $r[1]); $this->registry->getClass('output')->silentRedirect($r[1]); } else { $this->registry->getClass('output')->silentRedirect($r[0]); } } elseif (!$r) { throw new Exception('LINKED_MEMBER_LOGIN_FAIL'); } else { $this->registry->getClass('output')->silentRedirect($this->settings['base_url']); } } else { throw new Exception('CREATION_FAIL'); } } } } else { throw new Exception('CREATION_FAIL'); } } else { /* Need to re-auth */ } }
/** * Get the WHERE part of the SQL query * * @return string SQL WHERE string */ public function getWhereClause() { //----------------------------------------- // Ignore filters? //----------------------------------------- if ($this->showAllMembers) { return ''; } //----------------------------------------- // Init //----------------------------------------- $data = $this->generateFilterBoxes(); $_sql = array(); //print_r($data);exit; //----------------------------------------- // Filters //----------------------------------------- if ($data['member_contains_text']) { $_field = ''; $_text = $this->DB->addSlashes($data['member_contains_text']); switch ($data['member_contains']) { default: case 'member_id': $_field = 'm.member_id'; break; case 'name': $_field = 'm.members_l_username'; $_text = strtolower($_text); break; case 'members_display_name': $_field = 'm.members_l_display_name'; $_text = strtolower($_text); break; case 'email': $_field = 'm.email'; break; case 'ip_address': $_field = 'm.ip_address'; break; case 'signature': $_field = 'pp.signature'; break; } switch ($data['member_contains_type']) { default: case 'contains': $_sql[] = $this->DB->buildCast($_field, 'VARCHAR') . " LIKE '%" . $_text . "%'"; break; case 'begins': $_sql[] = $this->DB->buildCast($_field, 'VARCHAR') . " LIKE '" . $_text . "%'"; break; case 'ends': $_sql[] = $this->DB->buildCast($_field, 'VARCHAR') . " LIKE '%" . $_text . "'"; break; case 'equals': $_sql[] = $this->DB->buildCast($_field, 'VARCHAR') . " = '" . $_text . "'"; break; } } //----------------------------------------- // "Simple" all-in-one search //----------------------------------------- if ($data['member_string'] and strlen($data['member_string']) >= 3) { /* Fix from ticket 766094 */ $_text = $this->DB->addSlashes(IPSText::convertCharsets($data['member_string'], 'utf-8', IPS_DOC_CHAR_SET)); $_sql[] = '(' . $this->DB->buildCast('m.name', 'VARCHAR') . " LIKE '%" . $_text . "%' OR " . $this->DB->buildCast('m.members_display_name', 'VARCHAR') . " LIKE '%" . $_text . "%' OR " . $this->DB->buildCast('m.email', 'VARCHAR') . " LIKE '%" . $_text . "%' OR " . $this->DB->buildCast('m.ip_address', 'VARCHAR') . " LIKE '%" . $_text . "%')"; } //----------------------------------------- // Group limiting //----------------------------------------- if ($data['primary_group']) { if ($data['include_secondary']) { $_sql[] = "( m.member_group_id=" . intval($data['primary_group']) . " OR " . "m.mgroup_others LIKE '%," . intval($data['primary_group']) . ",%' OR " . "m.mgroup_others LIKE '" . intval($data['primary_group']) . ",%' OR " . "m.mgroup_others LIKE '%," . intval($data['primary_group']) . "' OR " . "m.mgroup_others='" . intval($data['primary_group']) . "' )"; } else { $_sql[] = "m.member_group_id=" . intval($data['primary_group']); } } if ($data['secondary_group']) { $_sql[] = "( m.mgroup_others LIKE '%," . $data['secondary_group'] . ",%' OR " . "m.mgroup_others LIKE '" . $data['secondary_group'] . ",%' OR " . "m.mgroup_others LIKE '%," . $data['secondary_group'] . "' OR " . "m.mgroup_others='" . $data['secondary_group'] . "' )"; } //----------------------------------------- // Post count //----------------------------------------- if (($data['post_count'] or $data['post_count'] == '0') and $data['post_count_type']) { $_type = ''; if ($data['post_count_type'] == 'gt') { $_type = '>'; } else { if ($data['post_count_type'] == 'lt') { $_type = '<'; } else { if ($data['post_count_type'] == 'eq') { $_type = '='; } } } if ($_type) { $_sql[] = "m.posts" . $_type . intval($data['post_count']); } } //----------------------------------------- // Date filters //----------------------------------------- foreach (array('reg', 'post', 'active') as $_bit) { foreach (array('from', 'to') as $_when) { $bit = 'date_' . $_bit . '_' . $_when; if ($data[$bit]) { //----------------------------------------- // mm/dd/yyyy instead of mm-dd-yyyy //----------------------------------------- $data[$bit] = str_replace('/', '-', $data[$bit]); list($month, $day, $year) = explode('-', $data[$bit]); if (!checkdate($month, $day, $year)) { $this->registry->output->global_message = sprintf($this->lang->words['m_daterange'], $month, $day, $year); } else { /* Bug #24067 */ /* Original fix caused this bug: http://community.invisionpower.com/tracker/issue-24416-search-dates-invalid-acp/ Changed to just verify the result is an int, as that is all that's needed to prevent DB error */ $time_int = mktime(0, 0, 0, $month, $day, $year); if (!is_int($time_int)) { $this->registry->output->global_message = sprintf($this->lang->words['m_daterange'], $month, $day, $year); } else { switch ($_bit) { case 'reg': $field = 'joined'; break; case 'post': $field = 'last_post'; break; case 'active': $field = 'last_activity'; break; } if ($_when == 'from') { $_sql[] = 'm.' . $field . ' > ' . $time_int; } else { $_sql[] = 'm.' . $field . ' < ' . $time_int; } } } } } } //----------------------------------------- // Custom fields... //----------------------------------------- if (is_array($data['custom_fields']) and count($data['custom_fields'])) { foreach ($data['custom_fields'] as $id => $value) { if ($value) { if ($this->caches['profilefields'][$id]['pf_type'] == 'drop') { $_sql[] = "p.field_{$id}='" . $this->DB->addSlashes($value) . "'"; } else { if ($this->caches['profilefields'][$id]['pf_type'] == 'cbox') { if (count($value)) { foreach (explode(',', $value) as $k) { $_sql[] = "p.field_{$id} LIKE '%|" . $this->DB->addSlashes($k) . "|%'"; } } } else { $_sql[] = $this->caches['profilefields'][$id]['pf_search_type'] == 'loose' ? "p.field_{$id} LIKE '%" . $this->DB->addSlashes($value) . "%'" : "p.field_{$id} = '" . $this->DB->addSlashes($value) . "'"; } } } } } //----------------------------------------- // Search member status type //----------------------------------------- if ($data['member_status']) { switch ($data['member_status']) { case 'banned': $_sql[] = "(m.member_banned=1)"; break; case 'spam': $_sql[] = '(' . IPSBWOptions::sql('bw_is_spammer', 'm.members_bitoptions', 'members', 'global', 'has') . ' OR val.spam_flag=1)'; break; case 'validating': $_sql[] = "(val.lost_pass=0 AND val.vid " . $this->DB->buildIsNull(false) . ")"; break; case 'incomplete': $_sql[] = "par.partial_member_id " . $this->DB->buildIsNull(false); break; case 'locked': if ($this->settings['ipb_bruteforce_attempts'] > 0) { $_sql[] = "m.failed_login_count >= " . intval($this->settings['ipb_bruteforce_attempts']); } else { $_sql[] = "m.failed_login_count > 0"; } break; default: case 'all': //----------------------------------------- // Hide partial members if showing 'all', and // we did not explicitly search //----------------------------------------- if (!count($_sql)) { $_sql[] = "par.partial_member_id " . $this->DB->buildIsNull(); } break; } } //----------------------------------------- // Return search string //----------------------------------------- return count($_sql) ? implode(" AND ", $_sql) : ''; }
/** * Parses the content */ public static function convert($k, $v) { return is_string($v) && !in_array($k, self::$noConvertFields) ? IPSText::convertCharsets($v, 'UTF-8', IPS_DOC_CHAR_SET) : $v; }
function prepare_remote_utf8_string($str) { $charset = get_local_charset(); if (strtolower($charset) == 'utf-8') { return $str; } if (is_ipb()) { return IPSText::convertCharsets($str, 'utf-8', $charset); } $str = html_entity_decode_utf8($str, true); $converted = false; if (function_exists('mb_convert_encoding') && !$converted) { $out = @mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8'); $out = @mb_convert_encoding($out, $charset, 'UTF-8'); if (mb_strlen(trim($out)) > 0) { $converted = true; } } if (function_exists('iconv') && !$converted) { $out = @iconv('UTF-8', $charset . '//TRANSLIT', $str); if ($out !== false) { $converted = true; } } if (!$converted) { $out = $str; } $out = escape_non_numerical_entities($out, $charset); return $out; }
/** * Function to resync a member's Twitter data * * @access public * @param mixed Member Data in an array form (result of IPSMember::load( $id, 'all' ) ) or a member ID * @return array Updated member data * * EXCEPTION CODES: * NO_MEMBER Member ID does not exist * NOT_LINKED Member ID or data specified is not linked to a FB profile */ public function syncMember($memberData) { //----------------------------------------- // INIT //----------------------------------------- $exProfile = array(); /* Do we need to load a member? */ if (!is_array($memberData)) { $memberData = IPSMember::load(intval($memberData), 'all'); } /* Got a member? */ if (!$memberData['member_id']) { throw new Exception('NO_MEMBER'); } /* Linked account? */ if (!$memberData['twitter_id']) { throw new Exception('NOT_LINKED'); } /* Not completed sign up ( no display name ) */ if ($memberData['member_group_id'] == $this->settings['auth_group']) { return false; } /* Thaw Options */ $bwOptions = IPSBWOptions::thaw($memberData['tc_bwoptions'], 'twitter'); /* Grab the data */ try { $this->resetApi($memberData['twitter_token'], $memberData['twitter_secret']); if ($this->isConnected()) { $user = $this->fetchUserData(); /* Load library */ if ($bwOptions['tc_s_pic']) { $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/member/photo.php', 'classes_member_photo'); $photo = new $classToLoad($this->registry); $photo->save($memberData, 'twitter'); } if ($bwOptions['tc_s_aboutme']) { $exProfile['pp_about_me'] = IPSText::getTextClass('bbcode')->stripBadWords(IPSText::convertCharsets($user['description'], 'utf-8', IPS_DOC_CHAR_SET)); } if ($bwOptions['tc_si_status'] and (isset($memberData['gbw_no_status_import']) and !$memberData['gbw_no_status_import']) and !$memberData['bw_no_status_update']) { /* Fetch timeline */ $memberData['tc_last_sid_import'] = $memberData['tc_last_sid_import'] < 1 ? 100 : $memberData['tc_last_sid_import']; $_updates = $this->fetchUserTimeline($user['id'], $memberData['tc_last_sid_import'], true); /* Got any? */ if (count($_updates)) { $update = array_shift($_updates); if (is_array($update) and isset($update['text'])) { /* Load status class */ if (!$this->registry->isClassLoaded('memberStatus')) { $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/member/status.php', 'memberStatus'); $this->registry->setClass('memberStatus', new $classToLoad(ipsRegistry::instance())); } /* Set Author */ $this->registry->getClass('memberStatus')->setAuthor($memberData); $this->registry->getClass('memberStatus')->setStatusOwner($memberData); /* Convert if need be */ if (IPS_DOC_CHAR_SET != 'UTF-8') { $update['text'] = IPSText::utf8ToEntities($update['text']); } /* Set Content */ $this->registry->getClass('memberStatus')->setContent(trim(IPSText::getTextClass('bbcode')->stripBadWords($update['text']))); /* Set as imported */ $this->registry->getClass('memberStatus')->setIsImport(1); /* Set creator */ $this->registry->getClass('memberStatus')->setCreator('twitter'); /* Can we reply? */ if ($this->registry->getClass('memberStatus')->canCreate()) { $this->registry->getClass('memberStatus')->create(); $exProfile['tc_last_sid_import'] = $update['id']; } } } } /* Allowed profile customization? */ if ($bwOptions['tc_s_bgimg'] and ($user['profile_background_image_url'] or $user['profile_background_color']) and ($this->memberData['gbw_allow_customization'] and !$this->memberData['bw_disable_customization'])) { /* remove bg images */ IPSMember::getFunction()->removeUploadedBackgroundImages($memberData['member_id']); $exProfile['pp_customization'] = serialize(array('bg_url' => $user['profile_background_image_url'], 'type' => $user['profile_background_image_url'] ? 'url' : 'color', 'bg_color' => IPSText::alphanumericalClean($user['profile_background_color']), 'bg_tile' => intval($user['profile_background_tile']))); } /* Update member */ IPSMember::save($memberData['member_id'], array('core' => array('tc_lastsync' => time()), 'extendedProfile' => $exProfile)); /* merge and return */ $memberData['tc_lastsync'] = time(); $memberData = array_merge($memberData, $exProfile); } } catch (Exception $e) { } return $memberData; }
/** * Redirect to Twitter * Exciting, isn't it. * * @access private * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://bobrdobr.ru/addext.html?url=" . urlencode($url) . '&title=' . urlencode($title); $this->registry->output->silentRedirect($url); }
/** * Return HTML content * * @param string HTML to output * @param boolean Force returned output to UTF-8 * @return @e void */ public function returnHtml($string, $returnAsUtf8 = false) { if ($string) { $this->cleanHtml($string); } /* Always return as UTF-8 */ if ($returnAsUtf8) { $string = IPSText::convertCharsets($string, IPS_DOC_CHAR_SET, "UTF-8"); } @header("Content-type: text/html;charset=" . IPS_DOC_CHAR_SET); $this->printNocacheHeaders(); print $string; exit; }
/** * Build a RSS import query * * @access public * @param mixed False on error/no entries, or an array of imported entries */ public function build($data) { /* Reset stuff */ $this->_imported = array(); $this->__usedGuids = array(); $this->__pointer = 0; $this->__map = array(); $this->errors = array(); /* Prep vars */ $final_guids = array(); $final_items = array(); if (isset($data['title'])) { $this->_titleMatch = $data['title']; } if (isset($data['content'])) { $this->_contentMatch = $data['content']; } if (isset($data['limit'])) { $this->_limit = intval($data['limit']); } /* Ensure we got stuff */ if (!$this->_limit) { $this->_limit = 50; } /* Loop through the channels */ foreach ($this->_rssClass->rss_channels as $channel_id => $channel_data) { if (is_array($this->_rssClass->rss_items[$channel_id]) and count($this->_rssClass->rss_items[$channel_id])) { /* Loop through the items in this channel */ foreach ($this->_rssClass->rss_items[$channel_id] as $item_data) { /* Item Data */ $item_data['content'] = $item_data['content'] ? $item_data['content'] : $item_data['description']; $item_data['guid'] = md5($this->_key . ($item_data['guid'] ? $item_data['guid'] : preg_replace("#\\s|\r|\n#is", "", $item_data['title'] . $item_data['link'] . $item_data['description']))); $item_data['unixdate'] = intval($item_data['unixdate']) ? intval($item_data['unixdate']) : time(); /* Convert char set? */ if ($this->_rssClass->orig_doc_type != $this->_rssClass->doc_type) { $item_data['title'] = IPSText::convertCharsets($item_data['title'], "UTF-8", IPS_DOC_CHAR_SET); $item_data['content'] = IPSText::convertCharsets($item_data['content'], "UTF-8", IPS_DOC_CHAR_SET); } /* Dates */ if ($item_data['unixdate'] < 1 or $item_data['unixdate'] > time()) { $item_data['unixdate'] = time(); } /* Error check */ if (!$item_data['title'] or !$item_data['content']) { $this->errors[] = $this->registry->getClass('class_localization')->words['_rssimportnotoc']; continue; } /* Content check? */ if ($this->_contentMatch) { if (!stristr($item_data['content'], $this->_contentMatch)) { continue; } } /* Title check? */ if ($this->_titleMatch) { if (!stristr($item_data['title'], $this->_titleMatch)) { continue; } } /* Add to array */ $items[$item_data['guid']] = $item_data; $check_guids[] = $item_data['guid']; } } } /* Check GUIDs */ if (!count($check_guids)) { $rss_error[] = $this->lang->words['im_noitems']; return false; } $this->DB->build(array('select' => 'rss_guid', 'from' => 'core_rss_imported', 'where' => "rss_foreign_key='" . $this->_key . "' AND rss_guid IN ('" . implode("','", $check_guids) . "')")); $i = $this->DB->execute(); while ($guid = $this->DB->fetch($i)) { $final_guids[$guid['rss_guid']] = $guid['rss_guid']; } /* Compare GUIDs */ $item_count = 0; foreach ($items as $guid => $data) { if (in_array($guid, $final_guids)) { continue; } else { $item_count++; /* Make sure each item has a unique date */ $final_items[$data['unixdate'] . '.' . $item_count] = $data; } } /* Sort Array */ krsort($final_items); /* Pick off last X */ $count = 1; $tmp_final_items = $final_items; $final_items = array(); foreach ($tmp_final_items as $date => $data) { $this->_imported[$date] = $data; if ($count >= $this->_limit) { break; } } /* now sort it oldest first */ ksort($this->_imported); /* add in map */ foreach ($this->_imported as $date => $data) { $this->__map[$count - 1] = $date; $count++; } reset($this->_imported); }
/** * Redirect to Twitter * Exciting, isn't it. * * @access private * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://reddit.com/submit?url=" . urlencode($url) . "&title=" . urlencode($title); $this->registry->output->silentRedirect($url); }
/** * Log in and create a brand new forum account * * @access public * @return mixed On success, an array containing a message and redirect URL * * EXCEPTION CODES: * NO_FACEBOOK_USER_LOGGED_IN System cannot detect a logged in facebook user * NO_FB_EMAIL Could not locate a facebook proxy email * CREATION_FAIL Account creation failed * ALREADY_LINKED_MEMBER The facebook UID is already linked to another IPB account */ public function loginWithNewAccount() { $loggedInUser = $this->FB()->get_loggedin_user(); if (!$loggedInUser) { throw new Exception('NO_FACEBOOK_USER_LOGGED_IN'); } /* Ensure that there is not already a linked account */ /* Now get the linked user */ $_member = IPSMember::load($loggedInUser, 'all', 'fb_uid'); if ($_member['member_id']) { throw new Exception('ALREADY_LINKED_MEMBER'); } /* Now fetch more data */ $_fbData = $this->API()->users_getInfo($loggedInUser, array('name', 'proxied_email', 'timezone', 'pic', 'pic_square', 'pic_square_with_logo', 'about_me')); $fbData = $_fbData[0]; if (!$fbData['proxied_email']) { throw new Exception('NO_FB_EMAIL'); } /* Generate BW options */ foreach (array('fbc_s_pic', 'fbc_s_avatar', 'fbc_s_status', 'fbc_s_aboutme') as $field) { $toSave[$field] = 1; } $fb_bwoptions = IPSBWOptions::freeze($toSave, 'facebook'); /* Generate FB hash */ $hash = $this->generateEmailHash($fbData['proxied_email']); $memberData = IPSMember::create(array('core' => array('name' => IPSText::convertCharsets($fbData['name'], 'utf-8', IPS_DOC_CHAR_SET), 'members_display_name' => IPSText::convertCharsets($fbData['name'], 'utf-8', IPS_DOC_CHAR_SET), 'members_created_remote' => 1, 'member_group_id' => $this->settings['fbc_mgid'] ? $this->settings['fbc_mgid'] : $this->settings['member_group'], 'email' => $fbData['proxied_email'], 'time_offset' => $fbData['timezone'], 'fb_uid' => $loggedInUser, 'fb_emailhash' => $hash), 'extendedProfile' => array('pp_about_me' => IPSText::convertCharsets($fbData['about_me'], 'utf-8', IPS_DOC_CHAR_SET), 'fb_photo' => $fbData['pic'], 'fb_photo_thumb' => $fbData['pic_square_with_logo'], 'fb_bwoptions' => $fb_bwoptions, 'avatar_location' => $fbData['pic_square'], 'avatar_type' => 'facebook')), TRUE); if (!$memberData['member_id']) { throw new Exception('CREATION_FAIL'); } /* Register with Facebook */ try { $reg = $this->API()->connect_registerUsers(json_encode(array(array('email_hash' => $hash, 'account_id' => $memberData['member_id'])))); } catch (Exception $error) { //print $error->getMessage(); exit(); } //----------------------------------------- // Update Stats //----------------------------------------- $cache = $this->cache->getCache('stats'); if ($memberData['members_display_name'] and $memberData['member_id']) { $cache['last_mem_name'] = $memberData['members_display_name']; $cache['last_mem_id'] = $memberData['member_id']; } $cache['mem_count'] += 1; $this->cache->setCache('stats', $cache, array('array' => 1, 'deletefirst' => 0)); //----------------------------------------- // New registration emails //----------------------------------------- if ($this->settings['new_reg_notify']) { $this->lang->loadLanguageFile(array('public_register'), 'core'); $date = $this->registry->class_localization->getDate(time(), 'LONG', 1); IPSText::getTextClass('email')->getTemplate('admin_newuser'); IPSText::getTextClass('email')->buildMessage(array('DATE' => $date, 'MEMBER_NAME' => $memberData['members_display_name'])); IPSText::getTextClass('email')->subject = $this->lang->words['new_registration_email1'] . $this->settings['board_name']; IPSText::getTextClass('email')->to = $this->settings['email_in']; IPSText::getTextClass('email')->sendMail(); } /* Here, so log us in!! */ return $this->_login()->loginWithoutCheckingCredentials($memberData['member_id'], TRUE); }
/** * Rebuild the RSS Stream cache * * @param mixed $rss_import_id ID of the stream to import * @param bool $return Set to true to return true/false * @param bool $id_is_array Set to true if the first paramter is an array of ids * @return mixed */ public function rssImportRebuildCache($rss_import_id, $return = true, $id_is_array = false) { /* INIT */ $errors = array(); $affected_forum_ids = array(); $rss_error = array(); $rss_import_ids = array(); $items_imported = 0; /* Check the ID */ if (!$rss_import_id) { $rss_import_id = $this->request['rss_import_id'] == 'all' ? 'all' : intval($this->request['rss_import_id']); } /* No ID Found */ if (!$rss_import_id) { $this->registry->output->global_error = $this->lang->words['im_noid']; $this->rssImportOverview(); return; } /* Create an array of ids */ if ($id_is_array == 1) { $rss_import_ids = explode(",", $rss_import_id); } /* Load the classes we need */ if (!$this->classes_loaded) { /* Get the RSS Class */ if (!is_object($this->class_rss)) { $classToLoad = IPSLib::loadLibrary(IPS_KERNEL_PATH . 'classRss.php', 'classRss'); $this->class_rss = new $classToLoad(); $this->class_rss->rss_max_show = 100; } /* Get the post class */ require_once IPSLib::getAppDir('forums') . '/sources/classes/post/classPost.php'; /*noLibHook*/ $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . '/sources/classes/post/classPostForms.php', 'classPostForms', 'forums'); $this->post = new $classToLoad($this->registry); /* Load the mod libarry */ if (!$this->func_mod) { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . '/sources/classes/moderate.php', 'moderatorLibrary', 'forums'); $this->func_mod = new $classToLoad($this->registry); } $this->classes_loaded = 1; } /* INIT Forums */ if (!is_array($this->registry->class_forums->forum_by_id) or !count($this->registry->class_forums->forum_by_id)) { $this->registry->class_forums->forumsInit(); } /* Sort out which IDs to load.. */ if ($rss_import_id == 'all') { $where = 'rss_import_enabled=1'; // Update only enabled ones! } elseif ($id_is_array == 1) { $where = 'rss_import_id IN (' . implode(',', $rss_import_ids) . ')'; } else { $where = 'rss_import_id=' . $rss_import_id; } /* Query the RSS imports */ $this->DB->build(array('select' => '*', 'from' => 'rss_import', 'where' => $where)); $outer = $this->DB->execute(); /* Loop through and build cache */ while ($row = $this->DB->fetch($outer)) { /* Skip non-existent forums - bad stuff happens */ if (empty($this->registry->class_forums->forum_by_id[$row['rss_import_forum_id']])) { continue; } /* Allowing badwords? */ IPSText::getTextClass('bbcode')->bypass_badwords = $row['rss_import_allow_html']; /* Set this import's doctype */ $this->class_rss->doc_type = strtoupper(IPS_DOC_CHAR_SET); /* Set this import's authentication */ $this->class_rss->auth_req = $row['rss_import_auth']; $this->class_rss->auth_user = $row['rss_import_auth_user']; $this->class_rss->auth_pass = $row['rss_import_auth_pass']; /* Clear RSS object's error cache first */ $this->class_rss->errors = array(); $this->class_rss->rss_items = array(); /* Reset the rss count as this is a new feed */ $this->class_rss->rss_count = 0; $this->class_rss->rss_max_show = $row['rss_import_pergo']; /* Parse RSS */ $this->class_rss->parseFeedFromUrl($row['rss_import_url']); /* Check for errors */ if (is_array($this->class_rss->errors) and count($this->class_rss->errors)) { $rss_error = array_merge($rss_error, $this->class_rss->errors); continue; } if (!is_array($this->class_rss->rss_channels) or !count($this->class_rss->rss_channels)) { $rss_error[] = sprintf($this->lang->words['im_noopen'], $row['rss_import_url']); continue; } /* Update last check time */ $this->DB->update('rss_import', array('rss_import_last_import' => IPS_UNIX_TIME_NOW), 'rss_import_id=' . $row['rss_import_id']); /* Apparently so: Parse feeds and check for already imported GUIDs */ $final_items = array(); $items = array(); $check_guids = array(); $final_guids = array(); $count = 0; if (!is_array($this->class_rss->rss_items) or !count($this->class_rss->rss_items)) { $rss_error[] = $row['rss_import_url'] . $this->lang->words['im_noimport']; continue; } /* Loop through the channels */ foreach ($this->class_rss->rss_channels as $channel_id => $channel_data) { if (is_array($this->class_rss->rss_items[$channel_id]) and count($this->class_rss->rss_items[$channel_id])) { /* Loop through the items in this channel */ foreach ($this->class_rss->rss_items[$channel_id] as $item_data) { /* Item Data */ $item_data['content'] = $item_data['content'] ? $item_data['content'] : $item_data['description']; $item_data['guid'] = md5($row['rss_import_id'] . ($item_data['guid'] ? $item_data['guid'] : preg_replace('#\\s|\\r|\\n#is', "", $item_data['title'] . $item_data['link'] . $item_data['description']))); $item_data['unixdate'] = intval($item_data['unixdate']) ? intval($item_data['unixdate']) : IPS_UNIX_TIME_NOW; /* If feed charset doesn't match original, we converted to utf-8 and need to convert back now */ if ($this->class_rss->doc_type != $this->class_rss->orig_doc_type) { $item_data['title'] = IPSText::convertCharsets($item_data['title'], "UTF-8", IPS_DOC_CHAR_SET); $item_data['content'] = IPSText::convertCharsets($item_data['content'], "UTF-8", IPS_DOC_CHAR_SET); } /* Error check */ if (!$item_data['title'] or !$item_data['content']) { $rss_error[] = sprintf($this->lang->words['im_notitle'], $item_data['title']); continue; } /* Dates */ if ($item_data['unixdate'] < 1) { $item_data['unixdate'] = IPS_UNIX_TIME_NOW; } else { if ($item_data['unixdate'] > IPS_UNIX_TIME_NOW) { $item_data['unixdate'] = IPS_UNIX_TIME_NOW; } } /* Add to array */ $items[$item_data['guid']] = $item_data; $check_guids[] = $item_data['guid']; } } } /* Check GUIDs */ if (!count($check_guids)) { $rss_error[] = $this->lang->words['im_noitems']; continue; } $this->DB->build(array('select' => '*', 'from' => 'rss_imported', 'where' => "rss_imported_guid IN ('" . implode("','", $check_guids) . "')")); $this->DB->execute(); while ($guid = $this->DB->fetch()) { $final_guids[$guid['rss_imported_guid']] = $guid['rss_imported_guid']; } /* Compare GUIDs */ $item_count = 0; foreach ($items as $guid => $data) { if (in_array($guid, $final_guids)) { continue; } else { $item_count++; /* Make sure each item has a unique date */ $final_items[$data['unixdate'] . $item_count] = $data; } } /* Sort Array */ krsort($final_items); /* Pick off last X */ $count = 1; $tmp_final_items = $final_items; $final_items = array(); foreach ($tmp_final_items as $date => $data) { $final_items[$date] = $data; if ($count >= $row['rss_import_pergo']) { break; } $count++; } /* Anything left? */ if (!count($final_items)) { continue; } /* Figure out MID */ $member = $this->DB->buildAndFetch(array('select' => 'member_id, name, members_display_name, ip_address', 'from' => 'members', 'where' => "member_id={$row['rss_import_mid']}")); if (!$member['member_id']) { continue; } /* Set member in post class */ $this->post->setAuthor($member['member_id']); $this->post->setForumData($this->registry->getClass('class_forums')->forum_by_id[$row['rss_import_forum_id']]); $this->post->setBypassPermissionCheck(true); $this->post->setForumID($row['rss_import_forum_id']); /* Make 'dem posts */ $affected_forum_ids[] = $row['rss_import_forum_id']; /* Get editor */ $classToLoad = IPSLib::loadLibrary(IPS_ROOT_PATH . 'sources/classes/editor/composite.php', 'classes_editor_composite'); $editor = new $classToLoad(); /* Force RTE */ $editor->setForceRte(true); $editor->setRteEnabled(true); $editor->setLegacyMode(false); foreach ($final_items as $topic_item) { /* Fix & */ $topic_item['title'] = str_replace('&', '&', $topic_item['title']); $topic_item['title'] = str_replace(array("\r", "\n"), ' ', $topic_item['title']); $topic_item['title'] = str_replace(array("<br />", "<br>"), ' ', $topic_item['title']); $topic_item['title'] = trim($topic_item['title']); $topic_item['title'] = strip_tags($topic_item['title']); $topic_item['title'] = IPSText::parseCleanValue($topic_item['title']); /* Fix up &reg; */ $topic_item['title'] = str_replace('&reg;', '®', $topic_item['title']); if ($row['rss_import_topic_pre']) { $topic_item['title'] = str_replace(' ', ' ', str_replace('&nbsp;', ' ', $row['rss_import_topic_pre'])) . ' ' . $topic_item['title']; } $this->post->setTopicTitle(IPSText::mbsubstr($topic_item['title'], 0, $this->settings['topic_title_max_len'])); $this->post->setDate($topic_item['unixdate']); $this->post->setPublished($row['rss_import_topic_hide'] ? false : true); $this->post->setPublishedRedirectSkip(true); /* Clean up.. */ $topic_item['content'] = preg_replace("#<br />(\r)?\n#is", "<br />", $topic_item['content']); if (!$row['rss_import_allow_html']) { $topic_item['content'] = stripslashes($topic_item['content']); $post_content = $editor->process($topic_item['content']); } else { $post_content = stripslashes($topic_item['content']); } /* Add in Show link... */ if ($row['rss_import_showlink'] and $topic_item['link']) { $the_link = str_replace('{url}', trim($topic_item['link']), $row['rss_import_showlink']); $the_link = "<br /><br />" . stripslashes($the_link); $post_content .= $the_link; } /* Make sure HTML mode is enabled correctly */ $this->request['post_htmlstatus'] = 1; /* Prevent invalid img extensions from breaking */ $_hack = $this->settings['img_ext']; $_zack = $this->settings['max_quotes_per_post']; $this->settings['img_ext'] = null; $this->settings['max_quotes_per_post'] = 500; $tmpForum = $this->post->getForumData(); $tmpAuthor = $this->post->getAuthor(); $this->post->setForumData(array_merge($tmpForum, array('use_html' => 1))); $this->post->setAuthor(array_merge($tmpAuthor, array('g_dohtml' => 1))); $this->post->setPostContentPreFormatted($post_content); /* Insert */ try { $this->post->addTopic(); } catch (Exception $e) { } /* Reset */ $this->settings['img_ext'] = $_hack; $this->settings['max_quotes_per_post'] = $_zack; $this->request['post_htmlstatus'] = 0; $this->post->setForumData($tmpForum); $this->post->setAuthor($tmpAuthor); if (!$row['rss_import_topic_open']) { if (!$this->modLibrary) { $classToLoad = IPSLib::loadLibrary(IPSLib::getAppDir('forums') . '/sources/classes/moderate.php', 'moderatorLibrary', 'forums'); $this->modLibrary = new $classToLoad($this->registry); } $this->modLibrary->init($row['rss_import_forum_id']); $this->modLibrary->topicClose($this->post->getTopicData('tid')); } /* Insert GUID match */ $this->DB->insert('rss_imported', array('rss_imported_impid' => $row['rss_import_id'], 'rss_imported_guid' => $topic_item['guid'], 'rss_imported_tid' => $this->post->getTopicData('tid'))); $this->import_count++; } } /* Uncomment when testing imports */ //$this->DB->delete( 'rss_imported', '1=1'); /* Recount Stats */ if (count($affected_forum_ids)) { foreach ($affected_forum_ids as $fid) { $this->func_mod->forumRecount($fid); } $this->cache->rebuildCache('stats', 'global'); } /* Return */ if ($return) { $this->registry->output->global_message = $this->lang->words['im_recached']; if (count($rss_error)) { $this->registry->output->global_message .= "<br />" . implode("<br />", $rss_error); } $this->rssImportOverview(); return; } else { return TRUE; } }
/** * Extract: Parse RSS document from URL * * @param string URI * @return @e boolean */ public function parseFeedFromUrl($feed_location) { //----------------------------------------- // Load file management class //----------------------------------------- require_once IPS_KERNEL_PATH . '/classFileManagement.php'; /*noLibHook*/ $this->classFileManagement = new classFileManagement(); $this->classFileManagement->use_sockets = $this->use_sockets; $this->classFileManagement->auth_req = $this->auth_req; $this->classFileManagement->auth_user = $this->auth_user; $this->classFileManagement->auth_pass = $this->auth_pass; $this->classFileManagement->userAgent = $this->userAgent; //------------------------------- // Reset arrays //------------------------------- $this->rss_items = array(); $this->rss_channels = array(); //------------------------------- // Get data //------------------------------- $data = $this->classFileManagement->getFileContents($feed_location); if (count($this->classFileManagement->errors)) { $this->errors = $this->classFileManagement->errors; return FALSE; } $_foundIn = ''; if (preg_match("#encoding=[\"'](\\S+?)[\"']#si", $data, $matches)) { $this->orig_doc_type = strtoupper($matches[1]); $_foundIn = 'encoding'; } if (!$this->orig_doc_type and preg_match("#charset=(\\S+?)#si", $data, $matches)) { $this->orig_doc_type = strtoupper($matches[1]); $_foundIn = 'charset'; } //----------------------------------------- // If feed charset isn't supportd by XML lib, // convert to UTF-8 // Edit - ALWAYS use utf-8. A wide html entity (‘) is // valid in iso-8859-1 output because it is an entity, however // the XML library tries to convert all entities to their appropriate // character which corrupts it. // @link http://community.invisionpower.com/tracker/issue-33588-rss-import-character-issue // @link http://us.php.net/manual/en/function.xml-set-character-data-handler.php#35065 //----------------------------------------- $supported_encodings = array("UTF-8"); $charset = ($this->orig_doc_type and in_array($this->orig_doc_type, $supported_encodings)) ? $this->orig_doc_type : "UTF-8"; if ($this->convert_charset and $data) { if ($charset != $this->orig_doc_type) { $data = IPSText::convertCharsets($data, $this->orig_doc_type, $charset); # Replace any char-set= data if ($_foundIn == 'encoding') { $data = preg_replace("#encoding=[\"'](\\S+?)[\"']#si", "encoding=\"" . $charset . "\"", $data); } else { $data = preg_replace("#charset=(\\S+?)#si", "charset=" . $charset, $data); } } } /* Parse */ $this->_parse($data, $charset); return TRUE; }
/** * Redirect to Google * Exciting, isn't it. * * @param string Plug in */ public function share($title, $url) { $title = IPSText::convertCharsets($title, IPS_DOC_CHAR_SET, 'utf-8'); $url = "http://www.google.com/sharer.php?u=" . urlencode($url); $this->registry->output->silentRedirect($url); }
/** * Callback function for array_walk_recursive to convert each entry * * @param mixed Value * @param string Array key * @return void */ public static function arrayWalkCallbackConvert(&$value, $key) { if (is_string($value)) { $value = IPSText::convertCharsets($value, IPS_DOC_CHAR_SET, "UTF-8"); } }
/** * Import files from disk * * @param string Directory to look in * @param int Language ID to import into * @param array [Only import these files] * @param boolean [Perform character set translation from UTF-8] * @return array List of files successfully imported */ private function _importFromDisk($mainDir, $langId, $onlyTheseFiles = array(), $convertCharSet = false) { /* INIT */ $imported = array(); $lang_entries = array(); $js_entries = array(); $counts = array(); /* Start looping */ if (is_dir($mainDir)) { $dh = opendir($mainDir); /* Ensure it has a trailing slash */ if (substr($mainDir, -1) != '/') { $mainDir .= '/'; } while ($f = readdir($dh)) { if ($f[0] == '.' || $f == 'index.html') { continue; } /* Skipping? */ if (is_array($onlyTheseFiles) and count($onlyTheseFiles) and !in_array($f, $onlyTheseFiles)) { continue; } if (preg_match('#^\\S+?_\\S+?\\.php$#', $f)) { //----------------------------------------- // INIT //----------------------------------------- $updated = 0; $inserted = 0; $app = preg_replace('#^([^_]+?)_(\\S+?)\\.php$#', "\\1", $f); $word_pack = preg_replace('#^([^_]+?)_(\\S+?)\\.php$#', "\\2", $f); $lang = array(); $db_lang = array(); $counts[$f] = array(); if (!is_file($mainDir . $f)) { continue; } /* Require the file */ require $mainDir . $f; /*noLibHook*/ //----------------------------------------- // Loop //----------------------------------------- foreach ($lang as $k => $v) { //----------------------------------------- // Build db array //----------------------------------------- $db_array = array('lang_id' => $langId, 'word_app' => $app, 'word_pack' => $word_pack, 'word_key' => $k, 'word_custom' => IPSText::convertCharsets($v, 'UTF-8', IPS_DOC_CHAR_SET), 'word_js' => 0); //----------------------------------------- // If cached, get from cache //----------------------------------------- if ($lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']]) { $lang_entry = $lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]; } else { $this->DB->build(array('select' => '*', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$langId} AND word_app='{$db_array['word_app']}' AND word_pack='{$db_array['word_pack']}'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $lang_entries[$r['lang_id']][$r['word_app']][$r['word_pack']][$r['word_key']] = $r; } if ($lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]) { $lang_entry = $lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]; } } /* Finish off */ $db_array['word_default'] = $lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]['word_default']; $db_array['word_default_version'] = $lang_entries[$langId][$db_array['word_app']][$db_array['word_pack']][$db_array['word_key']]['word_default_version']; $db_array['word_custom_version'] = IPB_LONG_VERSION; //----------------------------------------- // If there is no new custom lang bit to insert // don't delete what is already there. //----------------------------------------- if (!$db_array['word_custom']) { unset($db_array['word_custom']); } //----------------------------------------- // Lang bit already exists, update //----------------------------------------- if ($lang_entry['word_id']) { //----------------------------------------- // Don't update default version //----------------------------------------- unset($db_array['word_default_version']); $counts[$f]['updates']++; $this->DB->update('core_sys_lang_words', $db_array, "word_id={$lang_entry['word_id']}"); } else { if (!$lang_entry['word_id']) { $counts[$f]['inserts']++; $this->DB->insert('core_sys_lang_words', $db_array); } } } } else { if (preg_match('/(\\.js)$/', $f)) { $_js_word_pack = ''; if ($f == 'ipb.lang.js') { $_js_word_pack = 'public_js'; } else { if ($f == 'acp.lang.js') { $_js_word_pack = 'admin_js'; } } //----------------------------------------- // If not cached, get it //----------------------------------------- if (!$js_entries[$langId][$_js_word_pack]) { $this->DB->build(array('select' => '*', 'from' => 'core_sys_lang_words', 'where' => "lang_id={$langId} AND word_pack='{$_js_word_pack}'")); $this->DB->execute(); while ($r = $this->DB->fetch()) { $js_entries[$r['word_pack']][$r['word_key']] = $r; } } //----------------------------------------- // Delete current words for this app and word pack //----------------------------------------- $this->DB->delete('core_sys_lang_words', 'lang_id=' . $langId . " AND word_app='core' AND word_pack='" . $_js_word_pack . "'"); //----------------------------------------- // Get each line //----------------------------------------- $js_file = file($mainDir . $f); //----------------------------------------- // Loop through lines and import //----------------------------------------- foreach ($js_file as $r) { //----------------------------------------- // preg_match what we want //----------------------------------------- preg_match('#ipb\\.lang\\[\'(.+?)\'\\](.+?)= ["\'](.+?)["\'];#', $r, $matches); //----------------------------------------- // Valid? //----------------------------------------- if ($matches[1] && $matches[3]) { $counts[$f]['inserts']++; $insert = array('lang_id' => $langId, 'word_app' => 'core', 'word_pack' => $_js_word_pack, 'word_key' => $matches[1], 'word_custom' => IPSText::convertCharsets($matches[3], 'UTF-8', IPS_DOC_CHAR_SET), 'word_js' => 1, 'word_default' => $js_entries[$_js_word_pack][$matches[1]]['word_default'], 'word_default_version' => $js_entries[$_js_word_pack][$matches[1]]['word_default_version'], 'word_custom_version' => IPB_LONG_VERSION); $this->DB->insert('core_sys_lang_words', $insert); } } } } } closedir($dh); } return $counts; }
/** * Parse a "part" * * @param stdClass As returned by mailMime_decode */ protected function _parsePart($part) { /* Some clients use uppercase, but we check by lowercase */ $part->ctype_primary = strtolower($part->ctype_primary); $part->ctype_secondary = strtolower($part->ctype_secondary); /* Make sure .txt files get attached as .txt files */ if ($part->ctype_primary == 'text' and $part->disposition == 'attachment') { $part->ctype_primary = 'unknown'; $part->ctype_secondary = 'unknown'; } /* What is this? */ switch ($part->ctype_primary) { /* Multipart - means there's more than one part to this part */ case 'multipart': // "Alternative" means there's more than one way to interpret this part, usually means we have plain text and HTML varients if ($part->ctype_secondary == 'alternative') { // First, check if we have html and plaintext if (!$this->alternative) { $haveHtml = false; $havePlain = false; foreach ($part->parts as $p) { if ($p->ctype_primary == 'text') { if ($p->ctype_secondary == 'html') { $haveHtml = true; } elseif ($p->ctype_secondary == 'plain') { $havePlain = true; } } } } // This means we need to decide which of the parts we prefer $preferredPart = array_shift($part->parts); foreach ($part->parts as $p) { if ($this->_isBetter($preferredPart, $p)) { $preferredPart = $p; } } // What did we choose? if (!$this->alternative and $haveHtml and $havePlain) { if ($preferredPart->ctype_secondary == 'html') { $this->alternative = 'h'; } elseif ($preferredPart->ctype_secondary == 'html') { $this->alternative = 'p'; } } return $this->_parsePart($preferredPart); } // Otherwise, parse all parts foreach ($part->parts as $p) { $this->_parsePart($p); } return; /* Text */ /* Text */ case 'text': $body = $part->body; $this->original_message .= $body; //----------------------------------------- // Add <br /> tags //----------------------------------------- if ($part->ctype_secondary != 'html') { $body = nl2br($body); } //----------------------------------------- // Convert the charset if necessary //----------------------------------------- if (isset($part->ctype_parameters['charset']) and $part->ctype_parameters['charset'] != IPS_DOC_CHAR_SET) { // Sometimes the charset will be "xx-ascii" which isn't what we want if (strpos($part->ctype_parameters['charset'], 'ascii') !== FALSE) { //$part->ctype_parameters['charset'] = 'iso-8859-1'; } // Convert $body = IPSText::convertCharsets($body, $part->ctype_parameters['charset'], IPS_DOC_CHAR_SET); $part->ctype_parameters['charset'] = IPS_DOC_CHAR_SET; } //----------------------------------------- // Parse > style quotes //----------------------------------------- $quoteLevel = 0; $quotableLine = ''; foreach (explode("<br />", $body) as $k => $line) { $line = trim($line); // We only need to check for opening/closing quotes if this line actually has content if ($line) { // If this line starts with less >s than we're expecting, add a close quote tag // Note we strip whitespace when doing this check as sometimes you'll get ">>>" and other times "> > >" if (substr(str_replace(' ', '', $line), 0, $quoteLevel) != str_repeat('>', $quoteLevel)) { $quoteLevel--; $line = substr($line, $quoteLevel); $line .= '[/quote]<br />'; } else { // Strip out the >s that we're expecting // Note this has to use the regex as sometimes you'll get ">>>" and other times "> > >" $line = trim(preg_replace('/^(>\\s?){' . $quoteLevel . '}/', '', $line)); // If, after stripping the expected number of >s, the line still starts with a >, then open a quote tag if (substr($line, 0, 1) == '>') { $quoteLevel++; $line = substr($line, 1); // If we have content to add into the tag, do that, otherwise, a blank quote is fine if ($quotableLine) { $this->message = substr($this->message, 0, strrpos($this->message, $quotableLine)); $this->message .= "[quote collapse='1' name='" . str_replace(array("\r", "\n"), ' ', $quotableLine) . "']"; } else { $this->message .= "[quote collapse='1']"; } } } // Save the content of this line so that if a quote starts on the next line, we can put it in the header of that quote // Only do this if the line ends with a colon (i.e. "On x, y wrote:") and it doesn't contain any quote tags we've added $quotableLine = ''; if (substr($line, -1) == ':' and strpos($line, '[') === FALSE) { $quotableLine = $line; } } $this->message .= $line . '<br />'; } if ($quoteLevel) { for ($i = 0; $i < $quoteLevel; $i++) { $this->message .= '[/quote]'; } } //----------------------------------------- // Parse HTML block quotes //----------------------------------------- /* Loop */ preg_match_all('/<blockquote.+?>/s', $this->message, $matches); while (!empty($matches) and !empty($matches[0])) { $m = $matches[0][0]; // Get all the content before the quote $stripped = substr($this->message, 0, strpos($this->message, $m)); // Knock off any breaks or closed divs after it $stripped = trim(str_replace('</div>', '', $stripped)); $stripped = preg_replace('/((<br(\\s*\\/)?>| )*$)/s', '', $stripped); // Now scan back until we hit some other html $pos = strrpos($stripped, '>') + 1; $stripped = trim(substr($stripped, $pos)); // If it's an acceptable header, use it if (substr($stripped, -1, 1) == ':') { // Chop it out $this->message = substr_replace($this->message, '', strpos($this->message, $stripped), strlen($stripped)); // We have to encode the header so future tags don't replace it $stripped = '{{QUOTE-ENCODE:' . base64_encode($stripped) . '}}'; // Replace the blockquote $this->message = substr_replace($this->message, "[quote collapse='1' name='{$stripped}']", strpos($this->message, $m), strlen($m)); } else { // Replace the blockquote $this->message = substr_replace($this->message, "[quote collapse='1']", strpos($this->message, $m), strlen($m)); } // Do the scan again preg_match_all('/<blockquote.+?>/s', $this->message, $matches); } /* Decode the quote headers we made */ $this->message = preg_replace_callback('/{{QUOTE-ENCODE:(.+?)}}/', create_function('$m', 'return str_replace( array( "\\r", "\\n" ), " ", base64_decode( $m[1] ) );'), $this->message); /* Add in closing [/quote] tags */ $this->message = preg_replace('/<\\/blockquote>/', '[/quote]', $this->message); /* Check we haven't ended up with any blank quotes */ preg_match_all('/\\[quote.+?\\](.+?)\\[\\/quote\\]/s', $this->message, $matches); foreach ($matches[0] as $k => $m) { if (!trim(strip_tags($matches[1][$k]))) { $this->message = str_replace($m, '', $this->message); } } //----------------------------------------- // Quote out "Forwarded Message" //----------------------------------------- if (preg_match('/-{10,}\\s+(.+?)\\s-{10,}/', $this->message, $matches)) { $this->message = str_replace($matches[0], "[quote collapse='1']", $this->message); $this->message .= '[/quote]'; } //----------------------------------------- // Look for common quote encapsulation methods //----------------------------------------- if (strpos($this->message, 'OLK_SRC_BODY_SECTION') !== false) { if (preg_match('/<span id=["\']OLK_SRC_BODY_SECTION[\'"]>/ims', $this->message, $matches)) { $this->message = str_replace($matches[0], "[quote collapse='1']{$matches[0]}", $this->message); if (strpos($this->message, '</body>') !== false) { $this->message = str_replace('</body>', "[/quote]</body>", $this->message); } else { $this->message .= '[/quote]'; } } } if (strpos($this->message, 'MsoNormal') !== false) { if (preg_match('/<div style=["\'].+?border-top:.+?[\'"]>.*?<p class=["\']MsoNormal["\']>(.+)<\\/div>/ims', $this->message, $matches)) { $this->message = str_replace($matches[0], "[quote collapse='1']{$matches[0]}[/quote]", $this->message); } } // This code does work, however: // --Differing email clients have differing formats, so it's not reliable // --There can be cases where you have [quote collapse='1' name='On date, at time, so and so wrote:'] already, which results in [quote name='[quote ...]'], breaking the parsing /*if( preg_match( '/\bon\s+?.+?,\s*?at.+?,\s*?' . $this->settings['board_name'] . '.+?' . $this->settings['email_out'] . '.+?wrote:/ims', $this->message, $matches ) ) { //----------------------------------------- // If there's an opening <div> right after this, go there instead // but only if we're not going to strip quotes (otherwise we get a stray "blah blah said:" line) //----------------------------------------- if( strpos( $this->message, "<div>", strpos( $this->message, $matches[0] ) ) !== false ) { $matches[0] = substr( $this->message, strpos( $this->message, $matches[0] ), strpos( $this->message, "<div>", strpos( $this->message, $matches[0] ) ) - strpos( $this->message, $matches[0] ) + 5 ); $this->message = str_replace( $matches[0], "{$matches[0]}[quote collapse='1']", $this->message ); $this->message = preg_replace( "/<\/div>\s*?<\/body>/", "[/quote]</div></body>", $this->message ); } else { $this->message = str_replace( $matches[0], "{$matches[0]}[quote collapse='1']", $this->message ); if( strpos( $this->message, '</body>' ) !== false ) { $this->message = str_replace( '</body>', "[/quote]</body>", $this->message ); } else { $this->message .= '[/quote]'; } } }*/ /* Are we missing any closing tags? */ $_opening = substr_count($this->message, '[quote '); $_closing = substr_count($this->message, '[/quote]'); if ($_opening > $_closing) { for ($i = $_opening; $i < $_closing; $i++) { $this->message .= '[/quote]'; } } //----------------------------------------- // Parse the quote tag //----------------------------------------- //$this->message = preg_replace( "/\[quote collapse='(.*?)'\]/ims", "<blockquote class='ipsBlockquote' data-collapsed='\\1'>", $this->message ); //$this->message = str_replace( "[/quote]", "</blockquote>", $this->message ); /* Parse BBCode */ IPSText::getTextClass('bbcode')->parse_html = 0; IPSText::getTextClass('bbcode')->parse_nl2br = 1; IPSText::getTextClass('bbcode')->parse_smilies = 1; IPSText::getTextClass('bbcode')->parse_bbcode = 1; IPSText::getTextClass('bbcode')->parsing_section = 'support'; $this->message = IPSText::getTextClass('bbcode')->parseSingleBbcodes($this->message, 'display', 'quote'); return; /* Attachments */ /* Attachments */ default: if ($part->ctype_primary == '_text') { $part->ctype_primary = 'text'; } $mime = "{$part->ctype_primary}/{$part->ctype_secondary}"; $name = $part->ctype_parameters['name'] ? $part->ctype_parameters['name'] : $part->d_parameters['filename']; $name_parts = explode('.', $name); $ext = array_pop($name_parts); $content = "{ATTACHMENT WITH EXTENSION: {$ext}}"; if (isset($this->types[$ext]) and $this->types[$ext]['atype_post']) { /* Create the file */ $masked_name = md5(uniqid('email')) . "-{$name}"; while (is_file($this->settings['upload_dir'] . "/{$masked_name}")) { $masked_name = md5(uniqid('email') . microtime()) . "-{$name}"; } file_put_contents($this->settings['upload_dir'] . "/{$masked_name}", $part->body); /* Store attachment data */ $this->akey++; $this->attachments[$this->akey] = array('attach_ext' => $ext, 'attach_file' => $name, 'attach_location' => $masked_name, 'attach_is_image' => $part->ctype_primary == 'image' ? 1 : 0, 'attach_date' => time(), 'attach_filesize' => $part->d_parameters['size']); $content = "{ATTACHMENT:{$this->akey}}"; break; } $addedContent = FALSE; if (isset($part->disposition) and $part->disposition == 'inline') { $contentId = trim($part->headers['content-id'], '<>'); if (strpos($this->message, $contentId) !== FALSE) { switch ($part->ctype_primary) { case 'image': $this->message = preg_replace("/<img.+?src=['\"]cid:{$contentId}['\"].*?>/", $content, $this->message); $addedContent = TRUE; break; } } } if (!$addedContent) { $this->message .= $content; } return; } }
/** * Completes the connection * * @access public * @return redirect * */ public function finishLogin() { /* From reg flag */ if ($_REQUEST['code']) { /* Reset api to ensure user is not logged in */ $this->resetApi(); /* Ensure URL is correct */ $_urlExtra = ''; if ($_REQUEST['key']) { $_urlExtra .= '&key=' . $_REQUEST['key']; } if ($_REQUEST['reg']) { $_urlExtra .= '®=1'; } /* Update callback url */ $this->_api->setVariable('authorize_callback_uri', VKONTAKTE_CALLBACK . $_urlExtra); /* Generate oAuth token */ $rToken = $this->_api->getAccessToken(); if (is_string($rToken)) { try { $oAuthSession = $this->_api->getSession(); $r = $this->_api->api('getProfiles', 'GET', array('uids' => $oAuthSession['user_id'], 'fields' => 'uid,first_name,last_name,nickname,photo,photo_medium,photo_big,timezone,sex,nickname,activity')); $_userData = array_pop($r['response']); } catch (Exception $e) { } /* A little gymnastics */ $this->_userData = $_userData; $this->_userData['photo'] = $_userData['photo_big']; /* Got a member linked already? */ $_member = IPSMember::load($_userData['uid'], 'all', 'vk_uid'); if ($_member['member_id']) { $memberData = $_member; /* Ensure user's row is up to date */ IPSMember::save($memberData['member_id'], array('core' => array('vk_token' => $rToken))); /* Here, so log us in!! */ /* changed by denchu 26/12/12 */ $r = $this->_login()->loginWithoutCheckingCredentials($memberData['member_id'], TRUE); if (is_array($r)) { if (isset($r[1])) { $this->registry->getClass('output')->redirectScreen($r[0], $r[1]); $this->registry->getClass('output')->silentRedirect($r[1]); } else { $this->registry->getClass('output')->silentRedirect($r[0]); } } elseif (!$r) { throw new Exception('LINKED_MEMBER_LOGIN_FAIL'); } else { $this->registry->getClass('output')->silentRedirect($this->settings['base_url']); } } else { /* No? Create a new member */ foreach (array('vc_s_pic', 'vc_s_status') as $field) { $toSave[$field] = 1; } $vk_bwoptions = IPSBWOptions::freeze($toSave, 'vkontakte'); $safeName = IPSText::convertCharsets($_userData['first_name'] . ' ' . $_userData['last_name'], 'utf-8', IPS_DOC_CHAR_SET); $displayName = $this->settings['fb_realname'] == 'enforced' ? $safeName : ''; //$displayName = ( ! $this->settings['auth_allow_dnames'] ) ? $safeName : FALSE; /* Make sure usernames are safe */ if ($this->settings['username_characters']) { $check_against = preg_quote($this->settings['username_characters'], "/"); $check_against = str_replace('\\-', '-', $check_against); $safeName = preg_replace('/[^' . $check_against . ']+/i', '', $safeName); } if (IPSText::mbstrlen($safeName) > $this->settings['max_user_name_length']) { $safeName = mb_substr(IPSText::convertCharsets($_userData['last_name'], 'utf-8', IPS_DOC_CHAR_SET), 0, $this->settings['max_user_name_length'], 'UTF-8'); } /* Check ban filters? */ if (IPSMember::isBanned('name', $safeName)) { $this->registry->output->showError('you_are_banned', 1090003); } /* From reg, so create new account properly */ $toSave = array('core' => array('name' => $safeName, 'members_display_name' => $displayName, 'members_created_remote' => 1, 'member_group_id' => $this->settings['vk_mgid'] ? $this->settings['vk_mgid'] : $this->settings['member_group'], 'email' => '', 'vk_uid' => $_userData['uid'], 'time_offset' => $_userData['timezone'], 'vk_token' => $rToken), 'extendedProfile' => array('vk_bwoptions' => $vk_bwoptions)); $memberData = IPSMember::create($toSave, TRUE, FALSE, TRUE); if (!$memberData['member_id']) { throw new Exception('CREATION_FAIL'); } /* Sync up photo */ $this->syncMember($memberData['member_id']); $pmember = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'members_partial', 'where' => "partial_member_id=" . $memberData['member_id'])); if ($pmember['partial_member_id']) { $this->registry->getClass('output')->silentRedirect($this->settings['base_url'] . 'app=core&module=global§ion=register&do=complete_login&mid=' . $memberData['member_id'] . '&key=' . $pmember['partial_date']); } else { /* Already got a display name */ if ($displayName) { /* Here, so log us in!! */ /* changed by denchu 26/12/12*/ $r = $this->_login()->loginWithoutCheckingCredentials($memberData['member_id'], TRUE); IPSLib::runMemberSync('onCompleteAccount', $memberData); if ($this->settings['new_reg_notify']) { $this->registry->class_localization->loadLanguageFile(array('public_register'), 'core'); IPSText::getTextClass('email')->setPlainTextTemplate(IPSText::getTextClass('email')->getTemplate("admin_newuser")); IPSText::getTextClass('email')->buildMessage(array('DATE' => $this->registry->getClass('class_localization')->getDate(time(), 'LONG', 1), 'LOG_IN_NAME' => $safeFBName, 'EMAIL' => $_userData['email'], 'IP' => $this->member->ip_address, 'DISPLAY_NAME' => $displayName)); IPSText::getTextClass('email')->subject = sprintf($this->lang->words['new_registration_email'], $this->settings['board_name']); IPSText::getTextClass('email')->to = $this->settings['email_in']; IPSText::getTextClass('email')->sendMail(); } if (is_array($r)) { if (isset($r[1])) { $this->registry->getClass('output')->redirectScreen($r[0], $r[1]); $this->registry->getClass('output')->silentRedirect($r[1]); } else { $this->registry->getClass('output')->silentRedirect($r[0]); } } elseif (!$r) { throw new Exception('LINKED_MEMBER_LOGIN_FAIL'); } else { $this->registry->getClass('output')->silentRedirect($this->settings['base_url']); } } else { throw new Exception('CREATION_FAIL'); } } } } else { throw new Exception('CREATION_FAIL'); } } }
/** * Send Bulk Mail via Mandrill */ protected function _mailSendMandrill() { //----------------------------------------- // Load it //----------------------------------------- $id = intval($this->request['id']); $mail = $this->DB->buildAndFetch(array('select' => '*', 'from' => 'bulk_mail', 'where' => 'mail_id=' . $id)); if (!$mail['mail_id'] or !$mail['mail_subject'] or !$mail['mail_content']) { $this->registry->output->global_message = $this->lang->words['b_nosend']; $this->_mailStart(); return; } $opts = unserialize($mail['mail_opts']); //----------------------------------------- // Work out which vars we've actually used //----------------------------------------- $usedVars = array('unsubscribe'); foreach (array_keys($this->_getVariableInformation($this->memberData)) as $k) { if (strpos($mail['mail_content'], '{' . $k . '}') !== FALSE) { $usedVars[] = $k; } } //----------------------------------------- // Build the JSON document //----------------------------------------- $pergo = 2000; $recipientsTo = array(); $recipientsMerge = array(); /* Start with a basic query */ $queryData = array('select' => 'm.*', 'from' => array('members' => 'm'), 'order' => 'm.member_id', 'limit' => array($this->request['st'], $pergo)); /* Add in filters */ $done = 0; $complete = FALSE; $_queryData = $this->_buildMembersQuery($opts['filters']); $queryData['add_join'] = $_queryData['add_join']; $queryData['where'] = implode(' AND ', $_queryData['where']); /* Write the file */ $this->DB->build($queryData); $e = $this->DB->execute(); if (!$this->DB->getTotalRows($e)) { $complete = TRUE; } while ($r = $this->DB->fetch($e)) { /* Skip any invalid emails - the chars presented here are allowed via RFC (note that _ and - are already allowed in alphanumericClean and don't need to be specified) */ if (!$r['email'] or !$r['members_display_name'] or !IPSText::checkEmailAddress($r['email']) or $r['email'] != IPSText::alphanumericalClean($r['email'], '@.+!#$%&\'*/=?^`{|}~ ')) { continue; } $recipientsTo[] = array('email' => $r['email'], 'name' => $r['members_display_name']); $vars = array(); foreach ($this->_getVariableInformation($r, 1) as $k => $v) { if (in_array($k, $usedVars)) { $vars[] = array('name' => $k, 'content' => $v); } } if (!empty($vars)) { $recipientsMerge[] = array('rcpt' => $r['email'], 'vars' => $vars); } $done++; } //----------------------------------------- // Build Content //----------------------------------------- /* Sort out member vars */ $content = $mail['mail_content']; foreach ($this->_getVariableInformation($this->memberData) as $k => $v) { $content = str_replace('{' . $k . '}', '*|' . $k . '|*', $content); } /* Sort out global vars */ $globalMergeVars = array(); foreach ($this->_getVariableInformation(NULL, 2) as $k => $v) { if (in_array($k, $usedVars)) { $globalMergeVars[] = array('name' => $k, 'content' => $v); } } /* Get the full content */ IPSText::getTextClass('email')->clearContent(); IPSText::getTextClass('email')->unsubscribe = true; if ($opts['mail_html_on']) { IPSText::getTextClass('email')->setHtmlEmail(true); IPSText::getTextClass('email')->setHtmlTemplate(str_replace("\n", "", $content)); IPSText::getTextClass('email')->setHtmlWrapper('<#content#>'); } else { if ($this->settings['email_use_html']) { IPSText::getTextClass('email')->setHtmlEmail(true); IPSText::getTextClass('email')->setHtmlTemplate($content); } else { IPSText::getTextClass('email')->setPlainTextTemplate($content, true); } } if ($opts['mail_html_on'] or $this->settings['email_use_html']) { IPSText::getTextClass('email')->buildMessage(array('UNSUBSCRIBE' => '*|unsubscribe|*'), true, true); $content = IPSText::getTextClass('email')->getHtmlContent(); } else { IPSText::getTextClass('email')->buildMessage(array('UNSUBSCRIBE' => '*|unsubscribe|*')); $content = nl2br(IPSText::getTextClass('email')->getPlainTextContent()); } //----------------------------------------- // Send to Mandrill //----------------------------------------- if (IPS_DOC_CHAR_SET != "UTF-8") { $mail['mail_subject'] = IPSText::convertCharsets($mail['mail_subject'], IPS_DOC_CHAR_SET, "UTF-8"); } require_once IPSLib::getAppDir('members') . '/sources/classes/mandrill.php'; $mandrill = new Mandrill(); $response = $mandrill->messages_send(array('message' => array('html' => $content, 'subject' => $mail['mail_subject'], 'from_email' => $this->settings['email_out'], 'from_name' => $this->settings['board_name'], 'to' => $recipientsTo, 'auto_text' => true, 'url_strip_qs' => false, 'preserve_recipients' => false, 'merge' => true, 'global_merge_vars' => $globalMergeVars, 'merge_vars' => $recipientsMerge, 'tags' => array_merge(array('ips'), array_filter($opts['mandrill_tags'], create_function('$v', 'return (bool) $v;')))), 'async' => true)); if (isset($response->status) and $response->status == 'error') { $this->registry->output->showError('mandrill_error'); } //----------------------------------------- // Save //----------------------------------------- $this->DB->update('bulk_mail', array('mail_active' => 0, 'mail_updated' => time(), 'mail_sentto' => $mail['mail_sentto'] + count($recipientsTo)), 'mail_id=' . $mail['mail_id']); if ($complete !== TRUE) { $url = "{$this->settings['base_url']}app=members&module=bulkmail§ion=bulkmail&do=mail_send_mandrill&id={$id}&countmembers={$this->request['countmembers']}&st=" . ($this->request['st'] + $pergo); if (!$this->request['st']) { $this->registry->output->multipleRedirectInit($url); $this->registry->getClass('output')->html_main .= $this->registry->getClass('output')->global_template->global_frame_wrapper(); $this->registry->getClass('output')->sendOutput(); } else { $percentage = 100 / $this->request['countmembers'] * $this->request['st']; $percentage = floor($percentage); $this->registry->output->multipleRedirectHit($url, "Processing ({$percentage}% complete)"); } return; } else { $this->registry->output->multipleRedirectFinish(); } }