예제 #1
1
 /**
  * Reset user's password
  *
  * @param integer $userid User ID
  * @param string $activationid Activation ID
  */
 public function resetPassword($userid, $activationid)
 {
     $user = array();
     $userinfo = vB_User::fetchUserinfo($userid);
     $vboptions = vB::getDatastore()->getValue('options');
     if (isset($userinfo['userid'])) {
         $user = vB::getDbAssertor()->getRow('user_useractivation', array('userid' => $userinfo['userid']));
     }
     if (!$user) {
         throw new vB_Exception_Api('invalid_user_specified');
     }
     // Is it older than 24 hours ?
     if ($user['dateline'] < vB::getRequest()->getTimeNow() - 86400) {
         //fullurl shouldn't be necesary here, but it looks like the lostpw route doesn't quite handle things without it
         throw new vB_Exception_Api('resetexpired', vB5_Route::buildUrl('lostpw|fullurl'));
     }
     // Wrong act id ?
     if ($user['activationid'] != $activationid) {
         //fullurl shouldn't be necesary here, but it looks like the lostpw route doesn't quite handle things without it
         throw new vB_Exception_Api('resetbadid', vB5_Route::buildUrl('lostpw|fullurl'));
     }
     // Delete old activation id
     vB::getDbAssertor()->assertQuery('user_deleteactivationid', array('userid' => $userinfo['userid']));
     $loginlib = vB_Library::instance('login');
     $newpassword = $loginlib->resetPassword($userinfo['userid']);
     $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('resetpw', array($userinfo['username'], $newpassword, $vboptions['frontendurl'], $vboptions['bbtitle']), array($vboptions['bbtitle']), $userinfo['languageid']);
     vB_Mail::vbmail($userinfo['email'], $maildata['subject'], $maildata['message'], true);
     $response = vB_Api::instanceInternal('phrase')->fetch(array('password_reset', 'resetpw_message'));
     return $response;
 }
예제 #2
0
 /** Standard vB exception constructor for database exceptions.
  *
  *	@param	string	text message
  * 	@param	mixed	array of data- intended for debug mode
  * 	@code	mixed	normally an error flog.  If passed FALSE we won't send an email.
  */
 public function __construct($message = "", $data = array(), $code = 0)
 {
     $this->sql = $message;
     $this->data = $data;
     $message = $this->createMessage();
     $config = vB::getConfig();
     parent::__construct($message, $code);
     if (!empty($config['Database']['technicalemail']) and $code !== FALSE) {
         // This text is purposely hard-coded since we don't have
         // access to the database to get a phrase
         vB_Mail::vbmail($config['Database']['technicalemail'], 'Database Error', $message, true, $config['Database']['technicalemail'], '', '', true);
     }
 }
예제 #3
0
 /** sends a batch of emails
  *
  *	@param	mixed	array of recipients, or a semicolon-delimited string
  * 	@param	string	subject of the message
  * 	@param	string	content of message
  *
  * 	@return	mixed	either success => true, or array of sent, failed, errors, and message- the last is suitable for display to user.
  */
 public function send($to, $subject, $message)
 {
     //This should only be used by admins
     if (!vB::getUserContext()->hasAdminPermission('canadminusers')) {
         throw new vB_Exception_Api('no_permission');
     }
     if (!is_array($to)) {
         if (strpos($to, ';')) {
             $to = explode(';', $to);
         } else {
             $to = array($to);
         }
     }
     $errors = '';
     $sent = array();
     $failed = array();
     foreach ($to as $toemail) {
         //The next function returns either true, false or an error string.
         $result = vB_Mail::vbmail($toemail, $subject, $message, false, '', '', '', true);
         if (is_string($result)) {
             $errors .= $result;
         } else {
             if ($result) {
                 $sent[] = $toemail;
             } else {
                 $failed[] = $toemail;
             }
         }
     }
     if (empty($failed) and empty($errors)) {
         return array('success' => true);
     }
     $message = '';
     if (!empty($errors)) {
         $message = vB_Phrase::fetchSinglePhrase('error_x', $errors) . '. ';
     }
     if (!empty($sent)) {
         $message .= vB_Phrase::fetchSinglePhrase('sent_to_x', implode(',', $sent));
     }
     if (!empty($failed)) {
         $message .= vB_Phrase::fetchSinglePhrase('send_failed_to_x', implode(',', $failed));
     }
     return array('sent' => $sent, 'failed' => $failed, 'errors' => $errors, 'message' => $message);
 }
예제 #4
0
     $emails = explode(' ', $vbulletin->options['paymentemail']);
     $username = unhtmlspecialchars($apiobj->paymentinfo['username']);
     $userid = $apiobj->paymentinfo['userid'];
     $subscription = $vbphrase['sub' . $apiobj->paymentinfo['subscriptionid'] . '_title'];
     $amount = vb_number_format($apiobj->paymentinfo['amount'], 2) . ' ' . strtoupper($apiobj->paymentinfo['currency']);
     $processor = $api['title'];
     $transactionid = $apiobj->transaction_id;
     $memberlink = vB5_Route::buildUrl('profile|bburl', array('userid' => $userid, 'username' => $apiobj->paymentinfo['username']));
     if ($apiobj->type == 2) {
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('payment_reversed', array($username, $vbulletin->options['bbtitle'], $memberlink, $subscription, $amount, $processor, $transactionid), array($vbulletin->options['bbtitle']));
     } else {
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('payment_received', array($username, $vbulletin->options['bbtitle'], $memberlink, $subscription, $amount, $processor, $transactionid), array($vbulletin->options['bbtitle']));
     }
     foreach ($emails as $toemail) {
         if (trim($toemail)) {
             vB_Mail::vbmail($toemail, $maildata['subject'], $maildata['message'], true);
         }
     }
 }
 if (empty($transaction)) {
     // transaction hasn't been processed before
     /*insert query*/
     $trans = array('transactionid' => $apiobj->transaction_id, 'paymentinfoid' => $apiobj->paymentinfo['paymentinfoid'], 'amount' => $apiobj->paymentinfo['amount'], 'currency' => $apiobj->paymentinfo['currency'], 'state' => $apiobj->type, 'dateline' => TIMENOW, 'paymentapiid' => $api['paymentapiid']);
     if (!$apiobj->type) {
         $trans['request'] = serialize(array('vb_error_code' => $apiobj->error_code, 'GET' => serialize($_GET), 'POST' => serialize($_POST)));
     }
     vB::getDbAssertor()->insert('vBForum:paymenttransaction', $trans);
     if ($apiobj->type == 1) {
         $subobj->build_user_subscription($apiobj->paymentinfo['subscriptionid'], $apiobj->paymentinfo['subscriptionsubid'], $apiobj->paymentinfo['userid']);
         if ($apiobj->display_feedback) {
             $vbulletin->url = vB5_Route::buildUrl('settings|fullurl', array('tab' => 'subscriptions'));
function exec_digest($type = 2)
{
    // type = 2 : daily
    // type = 3 : weekly
    $lastdate = mktime(0, 0);
    // midnight today
    if ($type == 2) {
        // daily
        // yesterday midnight
        $lastdate -= 24 * 60 * 60;
    } else {
        // weekly
        // last week midnight
        $lastdate -= 7 * 24 * 60 * 60;
    }
    if (trim(vB::getDatastore()->getOption('globalignore')) != '') {
        $coventry = preg_split('#\\s+#s', vB::getDatastore()->getOption('globalignore'), -1, PREG_SPLIT_NO_EMPTY);
    } else {
        $coventry = array();
    }
    require_once DIR . '/includes/class_bbcode_alt.php';
    $vbulletin =& vB::get_registry();
    $plaintext_parser = new vB_BbCodeParser_PlainText($vbulletin, fetch_tag_list());
    vB_Mail::vbmailStart();
    $bf_misc_useroptions = vB::get_datastore()->get_value('bf_misc_useroptions');
    $bf_ugp_genericoptions = vB::get_datastore()->get_value('bf_ugp_genericoptions');
    $bf_ugp_forumpermissions = vB::get_datastore()->get_value('bf_ugp_forumpermissions');
    // we want to fetch all language records at once and using cache if possible
    $defaultLanguage = false;
    $languageIds = array();
    // get new threads (Topic Subscription)
    $threads = vB::getDbAssertor()->getRows('getNewThreads', array('dstonoff' => $bf_misc_useroptions['dstonoff'], 'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'], 'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup'], 'lastdate' => intval($lastdate)));
    // grab all forums / subforums for given subscription (Channel Subscription)
    $forums = vB::getDbAssertor()->assertQuery('getNewForums', array('dstonoff' => $bf_misc_useroptions['dstonoff'], 'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'], 'type' => intval($type), 'lastdate' => intval($lastdate), 'channelcontenttype' => vB_Api::instanceInternal('contenttype')->fetchContentTypeIdFromClass('Channel'), 'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup']));
    // Let's see which languageids we wanna fetch
    foreach ($threads as $thread) {
        if ($thread['languageid'] == 0) {
            if (!$defaultLanguage) {
                $defaultLanguage = intval(vB::getDatastore()->getOption('languageid'));
                $languageIds[] = $defaultLanguage;
            }
        } else {
            $languageIds[] = $thread['languageid'];
        }
    }
    foreach ($forums as $forum) {
        if ($forum['languageid'] == 0) {
            if (!$defaultLanguage) {
                $defaultLanguage = intval(vB::getDatastore()->getOption('languageid'));
                $languageIds[] = $defaultLanguage;
            }
        } else {
            $languageIds[] = $forum['languageid'];
        }
    }
    // fetch languages
    $languages = vB_Library::instance('language')->fetchLanguages($languageIds);
    // process threads
    foreach ($threads as $thread) {
        $postbits = '';
        // Make sure user have correct email notification settings.
        if ($thread['emailnotification'] != $type) {
            continue;
        }
        if ($thread['lastauthorid'] != $thread['userid'] and in_array($thread['lastauthorid'], $coventry)) {
            continue;
        }
        $usercontext = vB::getUserContext($thread['userid']);
        if (!$usercontext->getChannelPermission('forumpermissions', 'canview', $thread['nodeid']) or !$usercontext->getChannelPermission('forumpermissions', 'canviewthreads', $thread['nodeid']) or $thread['lastauthorid'] != $thread['userid'] and !$usercontext->getChannelPermission('forumpermissions', 'canviewothers', $thread['nodeid'])) {
            continue;
        }
        $langInfo =& $languages[$thread['languageid']];
        $userinfo = array('lang_locale' => $langInfo['locale'], 'dstonoff' => $thread['dstonoff'], 'timezoneoffset' => $thread['timezoneoffset']);
        $thread['lastreplydate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $thread['lastcontent'], false, true, true, false, $userinfo);
        $thread['lastreplytime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $thread['lastcontent'], false, true, true, false, $userinfo);
        $thread['htmltitle'] = unhtmlspecialchars($thread['htmltitle']);
        $thread['username'] = unhtmlspecialchars($thread['username']);
        $thread['postusername'] = unhtmlspecialchars($thread['authorname']);
        $thread['lastposter'] = unhtmlspecialchars($thread['lastcontentauthor']);
        $thread['newposts'] = 0;
        //not currently used and probably needs rethinking, but don't want to remove until this code gets rewritten
        //$thread['auth'] = md5($thread['userid'] . $thread['subscribediscussionid'] . $thread['secret'] . vB_Request_Web::$COOKIE_SALT);
        if ($thread['prefixid']) {
            // need prefix in correct language
            $phraseAux = vB_Api::instanceInternal('phrase')->fetch(array("prefix_{$thread['prefixid']}_title_plain"));
            $thread['prefix_plain'] = $phraseAux["prefix_{$thread['prefixid']}_title_plain"] . ' ';
        } else {
            $thread['prefix_plain'] = '';
        }
        // Note: closure.depth = 1  on the where clause means getNewPosts only grabs replies, not comments.
        // get posts
        $posts = vB::getDbAssertor()->getRows('getNewPosts', array('threadid' => intval($thread['nodeid']), 'lastdate' => intval($lastdate)));
        // compile
        $haveothers = false;
        foreach ($posts as $post) {
            if ($post['userid'] != $thread['userid'] and in_array($post['userid'], $coventry)) {
                continue;
            }
            if ($post['userid'] != $thread['userid']) {
                $haveothers = true;
            }
            $thread['newposts']++;
            $post['htmltitle'] = unhtmlspecialchars($post['htmltitle']);
            $post['postdate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $post['publishdate'], false, true, true, false, $userinfo);
            $post['posttime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $post['publishdate'], false, true, true, false, $userinfo);
            $post['postusername'] = unhtmlspecialchars($post['authorname']);
            $plaintext_parser->set_parsing_language($thread['languageid']);
            $contentAPI = vB_Library_Content::getContentApi($post['contenttypeid']);
            $contents = $contentAPI->getContent($post['nodeid']);
            $post['pagetext'] = $plaintext_parser->parse($contents[$post['nodeid']]['rawtext'], $thread['parentid']);
            $postlink = vB5_Route::buildUrl($post['routeid'] . '|bburl', array('nodeid' => $post['nodeid']));
            /*$postlink = fetch_seo_url('thread|nosession|bburl',
            		array('threadid' => $thread['nodeid'], 'title' => htmlspecialchars_uni($thread['title']))) .
            		"#post$post[nodeid]";*/
            // Legacy Hook 'digest_thread_post' Removed //
            $phrases = vB_Api::instanceInternal('phrase')->fetch('digestpostbit', $thread['languageid']);
            $postbits .= sprintf($phrases['digestpostbit'], $post['htmltitle'], $postlink, $post['postusername'], $post['postdate'], $post['posttime'], $post['pagetext']);
        }
        // Legacy Hook 'digest_thread_process' Removed //
        // Don't send an update if the subscriber is the only one who posted in the thread.
        if ($haveothers) {
            // make email
            // magic vars used by the phrase eval
            $threadlink = vB5_Route::buildUrl($thread['routeid'] . '|fullurl', array('nodeid' => $thread['nodeid']));
            //$threadlink = fetch_seo_url('thread|nosession|bburl', array('threadid' => $thread['threadid'], 'title' => htmlspecialchars_uni($thread['title'])));
            //this link probably doesn't do what the author thinks it does, need to validate.
            $unsubscribelink = vB5_Route::buildUrl('subscription|fullurl', array('tab' => 'subscriptions', 'userid' => $thread['userid']));
            $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestthread', array($thread['username'], $thread['prefix_plain'], $thread['htmltitle'], $thread['postusername'], $thread['newposts'], $thread['lastposter'], $threadlink, $postbits, vB::getDatastore()->getOption('bbtitle'), $unsubscribelink), array($thread['prefix_plain'], $thread['htmltitle']), $thread['languageid']);
            vB_Mail::vbmail($thread['email'], $maildata['subject'], $maildata['message']);
        }
    }
    unset($plaintext_parser);
    // process forums
    foreach ($forums as $forum) {
        $langInfo =& $languages[$forum['languageid']];
        $userinfo = array('lang_locale' => $langInfo['locale'], 'dstonoff' => $forum['dstonoff'], 'timezoneoffset' => $forum['timezoneoffset']);
        $newthreadbits = '';
        $newthreads = 0;
        $updatedthreadbits = '';
        $updatedthreads = 0;
        $forum['username'] = unhtmlspecialchars($forum['username']);
        $forum['title_clean'] = unhtmlspecialchars($forum['title_clean']);
        //not currently used and probably needs rethinking, but don't want to remove until this code gets rewritten
        //$forum['auth'] = md5($forum['userid'] . $forum['subscribeforumid'] . $forum['secret'] . vB_Request_Web::$COOKIE_SALT);
        $threads = vB::getDbAssertor()->assertQuery('fetchForumThreads', array('forumid' => intval($forum['forumid']), 'lastdate' => intval($lastdate)));
        foreach ($threads as $thread) {
            if ($thread['postuserid'] != $forum['userid'] and in_array($thread['postuserid'], $coventry)) {
                continue;
            }
            // allow those without canviewthreads to subscribe/receive forum updates as they contain not post content
            $usercontext = vB::getUserContext($thread['userid']);
            if (!$usercontext->getChannelPermission('forumpermissions', 'canview', $thread['nodeid']) or $thread['lastauthorid'] != $thread['userid'] and !$usercontext->getChannelPermission('forumpermissions', 'canviewothers', $thread['nodeid'])) {
                continue;
            }
            $thread['forumhtmltitle'] = unhtmlspecialchars($thread['forumhtmltitle']);
            $thread['lastreplydate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $thread['lastpost'], false, true, true, false, $userinfo);
            $thread['lastreplytime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $thread['lastpost'], false, true, true, false, $userinfo);
            $thread['htmltitle'] = unhtmlspecialchars($thread['htmltitle']);
            $thread['postusername'] = unhtmlspecialchars($thread['postusername']);
            $thread['lastposter'] = unhtmlspecialchars($thread['lastposter']);
            if ($thread['prefixid']) {
                // need prefix in correct language
                $phraseAux = vB_Api::instanceInternal('phrase')->fetch(array("prefix_{$thread['prefixid']}_title_plain"));
                $thread['prefix_plain'] = $phraseAux["prefix_{$thread['prefixid']}_title_plain"] . ' ';
            } else {
                $thread['prefix_plain'] = '';
            }
            $threadlink = vB5_Route::buildUrl($thread['routeid'] . '|fullurl', array('nodeid' => $thread['threadid']));
            // Legacy Hook 'digest_forum_thread' Removed //
            $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestthreadbit', array($thread['prefix_plain'], $thread['htmltitle'], $threadlink, $thread['forumhtmltitle'], $thread['postusername'], $thread['lastreplydate'], $thread['lastreplytime']), array(), $forum['languageid']);
            if ($thread['dateline'] > $lastdate) {
                // new thread
                $newthreads++;
                $newthreadbits .= $maildata['message'];
            } else {
                $updatedthreads++;
                $updatedthreadbits .= $maildata['message'];
            }
        }
        // Legacy Hook 'digest_forum_process' Removed //
        if (!empty($newthreads) or !empty($updatedthreadbits)) {
            // make email
            // magic vars used by the phrase eval
            //$forumlink = fetch_seo_url('forum|nosession|bburl', $forum);
            $forumlink = vB5_Route::buildUrl($forum['routeid'] . '|fullurl', array('nodeid' => $forum['forumid']));
            //this link probably doesn't do what the author thinks it does.  Need to validate.
            $unsubscribelink = vB5_Route::buildUrl('subscription|fullurl', array('tab' => 'subscriptions', 'userid' => $forum['userid']));
            $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestforum', array($forum['username'], $forum['title_clean'], $newthreads, $updatedthreads, $forumlink, $newthreadbits, $updatedthreadbits, vB::getDatastore()->getOption('bbtitle'), $unsubscribelink), array($forum['title_clean']), $forum['languageid']);
            vB_Mail::vbmail($forum['email'], $maildata['subject'], $maildata['message'], true);
        }
    }
    // ******* Social Group Digests **********
    $bf_misc_socnet = vB::get_datastore()->get_value('bf_misc_socnet');
    if (vB::getDatastore()->getOption('socnet') & $bf_misc_socnet['enable_groups']) {
        require_once DIR . '/includes/functions_socialgroup.php';
        /** @todo review this part*/
        /** @todo if we reenable this code, we need to prefetch language records as for threads and forums */
        /*
        $groups = vB::getDbAssertor()->assertQuery('fetchSocialGroupDigests', array(
        	'dstonoff' => $bf_misc_useroptions['dstonoff'],
        	'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'],
        	'languageid' => intval(vB::getDatastore()->getOption('languageid')),
        	'type' => $type == 2 ? 'daily' : 'weekly',
        	'lastdate' => intval($lastdate),
        	'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup']
        ));
        
        
        foreach ($groups as $group)
        {
        	$userperms = cache_permissions($group, false);
        	if (!($userperms['forumpermissions'] & $vbulletin->bf_ugp_forumpermissions['canview'])
        		OR !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canviewgroups'])
        	)
        	{
        		continue;
        	}
        
        	if ($group['options'] & $vbulletin->bf_misc_socialgroupoptions['join_to_view'] AND $vbulletin->options['sg_allow_join_to_view'])
        	{
        		if ($group['membertype'] != 'member'
        			AND !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canalwayspostmessage'])
        			AND !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canalwascreatediscussion'])
        		)
        		{
        			continue;
        		}
        	}
        
        	$userinfo = array(
        		'lang_locale'       => $group['lang_locale'],
        		'dstonoff'          => $group['dstonoff'],
        		'timezoneoffset'    => $group['timezoneoffset'],
        	);
        
        	$new_discussion_bits = '';
        	$new_discussions = 0;
        	$updated_discussion_bits = '';
        	$updated_discussions = 0;
        
        	$group['username'] = unhtmlspecialchars($group['username']);
        	$group['name'] = unhtmlspecialchars($group['name']);
        	$discussions = vB::getDbAssertor()->assertQuery('fetchGroupDiscussions', array(
        			'groupid' => $group['groupid'],
        			'lastdate' => intval($lastdate)
        	));
        	foreach ($discussions as $discussion)
        	{
        		$discussion['lastreplydate'] = vbdate($group['lang_dateoverride'] ? $group['lang_dateoverride'] : $vbulletin->options['default_dateformat'], $discussion['lastpost'], false, true, true, false, $userinfo);
        		$discussion['lastreplytime'] = vbdate($group['lang_timeoverride'] ? $group['lang_timeoverride'] : $vbulletin->options['default_timeformat'], $discussion['lastpost'], false, true, true, false, $userinfo);
        
        		$discussion['title'] = unhtmlspecialchars($discussion['title']);
        		$discussion['postusername'] = unhtmlspecialchars($discussion['postusername']);
        		$discussion['lastposter'] = unhtmlspecialchars($discussion['lastposter']);
        
        		// Legacy Hook 'digest_group_discussion' Removed //
        
        		//magic variables that will be picked up by the phrase eval
        		$discussionlink = fetch_seo_url('groupdiscussion', $discussion);
        
        		$maildata = vB_Api::instanceInternal('phrase')
        			->fetchEmailPhrases('digestgroupbit', array($discussion['htmltitle'], $discussionlink, $group['name'], $discussion['postusername'], $discussion['lastreplydate'], $discussion['lastreplytime']), array(), $group['languageid']);
        		if ($discussion['dateline'] > $lastdate)
        		{ // new discussion
        			$new_discussions++;
        			$new_discussion_bits .= $maildata['message'];
        		}
        		else
        		{
        			$updated_discussions++;
        			$updated_discussion_bits .= $maildata['message'];
        		}
        
        	}
        
        	// Legacy Hook 'digest_group_process' Removed //
        
        	if (!empty($new_discussion_bits) OR !empty($updated_discussion_bits))
        	{
        		//magic variables that will be picked up by the phrase eval
        		$grouplink = fetch_seo_url('group|nosession|bburl', $group);
        
        		// make email
        		$maildata = vB_Api::instanceInternal('phrase')
        			->fetchEmailPhrases('digestgroup', array($group['username'], $group['name'], $new_discussions, $updated_discussions, $grouplink, $new_discussion_bits, $updated_discussion_bits, $vbulletin->options['bbtitle']), array($group['name']), $group['languageid']);
        		vB_Mail::vbmail($group['email'], $maildata['subject'], $maildata['message']);
        	}
        }
        */
    }
    vB_Mail::vbmailEnd();
}
예제 #6
0
}
vB_Mail::vbmailStart();
$usernames = '';
$reminderbits = '';
foreach ($eventlist as $userid => $event) {
    $usernames .= iif($usernames, ', ');
    $usernames .= $userinfo["{$userid}"]['username'];
    $reminderbits = '';
    foreach ($event as $eventid => $hour) {
        $eventinfo =& $eventcache["{$eventid}"];
        $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('reminderbit', array($eventinfo['title'], $hour, $vbulletin->options['bburl'], $eventinfo['eventid'], $eventinfo['calendar']), array(), $userinfo["{$userid}"]['languageid']);
        $reminderbits .= $maildata['message'];
    }
    $username = unhtmlspecialchars($userinfo["{$userid}"]['username']);
    $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('reminder', array($username, $vbulletin->options['bbtitle'], $reminderbits, $vbulletin->options['bburl']), array($vbulletin->options['bbtitle']), $userinfo["{$userid}"]['languageid']);
    vB_Mail::vbmail($userinfo["{$userid}"]['email'], $maildata['subject'], $maildata['message']);
    if ($vb5_config['Misc']['debug'] and VB_AREA == 'AdminCP') {
        "<pre>";
        echo $maildata['subject'];
        echo "</pre>";
        echo "<pre>";
        echo $maildata['message'];
        echo "</pre><br />";
    }
}
vB_Mail::vbmailEnd();
if (!empty($usernames)) {
    log_cron_action($usernames, $nextitem, 1);
}
/*=========================================================================*\
|| #######################################################################
예제 #7
0
 public static function execStrikeUser($username = '')
 {
     // todo: remove this global variable
     global $strikes;
     $assertor = vB::getDbAssertor();
     $request = vB::getRequest();
     $options = vB::getDatastore()->getValue('options');
     if (!$options['usestrikesystem']) {
         return 0;
     }
     $strikeip = $request->getIpAddress();
     $ipFields = vB_Ip::getIpFields($strikeip);
     if (!empty($username)) {
         $strikes_user = $assertor->getRow('vBForum:strikes', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_COUNT, 'ip_4' => vB_dB_Type_UInt::instance($ipFields['ip_4']), 'ip_3' => vB_dB_Type_UInt::instance($ipFields['ip_3']), 'ip_2' => vB_dB_Type_UInt::instance($ipFields['ip_2']), 'ip_1' => vB_dB_Type_UInt::instance($ipFields['ip_1']), 'username' => vB_String::htmlSpecialCharsUni($username)));
         if ($strikes_user['count'] == 4) {
             if ($user = $assertor->getRow('user', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'username', 'value' => $username, 'operator' => vB_dB_Query::OPERATOR_EQ), array('field' => 'usergroupid', 'value' => 3, 'operator' => vB_dB_Query::OPERATOR_NE))))) {
                 $ip = $request->getIpAddress();
                 $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('accountlocked', array($user['username'], $options['bbtitle'], $ip), array($options['bbtitle']), $user['languageid']);
                 vB_Mail::vbmail($user['email'], $maildata['subject'], $maildata['message'], true);
             }
         }
     }
     /* insert query */
     $assertor->insert('vBForum:strikes', array('striketime' => $request->getTimeNow(), 'strikeip' => $strikeip, 'ip_4' => vB_dB_Type_UInt::instance($ipFields['ip_4']), 'ip_3' => vB_dB_Type_UInt::instance($ipFields['ip_3']), 'ip_2' => vB_dB_Type_UInt::instance($ipFields['ip_2']), 'ip_1' => vB_dB_Type_UInt::instance($ipFields['ip_1']), 'username' => vB_String::htmlSpecialCharsUni($username)));
     $strikes++;
     // Legacy Hook 'login_strikes' Removed //
 }
예제 #8
0
 protected function sendLegacyEmailNotification($data)
 {
     $options = vB::getDatastore()->getValue('options');
     if (isset($options['enableemail']) and !$options['enableemail']) {
         return;
         // email notifications are globally disabled
     }
     /*
      *	Save some data for this page load. Since we can potentially fetch a bunch of the same
      *	data over and over if multiple users are getting notifications about the same content
      *	that was just created, let's get rid of the redundant calls when this function is called
      *	in a loop.
      *	Todo: we should write a bulk-send-email-notification function
      *
      *	I can't actually think of a case where a single content creation that triggers a number
      *	of email notifications will have different contentnodeid in its group of notifications,
      *	but let's just be safe and allow for that possibility.
      */
     static $recipientIndependentDataArray;
     $contentnodeid = isset($data['contentnodeid']) ? $data['contentnodeid'] : 0;
     if (!empty($contentnodeid) and empty($recipientIndependentDataArray[$contentnodeid])) {
         //we need to load this using the correct library class or things get weird.
         //note that if we load it from cache here it will be in the local memory cache
         //when we load the full content and we won't do it twice.
         $cached = vB_Library_Content::fetchFromCache(array($contentnodeid), vB_Library_Content::CACHELEVEL_FULLCONTENT);
         if (isset($cached['found'][$contentnodeid])) {
             $contenttypeid = $cached['found'][$contentnodeid]['contenttypeid'];
         } else {
             $row = $this->assertor->getRow('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('contenttypeid'), 'nodeid' => $contentnodeid));
             $contenttypeid = $row['contenttypeid'];
         }
         $contentLib = vB_Library_Content::getContentLib($contenttypeid);
         $currentNode = $contentLib->getContent($contentnodeid);
         $currentNode = $currentNode[$contentnodeid];
         /*
          *	These data are static & independent of the recipient of this message, assuming that
          *	we're not trying to hide any data. If we are going to check permissions for each
          *	recipient, we should probably check view perms & remove from the recipients list
          *	BEFORE we ever get to this function, and just not send them a notification instead of
          *	hiding data.
          */
         $recipientIndependentDataArray[$contentnodeid] = array('authorname' => $currentNode['userinfo']['username'], 'nodeurl' => vB5_Route::buildUrl('node|fullurl', array('nodeid' => $contentnodeid)), 'previewtext' => vB_String::getPreviewText($currentNode['rawtext']), 'nodeid' => $currentNode['nodeid'], 'starter' => $currentNode['starter'], 'startertitle' => isset($currentNode['startertitle']) ? $currentNode['startertitle'] : '', 'parentid' => $currentNode['parentid'], 'channeltitle' => $currentNode['channeltitle'], 'channeltype' => $currentNode['channeltype']);
     }
     // additional data used for subscription notifications
     if (isset($data['subscriptionnodeid'])) {
         $subId = $data['subscriptionnodeid'];
         if (!isset($recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId])) {
             //we need to load this using the correct library class or things get weird.
             //note that if we load it from cache here it will be in the local memory cache
             //when we load the full content and we won't do it twice.
             $cached = vB_Library_Content::fetchFromCache(array($subId), vB_Library_Content::CACHELEVEL_FULLCONTENT);
             if (isset($cached['found'][$subId])) {
                 $contenttypeid = $cached['found'][$subId]['contenttypeid'];
             } else {
                 $row = $this->assertor->getRow('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('contenttypeid'), 'nodeid' => $subId));
                 $contenttypeid = $row['contenttypeid'];
             }
             if ($contenttypeid) {
                 $contentLib = vB_Library_Content::getContentLib($contenttypeid);
                 $subbedNode = $contentLib->getContent($subId);
                 $subbedNode = $subbedNode[$subId];
                 $channelTypeId = vB_Types::instance()->getContentTypeID('vBForum_Channel');
                 if ($subbedNode['contenttypeid'] == $channelTypeId) {
                     $nodetype = 'channel';
                 } else {
                     $nodetype = 'post';
                 }
                 $recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId] = array('title' => $subbedNode['title'], 'nodetype' => $nodetype);
             }
         }
         // We only expect channeltype_forum, channeltype_article, channeltype_blog, channeltype_group, but
         // a channeltype_<> phrase for each of vB_Channel::$channelTypes should exist, so we can do this
         $channeltype = "channeltype_" . $recipientIndependentDataArray[$contentnodeid]['channeltype'];
         $nodetype = $recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId]['nodetype'];
         // While phrases are dependent on languageid, it's not really recipient or userid
         // dependent and is shared/static among different recipients, so let's keep track
         // of them.
         if (!isset($phrases[$data['languageid']])) {
             $phrases[$data['languageid']] = vB_Api::instanceInternal('phrase')->fetch(array($channeltype, $nodetype), $data['languageid']);
         }
     }
     // keep track of the about strings that are for "content" notifications
     $temporary = array(vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_REPLY, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_COMMENT, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_THREADCOMMENT, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION);
     $contentNotificationAboutStrings = array();
     foreach ($temporary as $aboutString) {
         $contentNotificationAboutStrings[$aboutString] = $aboutString;
     }
     if ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_VM) {
         // A VM should have only 1 recipient, so no good reason to cache this like other URLs. Also
         // VMs don't seem to work with the /node/ route, so we can't rely on that.
         $vmURL = vB5_Route::buildUrl('visitormessage|fullurl', array('nodeid' => $contentnodeid));
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('visitormessage', array($data['username'], $recipientIndependentDataArray[$contentnodeid]['authorname'], $vmURL, $recipientIndependentDataArray[$contentnodeid]['previewtext'], $options['bbtitle']), array(), $data['languageid']);
     } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_VOTE) {
         // Vote notifications have their own section because their phrases aren't in the same format as the others
         // Since a vote doesn't have a node associated with it, we don't have a "currentnode" data.
         // Note that the poll library sets aboutid & contentid both to the nodeid of the poll-post
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('vote', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName(vB::getCurrentSession()->get('userid')), $recipientIndependentDataArray[$contentnodeid]['nodeurl'], $options['bbtitle']), array($recipientIndependentDataArray[$contentnodeid]['startertitle']), $data['languageid']);
     } elseif (isset($contentNotificationAboutStrings[$data['about']])) {
         // Normally the subject would contain the topic title, but if it's a subscription let's pass in the
         // title of the actual subscription node whether it's a channel, thread, blog etc.
         $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['startertitle']);
         // Since subscription email subjects don't have a title, we'll include the title in
         // the email body as a 7th variable.
         $emailBodyVars = array($data['username'], $recipientIndependentDataArray[$contentnodeid]['authorname'], $recipientIndependentDataArray[$contentnodeid]['nodeurl'], $recipientIndependentDataArray[$contentnodeid]['previewtext'], $options['bbtitle'], $options['frontendurl'] . '/member/' . $data['userid'] . '/subscriptions');
         // blog & social groups have special phrases, unless it's a subscription notification or a user mention.
         // If the latter, just send the generic subscription or user mention email.
         // As of 5.1.4, we do not expect to hit this block for blogs, because the people who *would*
         // receive this (the blog poster) are automatically subscribed to the blog channel, and
         // subscription notifications always trump other types of notifications. See VBV-13466
         if ($recipientIndependentDataArray[$contentnodeid]['channeltype'] == 'blog' and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION) {
             $mailPhrase = 'comment_blogentry';
         } else {
             if ($recipientIndependentDataArray[$contentnodeid]['channeltype'] == 'group' and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION) {
                 $mailPhrase = 'comment_grouptopic';
             } else {
                 switch ($data['about']) {
                     case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_REPLY:
                         $mailPhrase = 'reply_thread';
                         break;
                     case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_COMMENT:
                         $mailPhrase = 'comment_post';
                         break;
                     case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_THREADCOMMENT:
                         $mailPhrase = 'comment_thread';
                         break;
                     case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION:
                         $mailPhrase = 'subscribed_thread';
                         // $subId, $nodetype, $channeltype aer set above as long as 'subscriptionnodeid' was passed in.
                         if (!empty($subId)) {
                             // A new post in your {2} {3} subscription: {1}
                             $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId]['title'], $phrases[$data['languageid']][$channeltype], $phrases[$data['languageid']][$nodetype]);
                             // Since we removed the starter title from the subject, add it to the message.
                             $emailBodyVars[] = $recipientIndependentDataArray[$contentnodeid]['startertitle'];
                         }
                         break;
                     case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION:
                         $mailPhrase = 'usermention_post';
                         // subject: <username> mentioned you in <content item title>
                         $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['authorname'], $recipientIndependentDataArray[$contentnodeid]['startertitle']);
                         break;
                     default:
                         if ($recipientIndependentDataArray[$contentnodeid]['starter'] == $recipientIndependentDataArray[$contentnodeid]['parentid']) {
                             $mailPhrase = 'reply_thread';
                         } else {
                             $mailPhrase = 'reply_post';
                         }
                         break;
                 }
             }
         }
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases($mailPhrase, $emailBodyVars, $emailSubjectVars, $data['languageid']);
     } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_RATE) {
         $node = $recipientIndependentDataArray[$contentnodeid];
         // It doesn't make sense to call blog & article starters as "threads", so just go with "post"
         if ($node['nodeid'] == $node['starter'] and ($node['channeltype'] == 'forum' or $node['channeltype'] == 'group')) {
             $mailPhrase = 'like_thread';
         } else {
             $mailPhrase = 'like_post';
         }
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases($mailPhrase, array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['senderid']), $node['nodeurl'], $options['bbtitle']), array($options['bbtitle']));
     } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_FOLLOW) {
         // the use of vB5_Route::buildUrl() below should be ok performant wise, because we're not expecting to send a bulk email for this
         // notification type. We should avoid hacky hacks (see above in the content notification section for avoiding vB5_Route::buildUrl()
         // to each recipient's subscription page) when forgivable.
         $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('follow_approve', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['senderid']), vB5_Route::buildUrl('profile|fullurl', array('userid' => $data['senderid'], 'tab' => 'subscribed')), $options['bbtitle']), array($options['bbtitle']));
     } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_FOLLOWING) {
         /*
         	Per dev chat discussion, this never existed. Since there doesn't seem to be a strong customer request for this,
         	I'm gonna leave it out. I'm leaving this section in so that it's trivial to add in the future.
         */
         $maildata = array();
     } else {
         // We don't know how to handle this.
         $maildata = array();
     }
     if (!empty($data['email']) and !empty($maildata)) {
         // Send the email
         vB_Mail::vbmail($data['email'], $maildata['subject'], $maildata['message'], false);
     }
 }
예제 #9
0
// ########################################################################
$subobj = new vB_PaidSubscription();
$subobj->cache_user_subscriptions();
if (is_array($subobj->subscriptioncache)) {
    foreach ($subobj->subscriptioncache as $key => $subscription) {
        // disable people :)
        $subscribers = vB::getDbAssertor()->assertQuery('vBForum:subscriptionlog', array(vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'subscriptionid', 'value' => $subscription['subscriptionid'], vB_Db_Query::OPERATOR_KEY => vB_Db_Query::OPERATOR_EQ), array('field' => 'expirydate', 'value' => vB::getRequest()->getTimeNow(), vB_Db_Query::OPERATOR_KEY => vB_Db_Query::OPERATOR_LTE), array('field' => 'status', 'value' => 1, vB_Db_Query::OPERATOR_KEY => vB_Db_Query::OPERATOR_EQ))));
        foreach ($subscribers as $subscriber) {
            $subobj->delete_user_subscription($subscription['subscriptionid'], $subscriber['userid'], -1, true);
        }
    }
    // time for the reminders
    $subscriptions_reminders = vB::getDbAssertor()->assertQuery('getSubscriptionsReminders', array('time1' => vB::getRequest()->getTimeNow() + 86400 * 2, 'time2' => vB::getRequest()->getTimeNow() + 86400 * 3));
    vB_Mail::vbmailStart();
    foreach ($subscriptions_reminders as $subscriptions_reminder) {
        $phraseAux = vB_Api::instanceInternal('phrase')->fetch(array('sub' . $subscriptions_reminder['subscriptionid'] . '_title', 'subscription'));
        $subscription_title = $phraseAux['sub' . $subscriptions_reminder['subscriptionid'] . '_title'];
        $username = unhtmlspecialchars($subscriptions_reminder['username']);
        $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('paidsubscription_reminder', array($username, $subscription_title, $vbulletin->options['bburl'], $vbulletin->options['bbtitle']), array(), $subscriptions_reminder['languageid']);
        vB_Mail::vbmail($subscriptions_reminder['email'], $maildata['subject'], $maildata['message']);
    }
    vB_Mail::vbmailEnd();
    // Legacy Hook 'cron_script_subscriptions' Removed //
}
log_cron_action('', $nextitem, 1);
/*=========================================================================*\
|| #######################################################################
|| # Downloaded: 15:45, Tue Sep 8th 2015
|| # CVS: $RCSfile$ - $Revision: 83432 $
|| #######################################################################
\*=========================================================================*/
예제 #10
0
 /**
  * Sends a PM to the infracted user
  *
  * @param	array	The infraction data
  * @param	array	The (to be) infracted node information
  * @param	array	The (to be) infracted user information
  * @param	array	The information for this infraction level (or custom infraction as it may be)
  * @param	bool	Whether or not this is a warning
  * @param	mixed	if is an array the user will be banned if is false user won't be banned with this infraction, used to determine to send pm or email
  *
  * @return	(int|array)	The nodeid for the PM, or an array of information on error
  */
 protected function sendPm(array $data, array $infractedNode, array $infractedUserInfo, array $infractionLevelInfo, $isWarning, $banToApply)
 {
     $vboptions = vB::getDatastore()->getValue('options');
     $pmData = array('sentto' => array($data['infracteduserid']), 'sender' => vB::getCurrentSession()->get('userid'));
     // set PM title
     $pmData['title'] = sprintf($this->getPhrase(($isWarning ? 'warning' : 'infraction') . '_received_ginfraction'), $infractionLevelInfo['title']);
     // set PM text
     if ($data['infractednodeid']) {
         if ($isWarning) {
             // post warning
             $pmData['rawtext'] = sprintf($this->getPhrase('warning_received_post'), $infractedUserInfo['username'], $vboptions['bbtitle'], $infractionLevelInfo['title'], $data['message'], vB5_Route::buildUrl($infractedNode['routeid'] . '|fullurl', array('nodeid' => $infractedNode['nodeid'], 'title' => $infractedNode['title']), array('p' => $infractedNode['nodeid'])) . '#post' . $infractedNode['nodeid'], $infractedNode['pagetext'] ? $infractedNode['pagetext'] : $infractedNode['rawtext']);
         } else {
             // post infraction
             $pmData['rawtext'] = sprintf($this->getPhrase('infraction_received_post'), $infractedUserInfo['username'], $vboptions['bbtitle'], $infractionLevelInfo['title'], $data['message'], $infractionLevelInfo['points'], vB5_Route::buildUrl($infractedNode['routeid'] . '|fullurl', array('nodeid' => $infractedNode['nodeid'], 'title' => $infractedNode['title']), array('p' => $infractedNode['nodeid'])) . '#post' . $infractedNode['nodeid'], $infractedNode['pagetext'] ? $infractedNode['pagetext'] : $infractedNode['rawtext'], $infractionLevelInfo['reputation_penalty']);
         }
     } else {
         if ($isWarning) {
             // profile warning
             $pmData['rawtext'] = sprintf($this->getPhrase('warning_received_profile'), $infractedUserInfo['username'], $vboptions['bbtitle'], $infractionLevelInfo['title'], $data['message']);
         } else {
             // profile infraction
             $pmData['rawtext'] = sprintf($this->getPhrase('infraction_received_profile'), $infractedUserInfo['username'], $vboptions['bbtitle'], $infractionLevelInfo['title'], $data['message'], $infractionLevelInfo['points'], $infractionLevelInfo['reputation_penalty']);
         }
     }
     $currentBan = $this->assertor->getRow('userban', array('userid' => $infractedUserInfo['userid']));
     if ($currentBan and $currentBan['liftdate'] == 0 or is_array($banToApply) and isset($banToApply['liftdate']) and $banToApply['liftdate'] == 0) {
         return false;
     }
     if ($vboptions['enablepms'] and vB::getUserContext($infractedUserInfo['userid'])->getUsergroupLimit('pmquota')) {
         vB_Library::instance('Content_Privatemessage')->add($pmData, array('skipDupCheck' => true));
     }
     if ($vboptions['enableemail']) {
         vB_Mail::vbmail($infractedUserInfo['email'], $pmData['title'], $pmData['rawtext'], true);
     }
 }
예제 #11
0
 public function sendActivateEmail($userid)
 {
     $userinfo = vB_User::fetchUserinfo($userid);
     if (empty($userinfo)) {
         throw new vB_Exception_Api('invaliduserid');
     }
     if ($userinfo['usergroupid'] != 3) {
         // Already activated
         throw new vB_Exception_Api('activate_wrongusergroup');
     }
     $vboptions = vB::getDatastore()->getValue('options');
     $coppauser = false;
     if (!empty($userinfo['birthdaysearch'])) {
         $birthday = $userinfo['birthdaysearch'];
     } else {
         //we want YYYY-MM-DD for the coppa check but normally we store MM-DD-YYYY
         $birthday = $userinfo['birthday'];
         if (strlen($birthday) >= 6 and $birthday[2] == '-' and $birthday[5] == '-') {
             $birthday = substr($birthday, 6) . '-' . substr($birthday, 0, 2) . '-' . substr($birthday, 3, 2);
         }
     }
     if ($vboptions['usecoppa'] == 1 and $this->needsCoppa($birthday)) {
         $coppauser = true;
     }
     $username = trim(unhtmlspecialchars($userinfo['username']));
     require_once DIR . '/includes/functions_user.php';
     // Try to get existing activateid from useractivation table
     $useractivation = vB::getDbAssertor()->getRow('useractivation', array('userid' => $userinfo['userid']));
     if ($useractivation) {
         $activateid = fetch_random_string(40);
         vB::getDbAssertor()->update('useractivation', array('dateline' => vB::getRequest()->getTimeNow(), 'activationid' => $activateid), array('userid' => $userinfo['userid'], 'type' => 0));
     } else {
         $activateid = build_user_activation_id($userinfo['userid'], ($vboptions['moderatenewmembers'] or $coppauser) ? 4 : 2, 0);
     }
     $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('activateaccount', array($username, $vboptions['bbtitle'], $vboptions['frontendurl'], $userinfo['userid'], $activateid, $vboptions['webmasteremail']), array($username), $userinfo['languageid']);
     vB_Mail::vbmail($userinfo['email'], $maildata['subject'], $maildata['message'], true);
 }
예제 #12
0
 protected function sendEmailNotification($data)
 {
     if (isset($data['msgtype']) and $data['msgtype'] == 'request') {
         if (isset($data['about']) and $data['about'] == 'follow') {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('follow_request', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['aboutid']), vB5_Route::buildUrl('privatemessage|fullurl', array('folderid' => $data['folderid'], 'pagenum' => 1, 'action' => $data['msgtype'])), vB::getDatastore()->getOption('bbtitle')), array(vB::getDatastore()->getOption('bbtitle')));
         } else {
             if (isset($data['about']) and $data['about'] == 'moderator_to') {
                 $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('moderation_request', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['userid']), vB5_Route::buildUrl('privatemessage|fullurl', array('folderid' => $data['folderid'], 'pagenum' => 1, 'action' => $data['msgtype'])), vB::getDatastore()->getOption('bbtitle')), array(vB::getDatastore()->getOption('bbtitle')));
             } else {
                 if (isset($data['about']) and $data['about'] == 'owner_to') {
                     $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('ownership_request', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['userid']), vB5_Route::buildUrl('privatemessage|fullurl', array('folderid' => $data['folderid'], 'pagenum' => 1, 'action' => $data['msgtype'])), vB::getDatastore()->getOption('bbtitle')), array(vB::getDatastore()->getOption('bbtitle')));
                 }
             }
         }
     } else {
         if (isset($data['msgtype']) and $data['msgtype'] == 'message') {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('privatemessage', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['userid']), vB5_Route::buildUrl('privatemessage|fullurl', array('action' => 'list', 'pagenum' => 1, 'folderid' => $data['folderid'])), $data['rawtext'], vB::getDatastore()->getOption('bbtitle')), array(vB::getDatastore()->getOption('bbtitle')));
         }
     }
     // self::NOTIFICATION_TYPE_RATE & self::NOTIFICATION_TYPE_FOLLOW emails moved to notification library.
     if (!empty($maildata)) {
         // Sending the email
         vB_Mail::vbmail($data['email'], $maildata['subject'], $maildata['message'], false);
     }
 }
예제 #13
0
 /**
  * 	Adds a new node.
  *
  *	@param	mixed		Array of field => value pairs which define the record.
  *	@param	array		Array of options for the content being created.
  *						Understands skipTransaction, skipFloodCheck, floodchecktime, skipDupCheck, skipNotification, nl2br, autoparselinks.
  *							- nl2br: if TRUE, all \n will be converted to <br /> so that it's not removed by the html parser (e.g. comments).
  *	@param	bool		Convert text to bbcode
  *
  * 	@return	mixed		array with nodeid (int), success (bool), cacheEvents (array of strings), nodeVals (array of field => value), attachments (array of attachment records).
  */
 public function add($data, array $options = array(), $convertWysiwygTextToBbcode = true)
 {
     //Store this so we know whether we should call afterAdd()
     $skipTransaction = !empty($options['skipTransaction']);
     $vboptions = vB::getDatastore()->getValue('options');
     $reportemail = ($vboptions['enableemail'] and $vboptions['rpemail']);
     $data['reportnodeid'] = intval($data['reportnodeid']);
     // Build node title based on reportnodeid
     if (!$data['reportnodeid']) {
         throw new vB_Exception_Api('invalid_report_node');
     }
     $data['parentid'] = $this->ReportChannel;
     if (empty($data['title'])) {
         $reportnode = $this->nodeApi->getNodeFullContent($data['reportnodeid']);
         $reportnode = $reportnode[$data['reportnodeid']];
         $phraseapi = vB_Api::instanceInternal('phrase');
         if ($reportnode['nodeid'] == $reportnode['starter']) {
             // Thread starter
             $data['title'] = $reportnode['title'];
         } elseif ($reportnode['parentid'] == $reportnode['starter']) {
             $phrases = $phraseapi->fetch(array('reply_to'));
             $data['title'] = $phrases['reply_to'] . ' ' . $reportnode['startertitle'];
         } else {
             $phrases = $phraseapi->fetch(array('comment_in_a_topic'));
             $data['title'] = $phrases['comment_in_a_topic'] . ' ' . $reportnode['startertitle'];
         }
     }
     $result = parent::add($data, $options, $convertWysiwygTextToBbcode);
     if (!$skipTransaction) {
         //The child classes that have their own transactions all set this to true so afterAdd is always called just once.
         $this->afterAdd($result['nodeid'], $data, $options, $result['cacheEvents'], $result['nodeVals']);
     }
     // send an email
     if ($reportemail) {
         $reporterInfo = vB::getCurrentSession()->fetch_userinfo();
         $nodeLib = vB_Library::instance('node');
         $moderators = array();
         $moderatorUsernames = '';
         // Get moderators on the reported node
         $moderatorsArray = $nodeLib->getNodeModerators($reportnode['nodeid']);
         foreach ($moderatorsArray as $moderator) {
             $moderators[$moderator['userid']] = $moderator['userid'];
         }
         if ($vboptions['rpemail'] == 2) {
             // Fetch admins and super moderators
             $allmoderators = $nodeLib->getForumSupermoderatorsAdmins($moderators);
             foreach ($allmoderators as $moderator) {
                 $moderators[$moderator['userid']] = $moderator['userid'];
             }
         }
         // get user info
         foreach ($moderators as $moderatorid => $moderator) {
             $moderators[$moderatorid] = vB_Library::instance('user')->fetchUserinfo($moderatorid);
             $moderatorUsernames .= $moderators[$moderatorid]['username'] . ', ';
         }
         // Compose the email
         if ($reportnode['starter'] == $reportnode['nodeid']) {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('reportpost_newthread', array(vB5_Route::buildUrl('profile|fullurl', array('userid' => $reporterInfo['userid'])), $reporterInfo['username'], $data['rawtext'], vB5_Route::buildUrl($reportnode['routeid'] . '|fullurl', array('nodeid' => $reportnode['nodeid'], 'title' => $reportnode['title'])), $reportnode['title'], vB::getDatastore()->getOption('bbtitle'), substr($moderatorUsernames, 0, -2), $reportnode['authorname'], vB5_Route::buildUrl('profile|fullurl', array('userid' => $reportnode['userid'])), vB_String::getPreviewText($reportnode['rawtext'])), array($reporterInfo['username']));
         } else {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('reportpost', array($reporterInfo['username'], $reporterInfo['email'], $reportnode['title'], vB5_Route::buildUrl($reportnode['routeid'] . '|fullurl', array('nodeid' => $reportnode['starter'], 'userid' => $reportnode['starteruserid'], 'username' => $reportnode['starterauthorname'], 'innerPost' => $reportnode['nodeid'], 'innerPostParent' => $reportnode['parentid'])), $reportnode['startertitle'], vB5_Route::buildUrl($reportnode['routeid'] . '|fullurl', array('nodeid' => $reportnode['starter'], 'title' => $reportnode['startertitle'])), $data['rawtext']), array(vB::getDatastore()->getOption('bbtitle')));
         }
         // Send out the emails
         foreach ($moderators as $moderator) {
             if (!empty($moderator['email'])) {
                 vB_Mail::vbmail($moderator['email'], $maildata['subject'], $maildata['message'], false);
             }
         }
     }
     return $result;
 }
예제 #14
0
 /**
  * Sends emails to moderators configured in admincp
  */
 protected function sendModeratorNotification($nodeid)
 {
     // This is the list of ALL mods who have either the newpostemail or the newthreademail option enabled
     // We'll go through this list and figure out which ones are moderators of the ancestor channels of $nodeid
     $notify = vB_Cache::instance(vB_Cache::CACHE_STD)->read('vB_Mod_PostNotify');
     if ($notify === false) {
         $library = vB_Library::instance('usergroup');
         $smodgroups = $library->getSuperModGroups();
         //force to have a non empty array or the query will be unhappy.  It's unlikely that a site will
         //not have any usergroups with the superadmin flag set, but its possible
         if (!$smodgroups) {
             $smodgroups = array(0);
         }
         $notify = array();
         $bitFields = vb::getDatastore()->getValue('bf_misc_moderatorpermissions');
         $modQry = $this->assertor->assertQuery('vBForum:modPostNotify', array('bfPost' => $bitFields['newpostemail'], 'bfTopic' => $bitFields['newthreademail'], 'smodgroups' => $smodgroups));
         $events = array();
         if ($modQry->valid()) {
             foreach ($modQry as $mod) {
                 $events[$mod['userid']] = 'userChg_' . $mod['userid'];
                 //Every time a moderator changes emails, is deleted, etc, we have to invalidate it.
                 if (!isset($notify[$mod['nodeid']])) {
                     $notify[$mod['nodeid']] = array("posts" => array(), "topics" => array());
                 }
                 if ($mod['notifypost'] > 0) {
                     $notify[$mod['nodeid']]['posts'][] = $mod['email'];
                 }
                 if ($mod['notifytopic'] > 0) {
                     $notify[$mod['nodeid']]['topics'][] = $mod['email'];
                 }
             }
         }
         // all these user change events could be a lot...
         $events['vB_ModPostNotifyChg'] = 'vB_ModPostNotifyChg';
         vB_Cache::instance(vB_Cache::CACHE_STD)->write('vB_Mod_PostNotify', $notify, 1440, $events);
     }
     // grab parents of the added node, and see if we have any moderators on the channel
     $parents = vB::getDbAssertor()->getRows('vBForum:closure', array('child' => $nodeid));
     $notifyList = array();
     // the actual list of emails that are associated with this node.
     $node = vB_Library::instance('node')->getNodeFullContent($nodeid);
     $node = $node[$nodeid];
     if ($node['starter'] == $node['nodeid']) {
         $notifyKey = "topics";
     } else {
         $notifyKey = "posts";
     }
     foreach ($parents as $closure) {
         $parentid = $closure['parent'];
         if (array_key_exists($parentid, $notify)) {
             // each found list is an array of emails, so we have to merge
             $notifyList = array_merge($notifyList, $notify[$parentid][$notifyKey]);
         }
     }
     // Global moderators case. At the moment, the global mods in the moderator table has nodeid = 0 so the
     // closure check above leaves them out.
     if (!empty($notify[0])) {
         $notifyList = array_merge($notifyList, $notify[0][$notifyKey]);
     }
     $notifyList = array_unique($notifyList);
     if (empty($notifyList)) {
         return;
     }
     // grab some data for the message
     $userinfo = vB::getCurrentsession()->fetch_userinfo();
     $forumName = vB::getDatastore()->getOption('bbtitle');
     $starter = vB_Library::instance('node')->getNodeFullContent($node['starter']);
     $starter = $starter[$node['starter']];
     $threadTitle = $starter['title'];
     // Below is the call to fetch the url to the thread starter
     // $threadLink = vB5_Route::buildUrl($starter['routeid'] . '|fullurl', $starter);
     // If we want the direct link to the post, below is what's needed
     $routeInfo = array('nodeid' => $nodeid);
     // Using the normal vB5_Route::buildURL can throw an exception, because it'll likely use the
     // conversation route which checks permissions on the *current* user in the constructor and
     // throw an exception.
     // So we'll use vB5_Route_Node
     $nodeLink = vB5_Route::buildUrl('node|fullurl', $routeInfo);
     $message = vB_Phrase::fetchSinglePhrase('new_post_notification_a_b_c_d_e_f', array($userinfo['username'], $node['channeltitle'], $forumName, $threadTitle, $nodeLink, $node['rawtext']));
     $subject = vB_Phrase::fetchSinglePhrase('new_post_in_forum_x', $node['channeltitle']);
     // send emails
     foreach ($notifyList as $email) {
         if ($email != $userinfo['email']) {
             vB_Mail::vbmail($email, $subject, $message, true, '', '', '', TRUE);
         }
     }
 }
예제 #15
0
 /**
  * Send contact us mail
  *
  * @param array $maildata contact us mail data. Including name, email, subject, other_subject, message
  * @param array $hvinput Human Verify input data. @see vB_Api_Hv::verifyToken()
  * @throws vB_Exception_Api
  */
 public function sendMail($maildata, $hvinput = array())
 {
     $vboptions = vB::getDatastore()->getValue('options');
     if (empty($maildata['name']) || empty($maildata['email']) || empty($maildata['message'])) {
         throw new vB_Exception_Api('please_complete_required_fields');
     }
     if ($vboptions['contactusoptions'] and $maildata['subject'] == 'other' and ($maildata['other_subject'] == '' or !$vboptions['contactusother'])) {
         throw new vB_Exception_Api('nosubject');
     }
     if (!is_valid_email($maildata['email'])) {
         throw new vB_Exception_Api('bademail');
     }
     vB_Api::instanceInternal('hv')->verifyToken($hvinput, 'contactus');
     // No Errors. Send mail.
     $languageid = -1;
     if ($vboptions['contactusoptions']) {
         if ($maildata['subject'] == 'other') {
             $maildata['subject'] = $maildata['other_subject'];
         } else {
             $options = explode("\n", trim($vboptions['contactusoptions']));
             foreach ($options as $index => $title) {
                 if ($index == $maildata['subject']) {
                     if (preg_match('#^{(.*)} (.*)$#siU', $title, $matches)) {
                         $title =& $matches[2];
                         if (is_numeric($matches[1]) and intval($matches[1]) !== 0) {
                             $userinfo = vB_User::fetchUserinfo($matches[1]);
                             $alt_email =& $userinfo['email'];
                             $languageid =& $userinfo['languageid'];
                         } else {
                             $alt_email = $matches[1];
                         }
                     }
                     $maildata['subject'] = $title;
                     break;
                 }
             }
         }
     }
     if (!empty($alt_email)) {
         if ($alt_email == $vboptions['webmasteremail'] or $alt_email == $vboptions['contactusemail']) {
             $ip = vB::getRequest()->getIpAddress();
         } else {
             $ip =& $vbphrase['n_a'];
         }
         $destemail =& $alt_email;
     } else {
         $ip = vB::getRequest()->getIpAddress();
         if ($vboptions['contactusemail']) {
             $destemail =& $vboptions['contactusemail'];
         } else {
             $destemail =& $vboptions['webmasteremail'];
         }
     }
     $currentuser = vB::getCurrentSession()->fetch_userinfo();
     $mailcontent = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('contactus', array($vboptions['bbtitle'], $maildata['name'], $maildata['email'], $maildata['message'], $ip, $currentuser['username'], $currentuser['userid']), array($vboptions['bbtitle'], $maildata['subject']), $languageid);
     $flood = vB_Mail::vbmail($destemail, $mailcontent['subject'], $mailcontent['message'], true, $maildata['email']);
     if (is_array($flood)) {
         throw new vB_Exception_Api($flood[0], $flood[1]);
     }
     return true;
 }
예제 #16
0
vB_Mail::vbmailStart();
$emails = '';
foreach ($users as $user) {
    // make random number
    if (empty($user['activationid'])) {
        //none exists so create one
        $user['activationid'] = fetch_random_string(40);
        /*insert query*/
        vB::getDbAssertor()->assertQuery('user_replaceuseractivation2', array('userid' => $user['userid'], 'timenow' => $timenow, 'activateid' => $user['activationid'], 'type' => 0, 'usergroupid' => 0));
    } else {
        $user['activationid'] = fetch_random_string(40);
        vB::getDbAssertor()->update('useractivation', array('dateline' => $timenow, 'activationid' => $user['activationid']), array('userid' => $user['userid'], 'type' => 0));
    }
    $userid = $user['userid'];
    $username = $user['username'];
    $activateid = $user['activationid'];
    $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('activateaccount', array($username, vB::getDatastore()->getOption('bbtitle'), vB::getDatastore()->getOption('frontendurl'), $userid, $activateid, vB::getDatastore()->getOption('webmasteremail')), array(vB::getDatastore()->getOption('bbtitle')), $user['languageid']);
    vB_Mail::vbmail($user['email'], $maildata['subject'], $maildata['message']);
    $emails .= iif($emails, ', ');
    $emails .= $user['username'];
}
if ($emails) {
    log_cron_action($emails, $nextitem, 1);
}
vB_Mail::vbmailEnd();
/*=========================================================================*\
|| #######################################################################
|| # Downloaded: 15:45, Tue Sep 8th 2015
|| # CVS: $RCSfile$ - $Revision: 83432 $
|| #######################################################################
\*=========================================================================*/
예제 #17
0
 /**
  * Additional data to update after a save call (such as denormalized values in other tables).
  *
  * @param	boolean	Do the query?
  */
 function post_save_each($doquery = true)
 {
     $userid = $this->fetch_field('userid');
     if (!$userid or !$doquery) {
         return;
     }
     $usergroups_changed = $this->usergroups_changed();
     if (!empty($this->existing['usergroupid'])) {
         $wasadmin = $this->is_admin($this->existing['usergroupid'], $this->existing['membergroupids']);
     } else {
         $wasadmin = false;
     }
     $isadmin = $this->is_admin($this->fetch_field('usergroupid'), $this->fetch_field('membergroupids'));
     if (!empty($this->existing['usergroupid'])) {
         $wassupermod = $this->is_supermod($this->existing['usergroupid'], $this->existing['membergroupids']);
     } else {
         $wassupermod = false;
     }
     $issupermod = $this->is_supermod($this->fetch_field('usergroupid'), $this->fetch_field('membergroupids'));
     if (!$this->condition) {
         // save user count and new user id to template
         require_once DIR . '/includes/functions_databuild.php';
         build_user_statistics();
     } else {
         // update denormalized username field in various tables
         $this->update_username($userid);
         // if usergroup membership has changed...
         if ($usergroups_changed) {
             // update subscriptions
             $this->update_subscriptions($userid, $doquery);
             // update ban status
             $this->update_ban_status($userid, $doquery);
             // recache permissions if the userid is the current browsing user
             if ($userid == $this->userinfo['userid']) {
                 $this->userinfo['usergroupid'] = $this->fetch_field('usergroupid');
                 $this->userinfo['membergroupids'] = $this->fetch_field('membergroupids');
                 cache_permissions($this->userinfo);
             }
         }
         // if the primary user group has been changed, we need to update any user activation records
         if (!empty($this->user['usergroupid']) and $this->user['usergroupid'] != $this->existing['usergroupid']) {
             $this->assertor->update('useractivation', array('usergroupid' => $this->user['usergroupid']), array('userid' => $userid, 'type' => 0));
         }
         if (isset($this->usertextfield['signature'])) {
             // edited the signature, need to kill any parsed versions
             $this->assertor->delete('vBForum:sigparsed', array('userid' => $userid));
         }
     }
     // admin stuff
     $this->set_admin($userid, $usergroups_changed, $isadmin, $wasadmin);
     // super moderator stuff
     $this->set_supermod($userid, $usergroups_changed, $issupermod, $wassupermod);
     // update birthday datastore
     $this->update_birthday_datastore($userid);
     // update password history
     $this->update_password_history($userid);
     // reset style cookie
     $this->update_style_cookie($userid);
     // reset threadedmode cookie
     $this->update_threadedmode_cookie($userid);
     // reset languageid cookie
     $this->update_language_cookie($userid);
     // Send parent email
     if (isset($this->info['coppauser']) and $this->info['coppauser'] and $username = $this->fetch_field('username') and $parentemail = $this->fetch_field('parentemail')) {
         $vboptions = vB::getDatastore()->getValue('options');
         $memberlink = vB5_Route::buildUrl('profile|fullurl', array('userid' => $userid, 'username' => $username));
         $forumhomelink = vB5_Route::buildUrl('home|fullurl');
         if ($password = $this->info['coppapassword']) {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('parentcoppa_register', array($username, $vboptions['bbtitle'], $forumhomelink, $memberlink, $vboptions['privacyurl'], $password), array($username, $vboptions['bbtitle']));
         } else {
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('parentcoppa_profile', array($username, $vboptions['bbtitle'], $forumhomelink, $vboptions['privacyurl'], $memberlink), array($username, $vboptions['bbtitle']));
         }
         //$subject and $message are magic variables created by the code returned from fetch_email_phrase
         //when it gets returned.
         vB_Mail::vbmail($parentemail, $maildata['subject'], $maildata['message'], true);
     }
     vB_Cache::instance(vB_Cache::CACHE_FAST)->event("userData_{$userid}");
     // Legacy Hook 'userdata_postsave' Removed //
 }
예제 #18
0
 /**
  * Saves an uploaded file into the filedata system.
  *
  * @param	int		$userid				Id of user uploading the image. This user's permissions will be checked when necessary
  * @param	array	$filearray			Array of data describing the uploaded file with data-types & keys:
  *											string	'name'			Filename
  *											int		'size'			Filesize
  *											string	'type'			Filetype
  *											string	'tmp_name'		Filepath to the temporary file created on the server
  *											int		'parentid'		Optional. Node/Channelid this file will be uploaded under. If provided
  *																	permissions will be checked under this node.
  *											bool	'is_sigpic'		Optional. If this is not empty, the saved filedata will replace
  *																	the user's sigpicnew record (or inserted for the user if none exists),
  *																	and the filedata record will have refcount incremented & publicview
  *																	set to 1.
  * @param	string	$fileContents		String(?) containing file content BLOB
  * @param	int		$filesize			File size
  * @param	string	$extension			File extension
  * @param	bool	$imageOnly			If true, this function will throw an exception if the file is not an image
  * @param	bool	$skipUploadPermissionCheck		Optional boolean to skip permission checks. Only used internally when the system
  *													saves a theme icon. Do not use for normal calls to this function.
  *
  * @return	array	Array of saved filedata info with data-types & keys:
  *						int 		'filedataid'
  *						int 		'filesize'
  *						int			'thumbsize'		file size of the thumbnail of the saved filedata
  *						string		'extension'
  *						string		'filename'
  *						string[]	'headers'		array containing the content-type http header of the saved filedata
  *						boolean		'isimage'
  *
  * @throws	vB_Exception_Api('invalid_attachment_storage')	If 'attachfile' ("Save attachments as File") is enabled and the path specified
  *															by 'attachpath' option is not writable for some reason
  * @throws	vB_Exception_Api('dangerous_image_rejected')	If image verification failed for $fileContents or $filearray['tmp_name']
  * @throws	vB_Exception_Api('upload_attachfull_total')		If attachment quota specified by 'attachtotalspace' option is exceeded
  * @throws	vB_Exception_Api('cannot_create_file')			If the user fails the permission checks
  * @throws	vB_Exception_Api('upload_invalid_image')		If $imageOnly is true and the uploaded file is not an image
  * @throws	vB_Exception_Api('unable_to_add_filedata')		If adding the filedata record failed
  * @throws	vB_Exception_Api('attachpathfailed')			If 'attachfile' ("Save attachments as File") is enabled and creating or fetching
  *															the path to the attachment directory for the user failed
  * @throws	vB_Exception_Api('upload_file_system_is_not_writable_path')		If 'attachfile' ("Save attachments as File") is enabled and the
  *															path retrieved for the user is not writable.
  *
  * @access	public
  */
 public function saveUpload($userid, $filearray, $fileContents, $filesize, $extension, $imageOnly = false, $skipUploadPermissionCheck = false)
 {
     $assertor = vB::getDbAssertor();
     $datastore = vB::getDatastore();
     $options = $datastore->getValue('options');
     $config = vB::getConfig();
     $usercontext = vB::getUserContext($userid);
     //make sure there's a place to put attachments.
     if ($options['attachfile'] and (empty($options['attachpath']) or !file_exists($options['attachpath']) or !is_writable($options['attachpath']) or !is_dir($options['attachpath']))) {
         throw new vB_Exception_Api('invalid_attachment_storage');
     }
     //make sure the file is good.
     if (!$this->imageHandler->verifyImageFile($fileContents, $filearray['tmp_name'])) {
         @unlink($filearray['tmp_name']);
         throw new vB_Exception_Api('dangerous_image_rejected');
     }
     // Check if this is an image extension we're dealing with for displaying later.
     // exif_imagetype() will check the validity of image
     $isImageExtension = $isImage = $this->imageHandler->isImage($extension);
     if ($isImage and function_exists('exif_imagetype')) {
         $imageType = @exif_imagetype($filearray['tmp_name']);
         $isImage = (bool) $imageType;
     } else {
         if ($isImage and function_exists('finfo_open') and function_exists('finfo_file')) {
             /*
              * TODO: When pdf thumbnail support is fixed, this check might have to be updated.
              */
             // Just in case exif_imagetype is not there. finfo extension should be installed
             // by default (except windows), and is an alternative way to detect
             // if this is an image.
             // In the future, perhaps we can just use below to set the mimetype in the database,
             // and have the fetchImage functions return the mimetype as well rather than
             // trying to set it based on the filedata.extension (which may not be correct).
             $finfo = finfo_open(FILEINFO_MIME_TYPE);
             $mimetype = finfo_file($finfo, $filearray['tmp_name']);
             if ($mimetype) {
                 $mimetype = explode('/', $mimetype);
                 $toplevel = $mimetype[0];
                 if ($toplevel != 'image') {
                     $isImage = false;
                 }
             } else {
                 $isImage = false;
             }
         }
     }
     /*
      *	Note, this is for identification only, NOT for security!
      *	If we're going to depend on the extension to determine if it's an image,
      *	let's at least check that it's an image.
      */
     if ($isImageExtension and !$isImage) {
         // Do not allow a non-image to use an image extension.
         throw new vB_Exception_Api('image_extension_but_wrong_type');
     }
     // Thumbnails are a different story altogether. Something like a PDF
     // might have a thumbnail.
     $canHaveThumbnail = $this->imageHandler->imageThumbnailSupported($extension);
     /*
      * TODO: We might want to check that the extension matches the mimetype.
      *
      */
     //We check to see if this file already exists.
     $filehash = md5($fileContents);
     $fileCheck = $assertor->getRow('vBForum:getFiledataWithThumb', array('filehash' => $filehash, 'filesize' => $filesize));
     // Does filedata already exist?
     if (empty($fileCheck) or $fileCheck['userid'] != $userid) {
         // Check if we are not exceeding the quota
         if ($options['attachtotalspace'] > 0) {
             $usedSpace = $assertor->getField('vBForum:getUserFiledataFilesizeSum', array('userid' => $userid));
             $overage = $usedSpace + $filesize - $options['attachtotalspace'];
             if ($overage > 0) {
                 $overage = vb_number_format($overage, 1, true);
                 $userinfo = vB::getCurrentSession()->fetch_userinfo();
                 $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('attachfull', array($userinfo['username'], $options['attachtotalspace'], $options['bburl'], 'admincp'), array($options['bbtitle']), 0);
                 vB_Mail::vbmail($options['webmasteremail'], $maildata['subject'], $maildata['message']);
                 throw new vB_Exception_Api('upload_attachfull_total', $overage);
             }
         }
         // Can we move this permission check out of this library function?
         if (!$usercontext->canUpload($filesize, $extension, !empty($filearray['parentid']) ? $filearray['parentid'] : false) and !$skipUploadPermissionCheck) {
             @unlink($filearray['tmp_name']);
             throw new vB_Exception_Api('cannot_create_file');
         }
         if ($imageOnly and !$isImage) {
             throw new vB_Exception_Api('upload_invalid_image');
         }
         $timenow = vB::getRequest()->getTimeNow();
         if ($canHaveThumbnail) {
             //Get the image size information.
             $imageInfo = $this->imageHandler->fetchImageInfo($filearray['tmp_name']);
             $sizes = @unserialize($options['attachresizes']);
             if (!isset($sizes['thumb']) or empty($sizes['thumb'])) {
                 $sizes['thumb'] = 100;
             }
             $thumbnail = $this->imageHandler->fetchThumbnail($filearray['name'], $filearray['tmp_name'], $sizes['thumb'], $sizes['thumb'], $options['thumbquality']);
         } else {
             $thumbnail = array('filesize' => 0, 'width' => 0, 'height' => 0, 'filedata' => null);
         }
         $thumbnail_data = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'resize_type' => 'thumb', 'resize_dateline' => $timenow, 'resize_filesize' => $thumbnail['filesize'], 'resize_width' => $thumbnail['width'], 'resize_height' => $thumbnail['height']);
         // Note, unless this is a sigpic (defined as !empty($filearray['is_sigpic'])), below will set
         // the refcount of the new filedata record to 0.
         // So the caller MUST increment the refcount if this image should not be removed by the cron.
         $data = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'userid' => $userid, 'dateline' => $timenow, 'filesize' => $filesize, 'filehash' => $filehash, 'extension' => $extension, 'refcount' => 0);
         if (!empty($imageInfo)) {
             $data['width'] = $imageInfo[0];
             $data['height'] = $imageInfo[1];
         }
         //Looks like we're ready to store. But do we put it in the database or the filesystem?
         if ($options['attachfile']) {
             //We name the files based on the filedata record, but we don't have that until we create the record. So we need
             // to do an insert, then create/move the files.
             $filedataid = $assertor->assertQuery('filedata', $data);
             if (is_array($filedataid)) {
                 $filedataid = $filedataid[0];
             }
             if (!intval($filedataid)) {
                 throw new vB_Exception_Api('unable_to_add_filedata');
             }
             $path = $this->verifyAttachmentPath($userid);
             if (!$path) {
                 throw new vB_Exception_Api('attachpathfailed');
             }
             if (!is_writable($path)) {
                 throw new vB_Exception_Api('upload_file_system_is_not_writable_path', array(htmlspecialchars($path)));
             }
             if (!empty($thumbnail['filedata'])) {
                 file_put_contents($path . $filedataid . '.thumb', $thumbnail['filedata']);
             }
             rename($filearray['tmp_name'], $path . $filedataid . '.attach');
         } else {
             //We put the file contents into the data record.
             $data['filedata'] = $fileContents;
             $filedataid = $assertor->assertQuery('filedata', $data);
             if (is_array($filedataid)) {
                 $filedataid = $filedataid[0];
             }
             $thumbnail_data['resize_filedata'] = $thumbnail['filedata'];
         }
         $thumbnail_data['filedataid'] = $filedataid;
         if ($canHaveThumbnail) {
             $assertor->assertQuery('vBForum:filedataresize', $thumbnail_data);
         }
         if (!empty($filearray['name'])) {
             $filename = $filearray['name'];
         } else {
             $filename = '';
         }
         $result = array('filedataid' => $filedataid, 'filesize' => $filesize, 'thumbsize' => $thumbnail['filesize'], 'extension' => $extension, 'filename' => $filename, 'headers' => $this->getAttachmentHeaders(strtolower($extension)), 'isimage' => $isImage);
         if (!empty($filearray['is_sigpic'])) {
             $assertor->assertQuery('replaceSigpic', array('userid' => $userid, 'filedataid' => $filedataid));
             $assertor->assertQuery('incrementFiledataRefcountAndMakePublic', array('filedataid' => $filedataid));
         }
     } else {
         // file already exists so we are not going to insert a new one
         $filedataid = $fileCheck['filedataid'];
         if (!empty($filearray['is_sigpic'])) {
             // Get old signature picture data and decrease refcount
             $oldfiledata = vB::getDbAssertor()->getRow('vBForum:sigpicnew', array('userid' => $userid));
             if ($oldfiledata) {
                 vB::getDbAssertor()->assertQuery('decrementFiledataRefcount', array('filedataid' => $oldfiledata['filedataid']));
             }
             $assertor->assertQuery('replaceSigpic', array('userid' => $fileCheck['userid'], 'filedataid' => $filedataid));
             $assertor->assertQuery('incrementFiledataRefcountAndMakePublic', array('filedataid' => $filedataid));
         }
         $result = array('filedataid' => $filedataid, 'filesize' => $fileCheck['filesize'], 'thumbsize' => $fileCheck['resize_filesize'], 'extension' => $extension, 'filename' => $filearray['name'], 'headers' => $this->getAttachmentHeaders(strtolower($extension)), 'isimage' => $isImage);
     }
     return $result;
 }
예제 #19
0
 function check_attachment_overage($filehash, $filesize)
 {
     if ($this->registry->options['attachtotalspace']) {
         $filedata = $this->registry->db->query_first_slave("\n\t\t\t\tSELECT SUM(filesize) AS sum\n\t\t\t\tFROM " . TABLE_PREFIX . "filedata\n\t\t\t\tWHERE filehash <> '" . $this->registry->db->escape_string($filehash) . "'\n\t\t\t");
         // Legacy Hook 'upload_attachsum_total' Removed //
         if ($filedata['sum'] + $filesize > $this->registry->options['attachtotalspace']) {
             $overage = vb_number_format($filedata['sum'] + $filesize - $this->registry->options['attachtotalspace'], 1, true);
             global $vbulletin;
             $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('attachfull', array($vbulletin->userinfo['username'], $vbulletin->options['attachtotalspace'], $vbulletin->options['bburl'], 'admincp'), array($vbulletin->options['bbtitle']), 0);
             vB_Mail::vbmail($this->registry->options['webmasteremail'], $maildata['subject'], $maildata['message']);
             $this->set_error('upload_attachfull_total', $overage);
             return false;
         }
     }
     if ($this->userinfo['permissions']['attachlimit']) {
         $attachdata = $this->registry->db->query_first_slave("\n\t\t\t\tSELECT SUM(filesize) AS sum\n\t\t\t\tFROM\n\t\t\t\t(\n\t\t\t\t\tSELECT DISTINCT fd.filedataid, fd.filesize\n\t\t\t\t\tFROM " . TABLE_PREFIX . "attachment AS a\n\t\t\t\t\tINNER JOIN " . TABLE_PREFIX . "filedata AS fd ON (fd.filedataid = a.filedataid)\n\t\t\t\t\tWHERE\n\t\t\t\t\t\ta.userid = " . $this->userinfo['userid'] . "\n\t\t\t\t\t\t\tAND\n\t\t\t\t\t\tfilehash <> '" . $this->registry->db->escape_string($filehash) . "'\n\t\t\t\t) AS x\n\t\t\t");
         // Legacy Hook 'upload_attachsum_user' Removed //
         if ($attachdata['sum'] + $filesize > $this->userinfo['permissions']['attachlimit']) {
             $overage = vb_number_format($attachdata['sum'] + $filesize - $this->userinfo['permissions']['attachlimit'], 1, true);
             $this->set_error('upload_attachfull_user', $overage, vB::getCurrentSession()->get('sessionurl'));
             return false;
         }
     }
     return true;
 }