3646 lines
88 KiB
PHP
3646 lines
88 KiB
PHP
<?php
|
|
/*
|
|
* b1gMail
|
|
* Copyright (c) 2021 Patrick Schlangen et al
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
if(!defined('B1GMAIL_INIT'))
|
|
die('Directly calling this file is not supported');
|
|
|
|
/**
|
|
* user class
|
|
*/
|
|
class BMUser
|
|
{
|
|
var $_id;
|
|
var $_row;
|
|
|
|
/**
|
|
* constructor
|
|
*
|
|
* @param int $id User ID
|
|
* @return BMUser
|
|
*/
|
|
function __construct($id)
|
|
{
|
|
$this->_id = $id;
|
|
$this->_row = $this->Fetch();
|
|
}
|
|
|
|
/**
|
|
* get user's group
|
|
*
|
|
* @return BMGroup
|
|
*/
|
|
public function GetGroup()
|
|
{
|
|
return(_new('BMGroup', array($this->_row['gruppe'])));
|
|
}
|
|
|
|
/**
|
|
* check if user is allowed to send email (check send limit)
|
|
*
|
|
* @param $recipientCount Number of recipients
|
|
* @return bool
|
|
*/
|
|
public function MaySendMail($recipientCount)
|
|
{
|
|
global $db;
|
|
|
|
$group = $this->GetGroup();
|
|
$groupRow = $group->Fetch();
|
|
|
|
if($recipientCount < 1)
|
|
return(false);
|
|
|
|
if($groupRow['send_limit_count'] <= 0 || $groupRow['send_limit_time'] <= 0)
|
|
return(true);
|
|
|
|
if($recipientCount > $groupRow['send_limit_count'])
|
|
return(false);
|
|
|
|
$res = $db->Query('SELECT SUM(`recipients`) FROM {pre}sendstats WHERE `userid`=? AND `time`>=?',
|
|
$this->_id,
|
|
time() - 60 * $groupRow['send_limit_time']);
|
|
$row = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
$count = (int)$row[0];
|
|
|
|
return($count + $recipientCount <= $groupRow['send_limit_count']);
|
|
}
|
|
|
|
/**
|
|
* add email to send stats (for send limit)
|
|
*
|
|
* @param $recipientCount Number of recipients
|
|
*/
|
|
public function AddSendStat($recipientCount)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}sendstats(`userid`,`recipients`,`time`) VALUES(?,?,?)',
|
|
$this->_id,
|
|
max(1, $recipientCount),
|
|
time());
|
|
}
|
|
|
|
/**
|
|
* add email to receive stats (for incoming limits)
|
|
*
|
|
* @param int $size Size of email
|
|
*/
|
|
public function AddRecvStat($size)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}recvstats(`userid`,`size`,`time`) VALUES(?,?,?)',
|
|
$this->_id,
|
|
$size,
|
|
time());
|
|
}
|
|
|
|
/**
|
|
* Get count of received mails since a certain time.
|
|
*
|
|
* @param int $since Start time
|
|
* @return int Count
|
|
*/
|
|
public function GetReceivedMailsCount($since)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}recvstats WHERE `userid`=? AND `time`>=?',
|
|
$this->_id,
|
|
$since);
|
|
list($result) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return((int)$result);
|
|
}
|
|
|
|
/**
|
|
* Get size of received mails since a certain time.
|
|
*
|
|
* @param int $since Start time
|
|
* @return int Size in bytes
|
|
*/
|
|
public function GetReceivedMailsSize($since)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT SUM(`size`) FROM {pre}recvstats WHERE `userid`=? AND `time`>=?',
|
|
$this->_id,
|
|
$since);
|
|
list($result) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return((int)$result);
|
|
}
|
|
|
|
/**
|
|
* get unread notifications count
|
|
*
|
|
* @return int
|
|
*/
|
|
public function GetUnreadNotifications()
|
|
{
|
|
global $db;
|
|
|
|
$result = 0;
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}notifications WHERE `userid`=? AND `read`=0 AND (`expires`=0 OR `expires`<?)',
|
|
$this->_id,
|
|
time(),
|
|
time());
|
|
while($row = $res->FetchArray(MYSQLI_NUM))
|
|
{
|
|
$result = (int)$row[0];
|
|
}
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get latest notifications
|
|
*
|
|
* @param bool $markRead Whether to mark all notifications as read after fetching them
|
|
* @return array
|
|
*/
|
|
public function GetNotifications($markRead = true)
|
|
{
|
|
global $db, $tpl, $lang_custom;
|
|
|
|
$result = array();
|
|
|
|
$res = $db->Query('SELECT `notificationid`,`date`,`read`,`flags`,`text_phrase`,`text_params`,`link`,`icon` FROM {pre}notifications WHERE `userid`=? AND (`expires`=0 OR `expires`<?) ORDER BY `notificationid` DESC LIMIT ' . NOTIFICATION_LIMIT,
|
|
$this->_id,
|
|
time(),
|
|
time());
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
switch ($row['icon']) {
|
|
case '%%tpldir%%images/li/notify_newemail.png':
|
|
$row['faIcon'] = str_replace('%%tpldir%%images/li/notify_newemail.png', 'fa-envelope-square', $row['icon']);
|
|
break;
|
|
case '%%tpldir%%images/li/notify_email.png':
|
|
$row['faIcon'] = str_replace('%%tpldir%%images/li/notify_email.png', 'fa-envelope-o', $row['icon']);
|
|
break;
|
|
case '%%tpldir%%images/li/notify_birthday.png':
|
|
$row['faIcon'] = str_replace('%%tpldir%%images/li/notify_birthday.png', 'fa-birthday-cake', $row['icon']);
|
|
break;
|
|
case '%%tpldir%%images/li/notify_calendar.png':
|
|
$row['faIcon'] = str_replace('%%tpldir%%images/li/notify_calendar.png', 'fa-calendar', $row['icon']);
|
|
break;
|
|
}
|
|
$row['icon'] = str_replace('%%tpldir%%', $tpl->tplDir, $row['icon']);
|
|
|
|
if(($row['flags'] & NOTIFICATION_FLAG_USELANG) != 0)
|
|
$row['text_phrase'] = $lang_custom[ $row['text_phrase'] ];
|
|
|
|
$row['text'] = vsprintf($row['text_phrase'], ExplodeOutsideOfQuotation($row['text_params'], ','));
|
|
|
|
$row['old'] = $row['read'] && $row['date'] < mktime(0, 0, 0);
|
|
|
|
$result[] = $row;
|
|
}
|
|
$res->Free();
|
|
|
|
if($markRead)
|
|
{
|
|
$db->Query('UPDATE {pre}notifications SET `read`=1 WHERE `userid`=? AND (`expires`=0 OR `expires`<?)',
|
|
$this->_id,
|
|
time(),
|
|
time());
|
|
}
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* post a new notification
|
|
*
|
|
* @param string $textPhrase Text phrase or key in $lang_custom array when used with NOTIFICATION_FLAG_USELANG
|
|
* @param array $textParams Parameters array for format string
|
|
* @param string $link Notification link
|
|
* @param string $icon Icon path (can use %%tpldir%% variable)
|
|
* @param int $date Notification date (0 = now)
|
|
* @param int $expires Expiration date (0 = never)
|
|
* @param int $flags Flags
|
|
* @param string $class Unique name of notification class (optional)
|
|
* @param bool $uniqueClass Set to true to remove all previous notifications of the same class
|
|
* @return int Notification ID
|
|
*/
|
|
public function PostNotification($textPhrase, $textParams = array(), $link = '', $icon = '', $date = 0, $expires = 0, $flags = 0, $class = '', $uniqueClass = false)
|
|
{
|
|
global $db;
|
|
|
|
if($date == 0)
|
|
$date = time();
|
|
|
|
if(count($textParams))
|
|
$textParams = '"' . implode('","', array_map('addslashes', $textParams)) . '"';
|
|
else
|
|
$textParams = '';
|
|
|
|
if($uniqueClass && !empty($class))
|
|
{
|
|
$db->Query('DELETE FROM {pre}notifications WHERE `userid`=? AND `class`=?',
|
|
$this->_id,
|
|
$class);
|
|
}
|
|
|
|
$db->Query('INSERT INTO {pre}notifications(`userid`,`date`,`expires`,`flags`,`text_phrase`,`text_params`,`link`,`icon`,`class`) '
|
|
. 'VALUES(?,?,?,?,?,?,?,?,?)',
|
|
$this->_id,
|
|
$date,
|
|
$expires,
|
|
$flags,
|
|
$textPhrase,
|
|
$textParams,
|
|
$link,
|
|
$icon,
|
|
$class);
|
|
return($db->InsertId());
|
|
}
|
|
|
|
/**
|
|
* check if user may see SMS stuff
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function SMSEnabled()
|
|
{
|
|
global $bm_prefs, $db;
|
|
|
|
$this->Fetch();
|
|
|
|
$group = $this->GetGroup();
|
|
$groupRow = $group->Fetch();
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}smsgateways');
|
|
list($gatewayCount) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($gatewayCount > 0
|
|
&& ($this->GetStaticBalance() > 0
|
|
|| $groupRow['mail2sms'] == 'yes'
|
|
|| $groupRow['sms_monat'] > 0
|
|
|| $bm_prefs['sms_enable_charge'] == 'yes'));
|
|
}
|
|
|
|
/**
|
|
* update bayes training values for user
|
|
*
|
|
* @param int $nonSpam Count of NON spam mails
|
|
* @param int $spam Count of spam mails
|
|
* @param int $userID User ID
|
|
* @return bool
|
|
*/
|
|
public static function UpdateBayesValues($nonSpam, $spam, $userID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}users SET bayes_nonspam=?, bayes_spam=? WHERE id=?',
|
|
$nonSpam,
|
|
$spam,
|
|
$userID);
|
|
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get bayes training values for an user
|
|
*
|
|
* @param int $userID
|
|
* @return array bayes_nonspam, bayes_spam, bayes_border (%)
|
|
*/
|
|
public static function GetBayesValues($userID)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT bayes_nonspam,bayes_spam,bayes_border FROM {pre}users WHERE id=?',
|
|
$userID);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
$ret = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
}
|
|
else
|
|
$ret = array(0, 0, 90);
|
|
|
|
return($ret);
|
|
}
|
|
|
|
/**
|
|
* set preference
|
|
*
|
|
* @param string $key Key
|
|
* @param string $value Value
|
|
* @return bool
|
|
*/
|
|
public function SetPref($key, $value)
|
|
{
|
|
global $db;
|
|
$db->Query('REPLACE INTO {pre}userprefs(userID, `key`,`value`) VALUES(?, ?, ?)',
|
|
(int)$this->_id,
|
|
$key,
|
|
$value);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get preference
|
|
*
|
|
* @param string $key Key
|
|
* @return string
|
|
*/
|
|
public function GetPref($key)
|
|
{
|
|
global $db;
|
|
$res = $db->Query('SELECT `value` FROM {pre}userprefs WHERE userID=? AND `key`=?',
|
|
(int)$this->_id,
|
|
$key);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
$row = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
return($row[0]);
|
|
}
|
|
else
|
|
{
|
|
$res->Free();
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* delete preference
|
|
*
|
|
* @param string $key Key
|
|
* @return bool
|
|
*/
|
|
public function DeletePref($key)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}userprefs WHERE userID=? AND `key`=?',
|
|
(int)$this->_id,
|
|
$key);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* check if address is locked
|
|
*
|
|
* @param string $userm
|
|
* @return bool
|
|
*/
|
|
public static function AddressLocked($userm)
|
|
{
|
|
global $db;
|
|
|
|
$userm = strtolower($userm);
|
|
$locked = false;
|
|
$res = $db->Query('SELECT * FROM {pre}locked');
|
|
while($row = $res->FetchObject())
|
|
{
|
|
$laenge = strlen($row->benutzername);
|
|
$row->benutzername = strtolower($row->benutzername);
|
|
|
|
if(($row->typ == 'start') && (preg_match('/^' . preg_quote($row->benutzername) . '/i', $userm)))
|
|
{
|
|
$locked = true;
|
|
}
|
|
else if(($row->typ == 'ende') && (preg_match('/' . preg_quote($row->benutzername). '$/i', $userm)))
|
|
{
|
|
$locked = true;
|
|
}
|
|
else if(($row->typ == 'mitte') && (strstr($userm, $row->benutzername) !== false))
|
|
{
|
|
$locked = true;
|
|
}
|
|
else if(($row->typ == 'gleich') && ($row->benutzername == $userm))
|
|
{
|
|
$locked = true;
|
|
}
|
|
}
|
|
$res->Free();
|
|
|
|
if(!$locked)
|
|
{
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}workgroups WHERE email=?',
|
|
$userm);
|
|
list($wgCount) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
if($wgCount > 0)
|
|
$locked = true;
|
|
}
|
|
|
|
return($locked);
|
|
}
|
|
|
|
/**
|
|
* check address availability
|
|
*
|
|
* @param string $address
|
|
* @return bool
|
|
*/
|
|
public static function AddressAvailable($address)
|
|
{
|
|
global $db;
|
|
|
|
if(BMUser::GetID($address) != 0)
|
|
return(false);
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}workgroups WHERE `email`=?',
|
|
$address);
|
|
list($wgCount) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($wgCount == 0);
|
|
}
|
|
|
|
/**
|
|
* check address validity
|
|
*
|
|
* @param string $address
|
|
* @return bool
|
|
*/
|
|
public static function AddressValid($address, $forRegistration = true)
|
|
{
|
|
@list($preAt, $afterAt) = explode('@', $address);
|
|
if(preg_match('/^[a-zA-Z0-9&\'\\.\\-_\\+]+@[a-zA-Z0-9.-]+\\.+[a-zA-Z]{2,12}$/', $address) == 1)
|
|
if($forRegistration && (substr($preAt, -1) == '.' || substr($preAt, -1) == '_' || substr($preAt, -1) == '-' || substr($preAt, 0, 1) == '.' || substr($preAt, 0, 1) == '_' || substr($preAt, 0, 1) == '-'
|
|
|| strpos($preAt, '..') !== false))
|
|
return(false);
|
|
else
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* update last send timestamp and recipient count
|
|
*
|
|
* @param int $recipientCount Recipient count
|
|
* @return bool
|
|
*/
|
|
public function UpdateLastSend($recipientCount = 1)
|
|
{
|
|
global $db;
|
|
$db->Query('UPDATE {pre}users SET last_send=?,sent_mails=sent_mails+? WHERE id=?',
|
|
time(),
|
|
(int)$recipientCount,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* update receive count
|
|
*
|
|
* @param int $mailCount Mail count
|
|
* @return bool
|
|
*/
|
|
public function UpdateLastReceive($mailCount = 1)
|
|
{
|
|
global $db;
|
|
$db->Query('UPDATE {pre}users SET received_mails=received_mails+? WHERE id=?',
|
|
(int)$mailCount,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* password reset / activation
|
|
*
|
|
* @param int $userID User ID
|
|
* @param string $resetKey Reset key
|
|
*/
|
|
public function ResetPassword($userID, $resetKey)
|
|
{
|
|
global $db;
|
|
|
|
$result = false;
|
|
|
|
// prepare variables
|
|
$userID = (int)$userID;
|
|
$resetKey = trim($resetKey);
|
|
|
|
// do not accept empty keys
|
|
if(strlen($resetKey) == 32
|
|
&& $userID > 0)
|
|
{
|
|
// check key, activate password
|
|
$db->Query('UPDATE {pre}users SET passwort=pw_reset_new,pw_reset_new=?,pw_reset_key=? WHERE id=? AND LENGTH(pw_reset_new)=32 AND LENGTH(pw_reset_key)=32 AND pw_reset_key=?',
|
|
'',
|
|
'',
|
|
$userID,
|
|
$resetKey);
|
|
$result = ($db->AffectedRows() == 1);
|
|
}
|
|
|
|
// log & return
|
|
if($result)
|
|
{
|
|
// log
|
|
PutLog(sprintf('Password reset for user <%d> confirmed (key: %s, IP: %s)',
|
|
$userID,
|
|
$resetKey,
|
|
$_SERVER['REMOTE_ADDR']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
// log
|
|
PutLog(sprintf('Password reset for user <%d> failed (key: %s, IP: %s)',
|
|
$userID,
|
|
$resetKey,
|
|
$_SERVER['REMOTE_ADDR']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* password reset request
|
|
*
|
|
* @param string $email User's E-Mail address
|
|
* @return bool
|
|
*/
|
|
public static function LostPassword($email)
|
|
{
|
|
global $db, $bm_prefs, $lang_custom;
|
|
|
|
// user ID?
|
|
$userID = BMUser::GetID($email, true);
|
|
if($userID > 0)
|
|
{
|
|
// get alt. mail address
|
|
$res = $db->Query('SELECT altmail,vorname,nachname,anrede,passwort_salt FROM {pre}users WHERE id=?',
|
|
$userID);
|
|
list($altMail, $firstName, $lastName, $salutation, $salt) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
// extract mail address
|
|
$altMail = ExtractMailAddress($altMail);
|
|
|
|
// alt mail specified?
|
|
if(strlen(trim($altMail)) > 5)
|
|
{
|
|
// generate new password
|
|
$pwResetNew = '';
|
|
for($i=0; $i<PASSWORD_LENGTH; $i++)
|
|
$pwResetNew .= substr(PASSWORD_CHARS, mt_rand(0, strlen(PASSWORD_CHARS)-1), 1);
|
|
|
|
// generate key
|
|
$pwResetKey = GenerateRandomKey('pwResetKey');
|
|
|
|
// update row
|
|
$db->Query('UPDATE {pre}users SET pw_reset_new=?,pw_reset_key=? WHERE id=?',
|
|
md5(md5($pwResetNew).$salt),
|
|
$pwResetKey,
|
|
$userID);
|
|
|
|
// link
|
|
$vars = array(
|
|
'mail' => DecodeEMail($email),
|
|
'anrede' => ucfirst($salutation),
|
|
'vorname' => $firstName,
|
|
'nachname' => $lastName,
|
|
'passwort' => $pwResetNew,
|
|
'link' => sprintf('%sindex.php?action=resetPassword&user=%d&key=%s',
|
|
$bm_prefs['selfurl'],
|
|
$userID,
|
|
$pwResetKey)
|
|
);
|
|
if(SystemMail($bm_prefs['passmail_abs'],
|
|
$altMail,
|
|
$lang_custom['passmail_sub'],
|
|
'passmail_text',
|
|
$vars))
|
|
{
|
|
// log
|
|
PutLog(sprintf('User <%s> (%d) requested password reset (IP: %s)',
|
|
$email,
|
|
$userID,
|
|
$_SERVER['REMOTE_ADDR']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* create a new account
|
|
*
|
|
* @param string $email
|
|
* @param string $firstname
|
|
* @param string $surname
|
|
* @param string $street
|
|
* @param string $no
|
|
* @param string $zip
|
|
* @param string $city
|
|
* @param int $country
|
|
* @param string $phone
|
|
* @param string $fax
|
|
* @param string $altmail
|
|
* @param string $mobile_nr
|
|
* @param string $password
|
|
* @param array $profilefields
|
|
* @param bool $allowNotification
|
|
* @return int User ID
|
|
*/
|
|
public static function CreateAccount($email, $firstname, $surname, $street, $no, $zip, $city, $country, $phone, $fax, $altmail, $mobile_nr, $password, $profilefields = array(), $allowNotification = true, $c_uid = '', $salutation = '', $createLocked = false)
|
|
{
|
|
global $db, $bm_prefs, $currentCharset, $currentLanguage, $lang_custom;
|
|
|
|
// serialize profile fields
|
|
if(!is_array($profilefields))
|
|
$profilefields = array();
|
|
$profilefields = serialize($profilefields);
|
|
|
|
// check if user already exists and if address is valid
|
|
if(BMUser::AddressAvailable($email)
|
|
&& BMUser::AddressValid($email))
|
|
{
|
|
$defaultGroupRow = (new BMGroup(-1))->Fetch($bm_prefs['std_gruppe']);
|
|
$instantHTML = $defaultGroupRow['soforthtml'];
|
|
|
|
// status?
|
|
if(ADMIN_MODE)
|
|
{
|
|
$userStatus = 'no';
|
|
}
|
|
else
|
|
{
|
|
if($bm_prefs['reg_validation'] != 'off' || $createLocked)
|
|
$userStatus = 'locked';
|
|
else
|
|
$userStatus = $bm_prefs['usr_status'];
|
|
}
|
|
|
|
// validation code?
|
|
if(($bm_prefs['reg_validation'] == 'sms'
|
|
&& trim($mobile_nr) != '')
|
|
|| ($bm_prefs['reg_validation'] == 'email'
|
|
&& trim($altmail) != ''))
|
|
{
|
|
$ValidationCode = '';
|
|
for($i=0; $i<VALIDATIONCODE_LENGTH; $i++)
|
|
$ValidationCode .= substr(VALIDATIONCODE_CHARS, mt_rand(0, strlen(VALIDATIONCODE_CHARS)-1), 1);
|
|
}
|
|
else
|
|
$ValidationCode = '';
|
|
|
|
// create salt
|
|
$salt = GenerateRandomSalt(8);
|
|
|
|
// create account
|
|
$db->Query('INSERT INTO {pre}users(email,vorname,nachname,strasse,hnr,plz,ort,land,tel,fax,altmail,mail2sms_nummer,passwort,passwort_salt,gruppe,gesperrt,mail2sms,c_firstday,lastlogin,reg_ip,reg_date,profilfelder,datumsformat,charset,language,soforthtml,uid,sms_validation_code,sms_validation_last_send,sms_validation_send_times,anrede,preview) '
|
|
. 'VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,\'no\',\'1\',?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
|
|
$email,
|
|
$firstname,
|
|
$surname,
|
|
$street,
|
|
$no,
|
|
$zip,
|
|
$city,
|
|
$country,
|
|
$phone,
|
|
$fax,
|
|
$altmail,
|
|
$mobile_nr,
|
|
!LooksLikeMD5Hash($password) ? md5(md5($password).$salt) : md5($password.$salt),
|
|
$salt,
|
|
$bm_prefs['std_gruppe'],
|
|
$userStatus,
|
|
0,
|
|
$_SERVER['REMOTE_ADDR'],
|
|
time(),
|
|
$profilefields,
|
|
$bm_prefs['datumsformat'],
|
|
$currentCharset,
|
|
$currentLanguage,
|
|
$instantHTML,
|
|
$c_uid,
|
|
$ValidationCode,
|
|
$ValidationCode != '' ? time() : 0,
|
|
0,
|
|
$salutation,
|
|
'yes');
|
|
$uid = $db->InsertId();
|
|
|
|
// prefs
|
|
if($bm_prefs['hotkeys_default'] == 'yes')
|
|
{
|
|
$db->Query('INSERT INTO {pre}userprefs(`userid`,`key`,`value`) VALUES(?,?,?)',
|
|
$uid,
|
|
'hotkeys',
|
|
1);
|
|
}
|
|
|
|
// send notify mail
|
|
if($allowNotification && $bm_prefs['notify_mail'] == 'yes')
|
|
{
|
|
list(, $userDomain) = explode('@', $email);
|
|
$countryList = CountryList();
|
|
$countryName = $countryList[$country];
|
|
$vars = array(
|
|
'datum' => FormatDate(),
|
|
'email' => DecodeEMail($email),
|
|
'domain' => $userDomain,
|
|
'anrede' => ucfirst($salutation),
|
|
'name' => $surname . ', ' . $firstname,
|
|
'strasse' => $street . ' ' . $no,
|
|
'plzort' => $zip . ' ' . $city,
|
|
'land' => $countryName . ' (#' . $country . ')',
|
|
'tel' => $phone,
|
|
'fax' => $fax,
|
|
'altmail' => $altmail,
|
|
'link' => sprintf('%sadmin/?jump=%s',
|
|
$bm_prefs['selfurl'],
|
|
urlencode(sprintf('users.php?do=edit&id=%d&', $uid)))
|
|
);
|
|
SystemMail($bm_prefs['passmail_abs'],
|
|
$bm_prefs['notify_to'],
|
|
$lang_custom['snotify_sub'],
|
|
'snotify_text',
|
|
$vars);
|
|
}
|
|
|
|
// send welcome mail
|
|
if($bm_prefs['welcome_mail'] == 'yes')
|
|
{
|
|
list(, $userDomain) = explode('@', $email);
|
|
$countryList = CountryList();
|
|
$countryName = $countryList[$country];
|
|
$vars = array(
|
|
'datum' => FormatDate(),
|
|
'email' => DecodeEMail($email),
|
|
'domain' => $userDomain,
|
|
'anrede' => ucfirst($salutation),
|
|
'vorname' => $firstname,
|
|
'nachname' => $surname,
|
|
'strasse' => $street . ' ' . $no,
|
|
'plzort' => $zip . ' ' . $city,
|
|
'land' => $countryName . ' (#' . $country . ')',
|
|
'tel' => $phone,
|
|
'fax' => $fax,
|
|
'altmail' => $altmail
|
|
);
|
|
SystemMail($bm_prefs['passmail_abs'],
|
|
$email,
|
|
$lang_custom['welcome_sub'],
|
|
'welcome_text',
|
|
$vars);
|
|
}
|
|
|
|
// send validation sms/mail?
|
|
if($ValidationCode != '')
|
|
{
|
|
if($bm_prefs['reg_validation'] == 'sms')
|
|
{
|
|
if(!class_exists('BMSMS'))
|
|
include(B1GMAIL_DIR . 'serverlib/sms.class.php');
|
|
|
|
$smsText = GetPhraseForUser($uid, 'lang_custom', 'validationsms');
|
|
$smsText = str_replace('%%code%%', $ValidationCode, $smsText);
|
|
|
|
$sms = _new('BMSMS', array(0, false));
|
|
$sms->Send($bm_prefs['mail2sms_abs'], preg_replace('/[^0-9]/', '', str_replace('+', '00', $mobile_nr)), $smsText, $bm_prefs['smsvalidation_type'], false, false);
|
|
}
|
|
else if($bm_prefs['reg_validation'] == 'email')
|
|
{
|
|
$vars = array(
|
|
'activationcode' => $ValidationCode,
|
|
'email' => DecodeEMail($email),
|
|
'url' => sprintf('%sindex.php?action=activateAccount&id=%d&code=%s',
|
|
$bm_prefs['selfurl'],
|
|
$uid,
|
|
$ValidationCode)
|
|
);
|
|
|
|
SystemMail($bm_prefs['passmail_abs'],
|
|
$altmail,
|
|
$lang_custom['activationmail_sub'],
|
|
'activationmail_text',
|
|
$vars);
|
|
}
|
|
}
|
|
|
|
// module handler
|
|
ModuleFunction('OnSignup', array($uid, $email));
|
|
|
|
// log
|
|
PutLog(sprintf('User <%s> (%d) created (adminMode: %d, allowNotification: %d, notification: %d, createLocked: %d, IP: %s)',
|
|
$email,
|
|
$uid,
|
|
defined('ADMIN_MODE') && ADMIN_MODE ? 1 : 0,
|
|
$allowNotification ? 1 : 0,
|
|
$allowNotification && $bm_prefs['notify_mail'] == 'yes' ? 1 : 0,
|
|
$createLocked ? 1 : 0,
|
|
$_SERVER['REMOTE_ADDR']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
|
|
return($uid);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* check if coupon is valid
|
|
*
|
|
* @param string $code Coupon code
|
|
* @param string $where Validation context (signup, loggedin)
|
|
* @return bool
|
|
*/
|
|
public static function CouponValid($code, $where = '')
|
|
{
|
|
global $db;
|
|
|
|
$result = false;
|
|
|
|
// get code from DB
|
|
$res = $db->Query('SELECT id,code,von,bis,usedby,anzahl,used,ver,valid_signup,valid_loggedin FROM {pre}codes WHERE code=?',
|
|
$code);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
// additional case comparison
|
|
if($row['code'] == $code)
|
|
{
|
|
// check if coupon is active
|
|
if(($row['von'] == -1 && $row['bis'] == -1)
|
|
|| ($row['von'] == -1 && $row['bis'] >= time())
|
|
|| ($row['von'] <= time() && $row['bis'] == -1)
|
|
|| ($row['von'] <= time() && $row['bis'] >= time()))
|
|
{
|
|
if($where == ''
|
|
|| ($where == 'signup' && $row['valid_signup'] == 'yes')
|
|
|| ($where == 'loggedin' && $row['valid_loggedin'] == 'yes'))
|
|
{
|
|
$result = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* redeem coupon
|
|
*
|
|
* @param string $code Coupon code
|
|
* @param string $where Redeem context (signup, loggedin)
|
|
* @return bool
|
|
*/
|
|
public function RedeemCoupon($code, $where = '')
|
|
{
|
|
global $db, $lang_user;
|
|
|
|
$result = false;
|
|
|
|
// get code from DB
|
|
$res = $db->Query('SELECT id,code,von,bis,usedby,anzahl,used,ver,valid_signup,valid_loggedin FROM {pre}codes WHERE code=?',
|
|
$code);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
// additional case comparison
|
|
if($row['code'] == $code)
|
|
{
|
|
// check if coupon is active
|
|
if(($row['von'] == -1 && $row['bis'] == -1)
|
|
|| ($row['von'] == -1 && $row['bis'] >= time())
|
|
|| ($row['von'] <= time() && $row['bis'] == -1)
|
|
|| ($row['von'] <= time() && $row['bis'] >= time()))
|
|
{
|
|
if($where == ''
|
|
|| ($where == 'signup' && $row['valid_signup'] == 'yes')
|
|
|| ($where == 'loggedin' && $row['valid_loggedin'] == 'yes'))
|
|
{
|
|
$usedBy = @unserialize($row['usedby']);
|
|
if(!is_array($usedBy))
|
|
$usedBy = array();
|
|
|
|
// check if user may use this coupon
|
|
if(!in_array($this->_id, $usedBy)
|
|
&& (($row['anzahl']==-1)
|
|
|| ($row['anzahl'] > $row['used'])))
|
|
{
|
|
$benefit = @unserialize($row['ver']);
|
|
|
|
if(is_array($benefit))
|
|
{
|
|
// activate benefits
|
|
if($benefit['sms'] > 0)
|
|
$this->Debit($benefit['sms'], sprintf($lang_user['tx_coupon'], $code));
|
|
if($benefit['gruppe'] > 0)
|
|
{
|
|
$db->Query('UPDATE {pre}users SET gruppe=? WHERE id=?',
|
|
$benefit['gruppe'],
|
|
$this->_id);
|
|
}
|
|
|
|
// update coupon
|
|
$usedBy[] = $this->_id;
|
|
$db->Query('UPDATE {pre}codes SET used=used+1,usedby=? WHERE id=?',
|
|
serialize($usedBy),
|
|
$row['id']);
|
|
|
|
// log
|
|
PutLog(sprintf('User <%d> redeemed coupon <%s> (%d)',
|
|
$this->_id,
|
|
$code,
|
|
$row['id']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
|
|
// break
|
|
$result = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get id for user identified by e-mail address
|
|
*
|
|
* @param string $email
|
|
* @param bool $excludeDeleted
|
|
* @param bool $isAlias Output indicating if $email is an alias
|
|
* @return int
|
|
*/
|
|
public static function GetID($email, $excludeDeleted = false, &$isAlias = null)
|
|
{
|
|
global $db;
|
|
$userID = 0;
|
|
|
|
// look in user-table
|
|
$res = $db->Query('SELECT id FROM {pre}users WHERE email=? ' . ($excludeDeleted ? 'AND gesperrt!=\'delete\' ' : '') . 'LIMIT 1',
|
|
$email);
|
|
if($res->RowCount() == 1)
|
|
list($userID) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
// not in user-table -> alias?
|
|
if($userID == 0)
|
|
{
|
|
$res = $db->Query('SELECT {pre}users.id AS id FROM {pre}users,{pre}aliase WHERE {pre}aliase.email=? AND ({pre}aliase.type&'.ALIAS_RECIPIENT.')!=0 AND {pre}users.id={pre}aliase.user ' . ($excludeDeleted ? 'AND {pre}users.gesperrt!=\'delete\' ' : '') . 'LIMIT 1',
|
|
$email);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
list($userID) = $res->FetchArray(MYSQLI_NUM);
|
|
$isAlias = true;
|
|
}
|
|
$res->Free();
|
|
}
|
|
else
|
|
$isAlias = false;
|
|
|
|
// return ID
|
|
return($userID);
|
|
}
|
|
|
|
/**
|
|
* plugin auth helper
|
|
*
|
|
* @param string $email
|
|
* @param string $password
|
|
* @return mixed false or array
|
|
*/
|
|
private static function _pluginAuth($email, $passwordMD5, $passwordPlain)
|
|
{
|
|
global $plugins;
|
|
|
|
// prepare variables
|
|
$userParts = explode('@', trim($email));
|
|
$userName = isset($userParts[0]) ? $userParts[0] : '';
|
|
$userDomain = isset($userParts[1]) ? $userParts[1] : '';
|
|
|
|
// search for an auth handler
|
|
foreach($plugins->_plugins as $className=>$pluginInfo)
|
|
{
|
|
if(($result = $plugins->callFunction('OnAuthenticate', $className, false,
|
|
array($userName,
|
|
$userDomain,
|
|
$passwordMD5,
|
|
$passwordPlain))) !== false
|
|
&& is_array($result))
|
|
{
|
|
return($result);
|
|
}
|
|
}
|
|
|
|
// no auth handler useful
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* activate a user account using it's activation code
|
|
*
|
|
* @param int $id User ID
|
|
* @param string $code Code
|
|
* @return bool Success
|
|
*/
|
|
public static function ActivateAccount($id, $code)
|
|
{
|
|
global $db, $bm_prefs;
|
|
|
|
$id = (int)$id;
|
|
$code = trim($code);
|
|
|
|
// check code length
|
|
if(strlen($code) != VALIDATIONCODE_LENGTH)
|
|
return(false);
|
|
|
|
// get user row
|
|
$res = $db->Query('SELECT `email`,`sms_validation_code` FROM {pre}users WHERE `id`=?',
|
|
$id);
|
|
if($res->RowCount() != 1)
|
|
return(false);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
// check if validation is required
|
|
if(!BMUser::RequiresValidation($row['email']))
|
|
return(false);
|
|
|
|
// validation code ok?
|
|
if(strtoupper(trim($code)) == strtoupper($row['sms_validation_code']))
|
|
{
|
|
$db->Query('UPDATE {pre}users SET `sms_validation_code`=?,`gesperrt`=?,`sms_validation_time`=?,`sms_validation`=? WHERE `id`=?',
|
|
'',
|
|
'no',
|
|
time(),
|
|
$bm_prefs['reg_validation'] == 'sms' ? time() : 0,
|
|
$id);
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* login a user
|
|
*
|
|
* @param string $email E-Mail
|
|
* @param string $passwordPlain Password (PLAIN)
|
|
* @param bool $createSession Create session?
|
|
* @param bool $successLog Log successful logins?
|
|
* @return string Session-ID
|
|
*/
|
|
public static function Login($email, $passwordPlain, $createSession = true, $successLog = true, $ValidationCode = '', $skipSalting = false)
|
|
{
|
|
global $db, $currentCharset, $currentLanguage, $bm_prefs;
|
|
|
|
$passwordPlain = CharsetDecode($passwordPlain, false, 'ISO-8859-15');
|
|
$result = array(USER_DOES_NOT_EXIST, false);
|
|
$row = false;
|
|
$userID = 0;
|
|
$password = LooksLikeMD5Hash($passwordPlain) ? $passwordPlain : md5($passwordPlain);
|
|
|
|
// try plugin authentication first
|
|
$pluginAuth = BMUSer::_pluginAuth($email, $password, $passwordPlain);
|
|
|
|
// no plugin auth
|
|
if(!is_array($pluginAuth))
|
|
{
|
|
// get user ID
|
|
$userID = BMUser::GetID($email);
|
|
$res = $db->Query('SELECT id,gesperrt,passwort,passwort_salt,email,last_login_attempt,sms_validation_code,ip,lastlogin,preferred_language,last_timezone FROM {pre}users WHERE id=? LIMIT 1',
|
|
$userID);
|
|
$row = $res->FetchArray();
|
|
$res->Free();
|
|
}
|
|
|
|
// plugin auth
|
|
else
|
|
{
|
|
// find user
|
|
$res = $db->Query('SELECT id,gesperrt,passwort,passwort_salt,email,last_login_attempt,sms_validation_code,ip,lastlogin,preferred_language,last_timezone FROM {pre}users WHERE uid=? LIMIT 1',
|
|
$pluginAuth['uid']);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
$row = $res->FetchArray();
|
|
$res->Free();
|
|
|
|
// vars
|
|
$row['passwort'] = md5($password.$row['passwort_salt']);
|
|
$userID = $row['id'];
|
|
|
|
// update profile
|
|
if(isset($pluginAuth['profile'])
|
|
&& $row['gesperrt'] == 'no')
|
|
{
|
|
$theOldUserRow = $theUserRow = BMUser::staticFetch($row['id']);
|
|
|
|
$theUserRow['passwort'] = md5($password.$row['passwort_salt']);
|
|
foreach($pluginAuth['profile'] as $key=>$val)
|
|
$theUserRow[$key] = $val;
|
|
|
|
if($theOldUserRow != $theUserRow)
|
|
BMUser::UpdateContactData($theUserRow, false, true, $userID);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(isset($row) && $userID > 0)
|
|
{
|
|
$adminAuthOK = false;
|
|
if(isset($_REQUEST['adminAuth']))
|
|
{
|
|
$adminAuth = @explode(',', @base64_decode($_REQUEST['adminAuth']));
|
|
|
|
if(is_array($adminAuth) && count($adminAuth) == 3 && $adminAuth[0] == $userID)
|
|
{
|
|
$ares = $db->Query('SELECT * FROM {pre}admins WHERE `adminid`=?', $adminAuth[1]);
|
|
while($arow = $ares->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
$adminPrivs = @unserialize($arow['privileges']);
|
|
if(!is_array($adminPrivs)) $adminPrivs = array();
|
|
if($arow['type'] != 0 && !in_array('users', $adminPrivs)) continue;
|
|
|
|
$correctToken = md5(sprintf('%d,%d', $userID, $adminAuth[1]).md5($arow['password'].$_SERVER['HTTP_USER_AGENT']));
|
|
|
|
if($correctToken === $adminAuth[2])
|
|
$adminAuthOK = true;
|
|
}
|
|
$ares->Free();
|
|
}
|
|
}
|
|
|
|
if($skipSalting)
|
|
{
|
|
$saltedPassword = $passwordPlain;
|
|
}
|
|
else
|
|
{
|
|
$saltedPassword = md5($password.$row['passwort_salt']);
|
|
}
|
|
|
|
// user exists
|
|
if((strtolower($row['passwort']) === strtolower($saltedPassword) || $adminAuthOK)
|
|
&& ($row['last_login_attempt'] < 100 || $row['last_login_attempt']+ACCOUNT_LOCK_TIME < time()))
|
|
{
|
|
// validation unlock?
|
|
if($ValidationCode != ''
|
|
&& BMUser::RequiresValidation($email))
|
|
{
|
|
if(BMUser::ActivateAccount($userID, $ValidationCode))
|
|
$row['gesperrt'] = 'no';
|
|
}
|
|
|
|
// password ok
|
|
if($row['gesperrt'] == 'no')
|
|
{
|
|
if(isset($row['preferred_language']) && !empty($row['preferred_language']))
|
|
$userLanguage = $row['preferred_language'];
|
|
else
|
|
$userLanguage = false;
|
|
|
|
$availableLanguages = GetAvailableLanguages();
|
|
if(!isset($availableLanguages[$userLanguage]))
|
|
$userLanguage = false;
|
|
|
|
// okay => update user row
|
|
$db->Query('UPDATE {pre}users SET ip=?,lastlogin=?,last_login_attempt=0,charset=?,language=?,last_timezone=? WHERE id=?',
|
|
$adminAuthOK ? $row['ip'] : $_SERVER['REMOTE_ADDR'],
|
|
$adminAuthOK ? $row['lastlogin'] : time(),
|
|
$currentCharset,
|
|
$userLanguage ? $userLanguage : $currentLanguage,
|
|
isset($_SESSION['bm_timezone']) ? (int)$_SESSION['bm_timezone'] : (isset($_REQUEST['timezone']) ? $_REQUEST['timezone'] : $row['last_timezone']),
|
|
$userID);
|
|
|
|
// create session
|
|
if($createSession)
|
|
{
|
|
@session_start();
|
|
$sessionID = session_id();
|
|
|
|
if($bm_prefs['cookie_lock'] == 'yes')
|
|
{
|
|
$sessionSecret = GenerateRandomKey('sessionSecret');
|
|
setcookie('sessionSecret_'.substr($sessionID, 0, 16), $sessionSecret, 0, '/');
|
|
$_COOKIE['sessionSecret_'.substr($sessionID, 0, 16)] = $sessionSecret;
|
|
}
|
|
|
|
$_SESSION['bm_userLoggedIn'] = true;
|
|
$_SESSION['bm_userID'] = $userID;
|
|
$_SESSION['bm_loginTime'] = time();
|
|
$_SESSION['bm_sessionToken'] = SessionToken();
|
|
$_SESSION['bm_xorCryptKey'] = BMUser::GenerateXORCryptKey($userID, $passwordPlain);
|
|
|
|
if($userLanguage)
|
|
$_SESSION['bm_sessionLanguage'] = $userLanguage;
|
|
}
|
|
else
|
|
$sessionID = $userID;
|
|
|
|
// set result
|
|
$result = array(USER_OK, $sessionID);
|
|
ModuleFunction('OnLogin', array($userID));
|
|
}
|
|
else
|
|
{
|
|
// locked
|
|
$result = array(USER_LOCKED, false);
|
|
ModuleFunction('OnLoginFailed', array($email, $password, BM_LOCKED));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bad password or login lock
|
|
$result = array(USER_BAD_PASSWORD, false);
|
|
ModuleFunction('OnLoginFailed', array($email, $password, BM_WRONGLOGIN));
|
|
|
|
// bruteforce login protection
|
|
$lastLoginAttempt = $row['last_login_attempt'];
|
|
if($lastLoginAttempt < 100)
|
|
{
|
|
// register new attempt
|
|
$result = array(USER_BAD_PASSWORD, $lastLoginAttempt+1);
|
|
if(++$lastLoginAttempt >= 5)
|
|
$lastLoginAttempt = time();
|
|
$db->Query('UPDATE {pre}users SET last_login_attempt=? WHERE id=?',
|
|
$lastLoginAttempt,
|
|
$userID);
|
|
}
|
|
else
|
|
{
|
|
// account still locked
|
|
$lockedUntil = $lastLoginAttempt + ACCOUNT_LOCK_TIME;
|
|
if($lockedUntil < time())
|
|
{
|
|
// first attempt
|
|
$db->Query('UPDATE {pre}users SET last_login_attempt=? WHERE id=?',
|
|
1,
|
|
$userID);
|
|
$result = array(USER_BAD_PASSWORD, 1);
|
|
}
|
|
else
|
|
{
|
|
// locked
|
|
$result = array(USER_LOGIN_BLOCK, $lockedUntil);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// log
|
|
if($result[0] != USER_OK || $successLog)
|
|
PutLog(sprintf('Login attempt as <%s> %s (%s; IP: %s)',
|
|
$email,
|
|
$result[0] == USER_OK ? 'succeeded' : 'failed',
|
|
($result[0] == USER_LOGIN_BLOCK ? 'account locked because of too many login attempts'
|
|
: ($result[0] == USER_BAD_PASSWORD ? 'bad password'
|
|
: ($result[0] == USER_OK ? 'success'
|
|
: ($result[0] == USER_DOES_NOT_EXIST ? 'user does not exist'
|
|
: ($result[0] == USER_LOCKED ? 'account locked'
|
|
: 'unknown reason'))))),
|
|
$_SERVER['REMOTE_ADDR']), PRIO_NOTE, __FILE__, __LINE__);
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* log out
|
|
*
|
|
*/
|
|
public function Logout()
|
|
{
|
|
ModuleFunction('OnLogout', array($_SESSION['bm_userID']));
|
|
|
|
$_SESSION['bm_userLoggedIn'] = false;
|
|
$_SESSION['bm_userID'] = -1;
|
|
|
|
if(!isset($_SESSION['bm_adminLoggedIn']))
|
|
{
|
|
if(isset($_COOKIE['sessionSecret_'.substr(session_id(), 0, 16)]))
|
|
setcookie('sessionSecret_'.substr(session_id(), 0, 16), '', time()-TIME_ONE_HOUR, '/');
|
|
session_destroy();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* check if user account requires validation
|
|
*
|
|
* @param string $email User account e-mail
|
|
* @return bool
|
|
*/
|
|
public static function RequiresValidation($email)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT `gesperrt`,`sms_validation_code` FROM {pre}users WHERE `email`=?',
|
|
$email);
|
|
if($res->RowCount() != 1)
|
|
return(false);
|
|
list($userStatus, $ValidationCode) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($userStatus == 'locked' && strlen($ValidationCode) == VALIDATIONCODE_LENGTH);
|
|
}
|
|
|
|
/**
|
|
* validate mobile no
|
|
*
|
|
* @param string $code Validation code
|
|
* @return bool
|
|
*/
|
|
public function ValidateMobileNo($code)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT `sms_validation_code`,`sms_validation` FROM {pre}users WHERE `id`=?',
|
|
$this->_id);
|
|
list($smsValidationCode, $smsValidation) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
if(trim(strtoupper($code)) == strtoupper($smsValidationCode) && strlen($smsValidationCode) == VALIDATIONCODE_LENGTH)
|
|
{
|
|
$db->Query('UPDATE {pre}users SET `sms_validation_code`=?,`sms_validation`=? WHERE `id`=?',
|
|
'',
|
|
time(),
|
|
$this->_id);
|
|
return(true);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* fetch a user row (assoc)
|
|
*
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function Fetch($id = -1, $re = false)
|
|
{
|
|
global $db;
|
|
|
|
if($id == -1)
|
|
{
|
|
$id = $this->_id;
|
|
if(!$re && is_array($this->_row))
|
|
return($this->_row);
|
|
}
|
|
|
|
$res = $db->Query('SELECT * FROM {pre}users WHERE id=?',
|
|
$id);
|
|
if($res->RowCount() == 0)
|
|
return(false);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
return($row);
|
|
}
|
|
|
|
/**
|
|
* fetch a user row (static function)
|
|
*
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public static function staticFetch($id)
|
|
{
|
|
global $db;
|
|
if(!isset($id))
|
|
return false;
|
|
$res = $db->Query('SELECT * FROM {pre}users WHERE id=?',
|
|
$id);
|
|
if($res->RowCount() == 0)
|
|
return(false);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
return($row);
|
|
}
|
|
|
|
/**
|
|
* refresh user row
|
|
*
|
|
* @return array
|
|
*/
|
|
public function ReFetch()
|
|
{
|
|
$this->_row = $this->Fetch(-1, true);
|
|
return($this->_row);
|
|
}
|
|
|
|
/**
|
|
* get user's pop3 accounts
|
|
*
|
|
* @param string $sortColumn
|
|
* @param string $sortOrder
|
|
* @return array
|
|
*/
|
|
public function GetPOP3Accounts($sortColumn = 'p_user', $sortOrder = 'ASC', $activeOnly = false)
|
|
{
|
|
global $db;
|
|
|
|
$accounts = array();
|
|
$res = $db->Query('SELECT id,p_host,p_user,p_pass,p_target,p_port,p_keep,last_fetch,last_success,p_ssl,paused FROM {pre}pop3 WHERE user=? '
|
|
. ($activeOnly ? 'AND `paused`=\'no\' ' : '')
|
|
. 'ORDER BY ' . $sortColumn . ' ' . $sortOrder,
|
|
$this->_id);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$accounts[$row['id']] = array(
|
|
'id' => $row['id'],
|
|
'p_host' => $row['p_host'],
|
|
'p_user' => $row['p_user'],
|
|
'p_pass' => $row['p_pass'],
|
|
'p_target' => $row['p_target'],
|
|
'p_port' => $row['p_port'],
|
|
'p_keep' => $row['p_keep'] == 'yes',
|
|
'p_ssl' => $row['p_ssl'] == 'yes',
|
|
'paused' => $row['paused'] == 'yes',
|
|
'last_fetch' => $row['last_fetch'],
|
|
'last_success' => $row['last_success']
|
|
);
|
|
$res->Free();
|
|
|
|
return($accounts);
|
|
}
|
|
|
|
/**
|
|
* get pop3 account
|
|
*
|
|
* @param int $id
|
|
* @return array
|
|
*/
|
|
public function GetPOP3Account($id)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT id,p_host,p_user,p_pass,p_target,p_port,p_keep,last_fetch,p_ssl,paused FROM {pre}pop3 WHERE id=? AND user=?',
|
|
$id,
|
|
$this->_id);
|
|
if($res->RowCount() == 0)
|
|
return(false);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
$result = array(
|
|
'id' => $row['id'],
|
|
'p_host' => $row['p_host'],
|
|
'p_user' => $row['p_user'],
|
|
'p_pass' => $row['p_pass'],
|
|
'p_target' => $row['p_target'],
|
|
'p_port' => $row['p_port'],
|
|
'p_keep' => $row['p_keep'] == 'yes',
|
|
'p_ssl' => $row['p_ssl'] == 'yes',
|
|
'last_fetch' => $row['last_fetch'],
|
|
'paused' => $row['paused'] == 'yes'
|
|
);
|
|
return($result);
|
|
}
|
|
|
|
public function UpdatePOP3Account($id, $p_host, $p_user, $p_pass, $p_target, $p_port, $p_keep, $p_ssl, $paused)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}pop3 SET p_host=?,p_user=?,p_pass=?,p_target=?,p_port=?,p_keep=?,p_ssl=?,paused=? WHERE id=? AND user=?',
|
|
$p_host,
|
|
$p_user,
|
|
$p_pass,
|
|
(int)$p_target,
|
|
(int)$p_port,
|
|
$p_keep ? 'yes' : 'no',
|
|
$p_ssl ? 'yes' : 'no',
|
|
$paused ? 'yes' : 'no',
|
|
(int)$id,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* add pop3 account
|
|
*
|
|
* @param string $p_host
|
|
* @param string $p_user
|
|
* @param string $p_pass
|
|
* @param int $p_target
|
|
* @param int $p_port
|
|
* @param bool $p_keep
|
|
* @param bool $p_ssl
|
|
* @return int
|
|
*/
|
|
public function AddPOP3Account($p_host, $p_user, $p_pass, $p_target, $p_port, $p_keep, $p_ssl = false)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}pop3(user,p_host,p_user,p_pass,p_target,p_port,p_keep,p_ssl) '
|
|
. 'VALUES(?,?,?,?,?,?,?,?)',
|
|
$this->_id,
|
|
$p_host,
|
|
$p_user,
|
|
$p_pass,
|
|
(int)$p_target,
|
|
(int)$p_port,
|
|
$p_keep ? 'yes' : 'no',
|
|
$p_ssl ? 'yes' : 'no');
|
|
return($db->InsertId());
|
|
}
|
|
|
|
/**
|
|
* delete pop3 account
|
|
*
|
|
* @param int $id Account ID
|
|
* @return bool
|
|
*/
|
|
public function DeletePOP3Account($id)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}pop3 WHERE id=? AND user=?',
|
|
$id,
|
|
$this->_id);
|
|
|
|
if($db->AffectedRows() == 1)
|
|
{
|
|
$db->Query('DELETE FROM {pre}uidindex WHERE pop3=?',
|
|
$id);
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get user's signatures
|
|
*
|
|
* @param string $sortColumn
|
|
* @param string $sortOrder
|
|
* @return array
|
|
*/
|
|
public function GetSignatures($sortColumn = 'titel', $sortOrder = 'ASC')
|
|
{
|
|
global $db, $lang_user;
|
|
|
|
$signatures = array();
|
|
$res = $db->Query('SELECT id,titel,text,html FROM {pre}signaturen WHERE user=? '
|
|
. 'ORDER BY ' . $sortColumn . ' ' . $sortOrder,
|
|
$this->_id);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$signatures[$row['id']] = $row;
|
|
$res->Free();
|
|
|
|
return($signatures);
|
|
}
|
|
|
|
/**
|
|
* delete signature
|
|
*
|
|
* @param int $signatureID Signature ID
|
|
* @return bool
|
|
*/
|
|
public function DeleteSignature($signatureID)
|
|
{
|
|
global $db;
|
|
|
|
// delete
|
|
$db->Query('DELETE FROM {pre}signaturen WHERE id=? AND user=?',
|
|
(int)$signatureID,
|
|
$this->_id);
|
|
|
|
// return
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get signature
|
|
*
|
|
* @param int $signatureID Signature ID
|
|
* @return array
|
|
*/
|
|
public function GetSignature($signatureID)
|
|
{
|
|
global $db;
|
|
|
|
// get signature
|
|
$res = $db->Query('SELECT id,titel,text,html FROM {pre}signaturen WHERE id=? AND user=?',
|
|
$signatureID,
|
|
$this->_id);
|
|
if($res->RowCount() != 1)
|
|
return(false);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
return($row);
|
|
}
|
|
|
|
/**
|
|
* update signature
|
|
*
|
|
* @param int $id Signature ID
|
|
* @param string $title Title
|
|
* @param string $text Text
|
|
* @param string $html HTML
|
|
* @return bool
|
|
*/
|
|
public function UpdateSignature($signatureID, $title, $text, $html)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}signaturen SET titel=?,text=?,html=? WHERE id=? AND user=?',
|
|
$title,
|
|
$text,
|
|
$html,
|
|
$signatureID,
|
|
$this->_id);
|
|
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* add signature
|
|
*
|
|
* @param string $title Title
|
|
* @param string $text Text
|
|
* @param string $html HTML
|
|
* @return int
|
|
*/
|
|
public function AddSignature($title, $text, $html)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}signaturen(user,titel,text,html) VALUES(?,?,?,?)',
|
|
$this->_id,
|
|
$title,
|
|
$text,
|
|
$html);
|
|
|
|
return($db->InsertId());
|
|
}
|
|
|
|
/**
|
|
* get user's aliases
|
|
*
|
|
* @param string $sortColumn
|
|
* @param string $sortOrder
|
|
* @return array
|
|
*/
|
|
public function GetAliases($sortColumn = 'email', $sortOrder = 'ASC')
|
|
{
|
|
global $db, $lang_user;
|
|
|
|
$aliases = array();
|
|
$res = $db->Query('SELECT id,email,type,sendername FROM {pre}aliase WHERE user=? '
|
|
. 'ORDER BY ' . $sortColumn . ' ' . $sortOrder,
|
|
$this->_id);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
$typeTexts = array();
|
|
if($row['type'] & ALIAS_SENDER)
|
|
$typeTexts[] = $lang_user['aliastype_1'];
|
|
if($row['type'] & ALIAS_RECIPIENT)
|
|
$typeTexts[] = $lang_user['aliastype_2'];
|
|
if($row['type'] & ALIAS_PENDING)
|
|
$typeTexts = array($lang_user['aliastype_4']);
|
|
$row['typeText'] = implode(', ', $typeTexts);
|
|
$aliases[$row['id']] = $row;
|
|
}
|
|
$res->Free();
|
|
|
|
return($aliases);
|
|
}
|
|
|
|
/**
|
|
* get possible senders
|
|
*
|
|
* @return array
|
|
*/
|
|
public function GetPossibleSenders()
|
|
{
|
|
$senders = array();
|
|
$aliases = $this->GetAliases();
|
|
$worgroups = $this->GetWorkgroups(false);
|
|
|
|
$senders[] = sprintf('<%s>' ,
|
|
$this->_row['email']);
|
|
foreach($aliases as $alias)
|
|
if(($alias['type']&ALIAS_SENDER) != 0
|
|
&& ($alias['type']&ALIAS_PENDING) == 0)
|
|
$senders[] = sprintf('<%s>',
|
|
$alias['email']);
|
|
|
|
foreach($worgroups as $workgroup)
|
|
$senders[] = sprintf('<%s>',
|
|
$workgroup['email']);
|
|
|
|
if(trim($this->_row['absendername']) != '')
|
|
$senders[] = sprintf('"%s" <%s>',
|
|
$this->_row['absendername'],
|
|
$this->_row['email']);
|
|
else
|
|
$senders[] = sprintf('"%s %s" <%s>',
|
|
$this->_row['vorname'],
|
|
$this->_row['nachname'],
|
|
$this->_row['email']);
|
|
|
|
foreach($aliases as $alias)
|
|
if(($alias['type']&ALIAS_SENDER) != 0
|
|
&& ($alias['type']&ALIAS_PENDING) == 0)
|
|
if(trim($alias['sendername']) != '')
|
|
$senders[] = sprintf('"%s" <%s>',
|
|
$alias['sendername'],
|
|
$alias['email']);
|
|
else if(trim($this->_row['absendername']) != '')
|
|
$senders[] = sprintf('"%s" <%s>',
|
|
$this->_row['absendername'],
|
|
$alias['email']);
|
|
else
|
|
$senders[] = sprintf('"%s %s" <%s>',
|
|
$this->_row['vorname'],
|
|
$this->_row['nachname'],
|
|
$alias['email']);
|
|
|
|
foreach($worgroups as $workgroup)
|
|
$senders[] = sprintf('"%s" <%s>',
|
|
$workgroup['title'],
|
|
$workgroup['email']);
|
|
|
|
return($senders);
|
|
}
|
|
|
|
/**
|
|
* get default sender
|
|
*
|
|
* @return string
|
|
*/
|
|
public function GetDefaultSender()
|
|
{
|
|
$senders = $this->GetPossibleSenders();
|
|
return(isset($senders[$this->_row['defaultSender']])
|
|
? $senders[$this->_row['defaultSender']]
|
|
: array_shift($senders));
|
|
}
|
|
|
|
/**
|
|
* set default sender
|
|
*
|
|
* @param int $senderID Sender ID (from possible senders table)
|
|
* @return bool
|
|
*/
|
|
public function SetDefaultSender($senderID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}users SET defaultSender=? WHERE id=?',
|
|
$senderID,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* delete an alias
|
|
*
|
|
* @param int $aliasID Alias ID
|
|
* @return bool
|
|
*/
|
|
public function DeleteAlias($aliasID)
|
|
{
|
|
global $db;
|
|
|
|
// sender
|
|
$defaultSender = $this->GetDefaultSender();
|
|
|
|
// get email
|
|
$res = $db->Query('SELECT email FROM {pre}aliase WHERE id=? AND user=?',
|
|
(int)$aliasID,
|
|
$this->_id);
|
|
assert('$res->RowCount() != 0');
|
|
list($aliasEMail) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
// delete
|
|
$db->Query('DELETE FROM {pre}aliase WHERE id=? AND user=?',
|
|
(int)$aliasID,
|
|
$this->_id);
|
|
|
|
// save sender
|
|
$possibleSenders = $this->GetPossibleSenders();
|
|
foreach($possibleSenders as $senderID=>$senderString)
|
|
if($defaultSender == $senderString)
|
|
{
|
|
$this->SetDefaultSender($senderID);
|
|
break;
|
|
}
|
|
|
|
// log
|
|
PutLog(sprintf('User <%s> (%d) deleted alias <%s> (%d)',
|
|
$this->_row['email'],
|
|
$this->_id,
|
|
$aliasEMail,
|
|
$aliasID),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
|
|
// return
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* confirm an alias
|
|
*
|
|
* @param int $id Alias ID
|
|
* @param string $code Confirmation code
|
|
* @return bool
|
|
*/
|
|
public static function ConfirmAlias($id, $code)
|
|
{
|
|
global $db;
|
|
|
|
// get user id
|
|
$res = $db->Query('SELECT `user` FROM {pre}aliase WHERE `id`=? AND `code`=? AND `code`!=?',
|
|
$id,
|
|
$code,
|
|
'');
|
|
if($res->RowCount() != 1)
|
|
return(false);
|
|
list($userID) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
// store sender
|
|
$_obj = _new('BMUser', array($userID));
|
|
if($_obj->_row === false)
|
|
return(false);
|
|
$defaultSender = $_obj->GetDefaultSender();
|
|
|
|
$db->Query('UPDATE {pre}aliase SET type=(type^'.ALIAS_PENDING.'),code=? WHERE id=? AND code=? AND code!=?',
|
|
'',
|
|
$id,
|
|
$code,
|
|
'');
|
|
// log
|
|
if($db->AffectedRows() == 1)
|
|
{
|
|
// save sender
|
|
$possibleSenders = $_obj->GetPossibleSenders();
|
|
foreach($possibleSenders as $senderID=>$senderString)
|
|
if($defaultSender == $senderString)
|
|
{
|
|
$_obj->SetDefaultSender($senderID);
|
|
break;
|
|
}
|
|
|
|
PutLog(sprintf('External alias <%d> confirmed with code <%s> from <%s>',
|
|
$id,
|
|
$code,
|
|
$_SERVER['REMOTE_ADDR']),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
return(true);
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* add an alias
|
|
*
|
|
* @param string $email Alias e-mail address
|
|
* @param int $type Alias type
|
|
* @param string $sendername Alias name
|
|
* @return in
|
|
*/
|
|
public function AddAlias($email, $type, $sendername='')
|
|
{
|
|
global $db, $lang_custom, $bm_prefs, $thisUser;
|
|
|
|
$result = 0;
|
|
|
|
// default sender
|
|
$defaultSender = $this->GetDefaultSender();
|
|
|
|
//
|
|
// internal alias
|
|
//
|
|
if($type == (ALIAS_RECIPIENT|ALIAS_SENDER))
|
|
{
|
|
// add
|
|
$db->Query('INSERT INTO {pre}aliase(email,user,type,date,sendername) VALUES(?,?,?,?,?)',
|
|
$email,
|
|
$this->_id,
|
|
$type,
|
|
time(),
|
|
$sendername);
|
|
$id = $db->InsertId();
|
|
|
|
// log
|
|
PutLog(sprintf('User <%s> (%d) created internal alias <%s> (%d)',
|
|
$this->_row['email'],
|
|
$this->_id,
|
|
$email,
|
|
$id),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
$result = $id;
|
|
}
|
|
|
|
//
|
|
// external alias
|
|
//
|
|
else if($type == ALIAS_SENDER)
|
|
{
|
|
// add
|
|
$code = GenerateRandomKey('aliasCode');
|
|
$db->Query('INSERT INTO {pre}aliase(email,user,type,code,date,sendername) VALUES(?,?,?,?,?,?)',
|
|
$email,
|
|
$this->_id,
|
|
$type|ALIAS_PENDING,
|
|
$code,
|
|
time(),
|
|
$sendername);
|
|
$id = $db->InsertId();
|
|
|
|
// send mail
|
|
$link = $bm_prefs['selfurl'] . 'index.php?action=confirmAlias&id=' . $id . '&code=' . $code;
|
|
$vars = array(
|
|
'email' => DecodeEMail($this->_row['email']),
|
|
'aliasemail' => DecodeEMail($email),
|
|
'link' => $link
|
|
);
|
|
SystemMail($thisUser->GetDefaultSender(),
|
|
$email,
|
|
$lang_custom['alias_sub'],
|
|
'alias_text',
|
|
$vars);
|
|
|
|
// log
|
|
PutLog(sprintf('User <%s> (%d) created external alias <%s> (%d)',
|
|
$this->_row['email'],
|
|
$this->_id,
|
|
$email,
|
|
$id),
|
|
PRIO_NOTE,
|
|
__FILE__,
|
|
__LINE__);
|
|
$result = $id;
|
|
}
|
|
|
|
// save sender
|
|
$possibleSenders = $this->GetPossibleSenders();
|
|
foreach($possibleSenders as $senderID=>$senderString)
|
|
if($defaultSender == $senderString)
|
|
{
|
|
$this->SetDefaultSender($senderID);
|
|
break;
|
|
}
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get used month sms credits
|
|
*
|
|
* @return int
|
|
*/
|
|
public function GetUsedMonthSMS()
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT SUM(price) FROM {pre}smsend WHERE user=? AND monat=?',
|
|
$this->_id,
|
|
(int)date('mY'));
|
|
list($usedMonthSMS) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($usedMonthSMS);
|
|
}
|
|
|
|
/**
|
|
* get user count
|
|
*
|
|
* @return int
|
|
*/
|
|
public static function GetUserCount()
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}users');
|
|
list($userCount) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($userCount);
|
|
}
|
|
|
|
/**
|
|
* get user's workgroups
|
|
*
|
|
* @param bool $withMembers Include members?
|
|
* @return array
|
|
*/
|
|
public function GetWorkgroups($withMembers = false)
|
|
{
|
|
return(BMWorkgroup::GetSimpleWorkgroupList($this->_id, $withMembers));
|
|
}
|
|
|
|
/**
|
|
* get account balance
|
|
*
|
|
* @return int
|
|
*/
|
|
public function GetBalance()
|
|
{
|
|
$group = $this->GetGroup();
|
|
$groupRow = $group->Fetch();
|
|
|
|
$smsPerMonth = $groupRow['sms_monat'];
|
|
$balance = max(0, $smsPerMonth - $this->GetUsedMonthSMS()) + $this->GetStaticBalance();
|
|
|
|
return($balance);
|
|
}
|
|
|
|
/**
|
|
* Get static-only credit balance at a certain point int ime
|
|
*
|
|
* Does not take into account monthly dynamic credits.
|
|
*
|
|
* @param int $when Timestamp (0 = now)
|
|
* @return int Credits
|
|
*/
|
|
public function GetStaticBalance($when = 0)
|
|
{
|
|
global $db;
|
|
|
|
if($when == 0)
|
|
$when = time();
|
|
|
|
$result = 0;
|
|
|
|
$res = $db->Query('SELECT SUM(`amount`) FROM {pre}transactions WHERE `userid`=? AND `status`=? AND `date`<=?',
|
|
$this->_id, TRANSACTION_BOOKED, $when);
|
|
list($result) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return (int)$result;
|
|
}
|
|
|
|
/**
|
|
* charge account
|
|
*
|
|
* @param int $credits Credits
|
|
* @return int -1 = failed, 0 = ok, but no smsend ID, > 0 = smsend ID
|
|
*/
|
|
public function Debit($credits, $description = 'Unknown')
|
|
{
|
|
global $db;
|
|
|
|
$result = -1;
|
|
$group = $this->GetGroup();
|
|
$groupRow = $group->Fetch();
|
|
|
|
$smsPerMonth = $groupRow['sms_monat'];
|
|
$freeMonthCredits = $smsPerMonth - $this->GetUsedMonthSMS();
|
|
$freeStaticCredits = $this->GetStaticBalance();
|
|
|
|
if($credits < 0)
|
|
{
|
|
$credits = abs($credits);
|
|
if($credits <= ($freeStaticCredits+$freeMonthCredits))
|
|
{
|
|
$monthPart = min($freeMonthCredits, $credits);
|
|
$staticPart = $credits - $monthPart;
|
|
|
|
if($monthPart > 0)
|
|
{
|
|
$db->Query('INSERT INTO {pre}smsend(user,monat,price,isSMS) VALUES(?,?,?,?)',
|
|
$this->_id,
|
|
(int)date('mY'),
|
|
$credits,
|
|
0);
|
|
$result = $db->InsertId();
|
|
}
|
|
|
|
if($staticPart > 0)
|
|
{
|
|
$db->Query('INSERT INTO {pre}transactions(`userid`,`description`,`amount`,`date`,`status`) '
|
|
. 'VALUES(?,?,?,?,?)',
|
|
$this->_id,
|
|
$description,
|
|
- abs($staticPart),
|
|
time(),
|
|
TRANSACTION_BOOKED);
|
|
if($result == -1)
|
|
$result = 0;
|
|
}
|
|
|
|
return($result);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$db->Query('INSERT INTO {pre}transactions(`userid`,`description`,`amount`,`date`,`status`) '
|
|
. 'VALUES(?,?,?,?,?)',
|
|
$this->_id,
|
|
$description,
|
|
abs($credits),
|
|
time(),
|
|
TRANSACTION_BOOKED);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get transactions in a certain timeframe
|
|
*
|
|
* @param int $from Start timestamp
|
|
* @param int $to End timestamp
|
|
* @param string $sortBy Sort field (date|transactionid|description|status|amount)
|
|
* @param string $sortOrder Sort order (ASC|DESC)
|
|
* @return array
|
|
*/
|
|
public function GetTransactions($from, $to, $sortBy = 'date', $sortOrder = 'ASC')
|
|
{
|
|
global $db, $lang_user;
|
|
|
|
if(!in_array($sortBy, array('date', 'transactionid', 'description', 'status', 'amount')))
|
|
$sortBy = 'date';
|
|
if(!in_array($sortOrder, array('ASC', 'DESC')))
|
|
$sortOrder = 'ASC';
|
|
|
|
$result = array();
|
|
|
|
$res = $db->Query('SELECT * FROM {pre}transactions WHERE `userid`=? AND `date`>=? AND `date`<=? AND `status`>0 '
|
|
. 'ORDER BY `' . $sortBy . '` ' . $sortOrder,
|
|
$this->_id, $from, $to);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
if(strlen($row['description']) > 5 && substr($row['description'], 0, 5) == 'lang:'
|
|
&& isset($lang_user[substr($row['description'], 5)]))
|
|
$row['description'] = $lang_user[substr($row['description'], 5)];
|
|
$result[$row['transactionid']] = $row;
|
|
}
|
|
$res->Free();
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* cancel account
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function CancelAccount()
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}users SET gesperrt=? WHERE id=?',
|
|
'delete',
|
|
$this->_id);
|
|
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get user autoresponder
|
|
*
|
|
* @return array $active, $subject, $text
|
|
*/
|
|
public function GetAutoresponder()
|
|
{
|
|
global $db;
|
|
|
|
$active = 'no';
|
|
$subject = $text = '';
|
|
$lastSend = 0;
|
|
|
|
$res = $db->Query('SELECT active,betreff,mitteilung,last_send FROM {pre}autoresponder WHERE userid=?',
|
|
$this->_id);
|
|
if($res->RowCount() > 0)
|
|
{
|
|
list($active, $subject, $text, $lastSend) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
}
|
|
|
|
return(array($active == 'yes', $subject, $text, $lastSend));
|
|
}
|
|
|
|
/**
|
|
* set last_sent field of autoresponder
|
|
*
|
|
* @param string $lastSend Last mail address
|
|
* @return bool
|
|
*/
|
|
public function SetAutoresponderLastSend($lastSend)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}autoresponder SET last_send=? WHERE userid=?',
|
|
strtolower($lastSend),
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* set autoresponder settings
|
|
*
|
|
* @param bool $active Active?
|
|
* @param string $subject Subject
|
|
* @param string $text Text
|
|
* @return int
|
|
*/
|
|
public function SetAutoresponder($active, $subject, $text)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT id FROM {pre}autoresponder WHERE userid=?',
|
|
$this->_id);
|
|
if($res->RowCount() > 0)
|
|
{
|
|
list($id) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
$db->Query('UPDATE {pre}autoresponder SET active=?,betreff=?,mitteilung=? WHERE id=?',
|
|
$active ? 'yes' : 'no',
|
|
$subject,
|
|
$text,
|
|
$id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
else
|
|
{
|
|
$db->Query('INSERT INTO {pre}autoresponder(active,userid,betreff,mitteilung) VALUES(?,?,?,?)',
|
|
$active ? 'yes' : 'no',
|
|
$this->_id,
|
|
$subject,
|
|
$text);
|
|
return($db->InsertId() != 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get spam index size (entry count)
|
|
*
|
|
* @return int
|
|
*/
|
|
public function GetSpamIndexSize()
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}spamindex WHERE userid=?',
|
|
$this->_id);
|
|
list($size) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
return($size);
|
|
}
|
|
|
|
/**
|
|
* reset spam index
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function ResetSpamIndex()
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}spamindex WHERE userid=?',
|
|
$this->_id);
|
|
$db->Query('UPDATE {pre}users SET bayes_spam=0, bayes_nonspam=0 WHERE id=?',
|
|
$this->_id);
|
|
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
* set antivirus settings
|
|
*
|
|
* @param bool $active Filter active?
|
|
* @param int $action Virus action
|
|
* @return bool
|
|
*/
|
|
public function SetAntivirusSettings($active, $action)
|
|
{
|
|
global $db;
|
|
$db->Query('UPDATE {pre}users SET virusfilter=?, virusaction=? WHERE id=?',
|
|
$active ? 'yes' : 'no',
|
|
$action,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* set antispam settings
|
|
*
|
|
* @param bool $active Filter active?
|
|
* @param int $action Spam action
|
|
* @param bool $unspamMe Mark sent mails as NON-spam?
|
|
* @param int $bayesBorder Bayes border (%)
|
|
* @param bool $addressbookNoSpam Mark as NON-spam when sender is in the address book?
|
|
* @return bool
|
|
*/
|
|
public function SetAntispamSettings($active, $action, $unspamMe, $bayesBorder = false, $addressbookNoSpam)
|
|
{
|
|
global $db;
|
|
$db->Query('UPDATE {pre}users SET spamfilter=?, spamaction=?, unspamme=?, addressbook_nospam=?'
|
|
. ($bayesBorder !== false ? ', bayes_border=' . (int)$bayesBorder : '')
|
|
. ' WHERE id=?',
|
|
$active ? 'yes' : 'no',
|
|
$action,
|
|
$unspamMe ? 'yes' : 'no',
|
|
$addressbookNoSpam ? 'yes' : 'no',
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get user's filters
|
|
*
|
|
* @return array
|
|
*/
|
|
public function GetFilters($sortColumn = 'orderpos', $sortOrder = 'ASC')
|
|
{
|
|
global $db;
|
|
|
|
$filters = array();
|
|
$res = $db->Query('SELECT id,title,applied,active,link,orderpos,flags FROM {pre}filter WHERE userid=? '
|
|
. 'ORDER BY ' . $sortColumn . ' ' . $sortOrder,
|
|
$this->_id);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
$filters[$row['id']] = $row;
|
|
}
|
|
$res->Free();
|
|
|
|
return($filters);
|
|
}
|
|
|
|
/**
|
|
* move filter
|
|
*
|
|
* @param int $id Filter ID
|
|
* @param int $direction Direction (-1 = up, 1 = down)
|
|
*/
|
|
public function MoveFilter($id, $direction)
|
|
{
|
|
global $db;
|
|
|
|
$filters = $this->GetFilters();
|
|
$newFilters = array();
|
|
$maxPos = 0;
|
|
|
|
foreach($filters as $filter)
|
|
if($filter['orderpos'] > $maxPos)
|
|
$maxPos = $filter['orderpos'];
|
|
|
|
$newPos = max(1, min($maxPos, $filters[$id]['orderpos'] + $direction));
|
|
|
|
foreach($filters as $filterID=>$filter)
|
|
{
|
|
if(count($newFilters) + 1 == $newPos)
|
|
{
|
|
$newFilters[$id] = $filters[$id];
|
|
$newFilters[$id]['orderpos'] = $newPos;
|
|
}
|
|
|
|
if($filterID != $id)
|
|
{
|
|
$filter['orderpos'] = count($newFilters) + 1;
|
|
$newFilters[$filterID] = $filter;
|
|
}
|
|
}
|
|
|
|
if(!isset($newFilters[$id]))
|
|
{
|
|
$newFilters[$id] = $filters[$id];
|
|
$newFilters[$id]['orderpos'] = $newPos;
|
|
}
|
|
|
|
foreach($newFilters as $filterID=>$newFilter)
|
|
{
|
|
if($newFilter['orderpos'] != $filters[$filterID]['orderpos'])
|
|
$db->Query('UPDATE {pre}filter SET orderpos=? WHERE id=?',
|
|
$newFilter['orderpos'],
|
|
$filterID);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* get a filter
|
|
*
|
|
* @param int $id Filter ID
|
|
* @return array
|
|
*/
|
|
public function GetFilter($id)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT id,userid,title,applied,active,link,orderpos,flags FROM {pre}filter WHERE id=? AND userid=?',
|
|
(int)$id,
|
|
$this->_id);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
return($row);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* add a filter
|
|
*
|
|
* @param string $title Title
|
|
* @param bool $active Active?
|
|
* @return int
|
|
*/
|
|
public function AddFilter($title, $active)
|
|
{
|
|
global $db;
|
|
|
|
$orderPos = 0;
|
|
$res = $db->Query('SELECT orderpos FROM {pre}filter WHERE userid=? ORDER BY orderpos DESC LIMIT 1',
|
|
$this->_id);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
list($orderPos) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
}
|
|
|
|
$db->Query('INSERT INTO {pre}filter(userid,title,active,orderpos) VALUES(?,?,?,?)',
|
|
$this->_id,
|
|
$title,
|
|
$active ? 1 : 0,
|
|
++$orderPos);
|
|
$id = $db->InsertId();
|
|
|
|
if($id > 0)
|
|
{
|
|
$this->AddFilterCondition($id);
|
|
$this->AddFilterAction($id);
|
|
return($id);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/**
|
|
* update a filter
|
|
*
|
|
* @param int $id Filter ID
|
|
* @param string $title Title
|
|
* @param bool $active Active?
|
|
* @param int $link Link type
|
|
* @param int $flags Filter flags
|
|
* @return bool
|
|
*/
|
|
public function UpdateFilter($id, $title, $active, $link, $flags = 0)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}filter SET title=?,active=?,link=?,flags=? WHERE id=? AND userid=?',
|
|
$title,
|
|
$active ? 1 : 0,
|
|
(int)$link,
|
|
(int)$flags,
|
|
(int)$id,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* delete a filter
|
|
*
|
|
* @param int $id Filter ID
|
|
* @return bool
|
|
*/
|
|
public function DeleteFilter($id)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}filter WHERE id=? AND userid=?',
|
|
(int)$id,
|
|
$this->_id);
|
|
if($db->AffectedRows() == 1)
|
|
{
|
|
$db->Query('DELETE FROM {pre}filter_conditions WHERE filter=?',
|
|
(int)$id);
|
|
return(true);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* get filter conditions
|
|
*
|
|
* @param int $filterID Filter ID
|
|
* @return array
|
|
*/
|
|
public function GetFilterConditions($filterID)
|
|
{
|
|
global $db;
|
|
|
|
$result = array();
|
|
$res = $db->Query('SELECT id,field,op,val FROM {pre}filter_conditions WHERE filter=? ORDER BY id ASC',
|
|
(int)$filterID);
|
|
while($row = $res->FetchArray())
|
|
$result[$row['id']] = $row;
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* delete filter condition
|
|
*
|
|
* @param int $conditionID Condition ID
|
|
* @param int $filterID Filter ID
|
|
* @return bool
|
|
*/
|
|
public function DeleteFilterCondition($conditionID, $filterID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}filter_conditions WHERE id=? AND filter=?',
|
|
(int)$conditionID,
|
|
(int)$filterID);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* add filter condition
|
|
*
|
|
* @param int $filterID Filter ID
|
|
* @return int
|
|
*/
|
|
public function AddFilterCondition($filterID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}filter_conditions(filter,field,op,val) VALUES(?,?,?,?)',
|
|
(int)$filterID,
|
|
1,
|
|
1,
|
|
'');
|
|
return($db->InsertID());
|
|
}
|
|
|
|
/**
|
|
* update filter condition
|
|
*
|
|
* @param int $conditionID Condition ID
|
|
* @param int $filterID Filter ID
|
|
* @param int $field Field constant
|
|
* @param int $op Op constant
|
|
* @param string $val Value
|
|
* @return bool
|
|
*/
|
|
public function UpdateFilterCondition($conditionID, $filterID, $field, $op, $val)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}filter_conditions SET field=?,op=?,val=? WHERE id=? AND filter=?',
|
|
(int)$field,
|
|
(int)$op,
|
|
$val,
|
|
(int)$conditionID,
|
|
(int)$filterID);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* get filter actions
|
|
*
|
|
* @param int $filterID Filter ID
|
|
* @return array
|
|
*/
|
|
public function GetFilterActions($filterID)
|
|
{
|
|
global $db;
|
|
|
|
$result = array();
|
|
$res = $db->Query('SELECT id,filter,op,val,text_val FROM {pre}filter_actions WHERE filter=? ORDER BY id ASC',
|
|
(int)$filterID);
|
|
while($row = $res->FetchArray())
|
|
$result[$row['id']] = $row;
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* delete filter action
|
|
*
|
|
* @param int $actionID Action ID
|
|
* @param int $filterID Filter ID
|
|
* @return bool
|
|
*/
|
|
public function DeleteFilterAction($actionID, $filterID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('DELETE FROM {pre}filter_actions WHERE id=? AND filter=?',
|
|
(int)$actionID,
|
|
(int)$filterID);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* add filter action
|
|
*
|
|
* @param int $filterID Filter ID
|
|
* @return int
|
|
*/
|
|
public function AddFilterAction($filterID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('INSERT INTO {pre}filter_actions(filter,op,val) VALUES(?,?,?)',
|
|
(int)$filterID,
|
|
1,
|
|
0);
|
|
return($db->InsertID());
|
|
}
|
|
|
|
/**
|
|
* update filter action
|
|
*
|
|
* @param int $actionID Action ID
|
|
* @param int $filterID Filter ID
|
|
* @param int $field Field constant
|
|
* @param int $op Op constant
|
|
* @param string $val Value
|
|
* @return bool
|
|
*/
|
|
public function UpdateFilterAction($actionID, $filterID, $op, $val, $textVal)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}filter_actions SET op=?,val=?,text_val=? WHERE id=? AND filter=?',
|
|
(int)$op,
|
|
$val,
|
|
$textVal,
|
|
(int)$actionID,
|
|
(int)$filterID);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* increment filter applied-counter
|
|
*
|
|
* @param int $filterID Filter ID
|
|
* @return bool
|
|
*/
|
|
public function IncFilter($filterID)
|
|
{
|
|
global $db;
|
|
|
|
$db->Query('UPDATE {pre}filter SET applied=applied+1 WHERE id=? AND userid=?',
|
|
(int)$filterID,
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* Update common preferences
|
|
*
|
|
* @param int $inboxRefresh
|
|
* @param bool $instantHTML
|
|
* @param int $firstDayOfWeek
|
|
* @param string $dateFormat
|
|
* @param string $senderName
|
|
* @param int $defaultSender
|
|
* @param string $rePrefix
|
|
* @param string $fwdPrefix
|
|
* @param bool $mailToSMS
|
|
* @param bool $forwardEnabled
|
|
* @param string $forwardTo
|
|
* @param bool $forwardDelete
|
|
* @param bool $enablePreview
|
|
* @param bool $conversationView
|
|
* @return bool
|
|
*/
|
|
public function UpdateCommonSettings($inboxRefresh, $instantHTML, $firstDayOfWeek, $dateFormat, $senderName, $defaultSender, $rePrefix, $fwdPrefix, $mailToSMS, $forwardEnabled, $forwardTo, $forwardDelete, $enablePreview, $conversationView, $newsletterOptIn, $plaintextCourier, $replyQuote, $hotkeys, $attCheck, $searchDetailsDefault, $preferredLanguage,
|
|
$notifySound, $notifyEMail, $notifyBirthday, $autoSaveDrafts, $autoSaveDraftsInterval)
|
|
{
|
|
global $db, $bm_prefs;
|
|
|
|
$this->SetPref('hotkeys', $hotkeys);
|
|
|
|
$db->Query('UPDATE {pre}users SET in_refresh=?, soforthtml=?, c_firstday=?, datumsformat=?, absendername=?, defaultSender=?, re=?, fwd=?, mail2sms=?, forward=?, forward_to=?, forward_delete=?, preview=?, conversation_view=?, newsletter_optin=?, plaintext_courier=?, reply_quote=?, attcheck=?, search_details_default=?, preferred_language=?, notify_sound=?, notify_email=?, notify_birthday=?, auto_save_drafts=?, auto_save_drafts_interval=? WHERE id=?',
|
|
$inboxRefresh,
|
|
$instantHTML ? 'yes' : 'no',
|
|
$firstDayOfWeek,
|
|
$dateFormat,
|
|
$senderName,
|
|
$defaultSender,
|
|
$rePrefix,
|
|
$fwdPrefix,
|
|
$mailToSMS ? 'yes' : 'no',
|
|
$forwardEnabled ? 'yes' : 'no',
|
|
$forwardTo,
|
|
$forwardDelete ? 'yes' : 'no',
|
|
$enablePreview ? 'yes' : 'no',
|
|
$conversationView ? 'yes' : 'no',
|
|
$newsletterOptIn ? 'yes' : 'no',
|
|
$plaintextCourier ? 'yes' : 'no',
|
|
$replyQuote ? 'yes' : 'no',
|
|
$attCheck ? 'yes' : 'no',
|
|
$searchDetailsDefault ? 'yes' : 'no',
|
|
$preferredLanguage,
|
|
$notifySound ? 'yes' : 'no',
|
|
$notifyEMail ? 'yes' : 'no',
|
|
$notifyBirthday ? 'yes' : 'no',
|
|
$autoSaveDrafts ? 'yes' : 'no',
|
|
max($bm_prefs['min_draft_save_interval'], $autoSaveDraftsInterval),
|
|
$this->_id);
|
|
return($db->AffectedRows() == 1);
|
|
}
|
|
|
|
/**
|
|
* update user contact data
|
|
*
|
|
* @param array $userRow Updates user row
|
|
* @param array $profileFields Profile field data
|
|
* @param bool $noHistory No history?
|
|
* @return bool
|
|
*/
|
|
public function UpdateContactData($userRow, $profileFields, $noHistory = false, $userID = 0, $passwordPlain = false)
|
|
{
|
|
global $db, $bm_prefs;
|
|
|
|
if($noHistory || $userRow != $this->_row || ($profileFields !== false && $profileFields != @unserialize($userRow['profilfelder'])))
|
|
{
|
|
// save contact history?
|
|
if(!$noHistory)
|
|
{
|
|
$contactHistory = $this->_row['contactHistory'];
|
|
if($bm_prefs['contact_history'] == 'yes')
|
|
{
|
|
$contactHistory = @unserialize($this->_row['contactHistory']);
|
|
if(!is_array($contactHistory))
|
|
$contactHistory = array();
|
|
$contactHistory[] = array(
|
|
'anrede' => $this->_row['anrede'],
|
|
'vorname' => $this->_row['vorname'],
|
|
'nachname' => $this->_row['nachname'],
|
|
'strasse' => $this->_row['strasse'],
|
|
'hnr' => $this->_row['hnr'],
|
|
'plz' => $this->_row['plz'],
|
|
'ort' => $this->_row['ort'],
|
|
'land' => (int)$this->_row['land'],
|
|
'tel' => $this->_row['tel'],
|
|
'fax' => $this->_row['fax'],
|
|
'mail2sms_nummer' => $this->_row['mail2sms_nummer'],
|
|
'altmail' => $this->_row['altmail'],
|
|
'profilfelder' => $this->_row['profilfelder'],
|
|
'company' => $this->_row['company'],
|
|
'taxid' => $this->_row['taxid'],
|
|
'changeDate' => time()
|
|
);
|
|
$contactHistory = serialize($contactHistory);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if($userID == 0)
|
|
$contactHistory = $this->_row['contactHistory'];
|
|
else
|
|
{
|
|
$user = _new('BMUser', array($userID));
|
|
$row = $user->Fetch();
|
|
$contactHistory = $row['contactHistory'];
|
|
}
|
|
}
|
|
|
|
// profile fields
|
|
if($profileFields === false)
|
|
{
|
|
$profileFields = @unserialize($userRow['profilfelder']);
|
|
if(!is_array($profileFields))
|
|
$profileFields = array();
|
|
}
|
|
|
|
// store data
|
|
$db->Query('UPDATE {pre}users SET vorname=?, nachname=?, strasse=?, hnr=?, plz=?, ort=?, land=?, tel=?, fax=?, mail2sms_nummer=?, altmail=?, profilfelder=?, passwort=?, company=?, taxid=?, contactHistory=?, sms_validation=?, anrede=? WHERE id=?',
|
|
$userRow['vorname'],
|
|
$userRow['nachname'],
|
|
$userRow['strasse'],
|
|
$userRow['hnr'],
|
|
$userRow['plz'],
|
|
$userRow['ort'],
|
|
(int)$userRow['land'],
|
|
$userRow['tel'],
|
|
$userRow['fax'],
|
|
$userRow['mail2sms_nummer'],
|
|
$userRow['altmail'],
|
|
serialize($profileFields),
|
|
$userRow['passwort'],
|
|
$userRow['company'],
|
|
$userRow['taxid'],
|
|
$contactHistory,
|
|
$userID != 0
|
|
? 0
|
|
: (trim($userRow['mail2sms_nummer']) != trim($this->_row['mail2sms_nummer'])
|
|
? 0
|
|
: $this->_row['sms_validation']),
|
|
$userRow['anrede'],
|
|
$userID != 0 ? $userID : $this->_id);
|
|
if($db->AffectedRows() == 1 || true)
|
|
{
|
|
// pw changed?
|
|
if($userID == 0 && ($this->_row['passwort'] != $userRow['passwort']))
|
|
{
|
|
ModuleFunction('OnUserPasswordChange', array($this->_id, $this->_row['passwort'], $userRow['passwort'], $passwordPlain));
|
|
|
|
if(isset($_SESSION['bm_xorCryptKey']) && $passwordPlain !== false)
|
|
{
|
|
$privateKeyPasswords = $this->GetPrivateKeyPasswords();
|
|
|
|
$_SESSION['bm_xorCryptKey'] = $this->GenerateXORCryptKey($this->_id, $passwordPlain);
|
|
|
|
if($privateKeyPasswords)
|
|
$this->SetPrivateKeyPasswords($privateKeyPasswords);
|
|
}
|
|
}
|
|
|
|
// mobile no changed?
|
|
if($userID == 0
|
|
&&
|
|
((trim($userRow['mail2sms_nummer']) != trim($this->_row['mail2sms_nummer']) || ($this->_row['sms_validation'] == 0 && $this->_row['sms_validation_time'] == 0))
|
|
&& trim($userRow['mail2sms_nummer']) != ''))
|
|
{
|
|
$userGroupRow = $this->GetGroup();
|
|
|
|
if($userGroupRow->_row['smsvalidation'] == 'yes')
|
|
{
|
|
// generate validation code
|
|
$smsValidationCode = '';
|
|
for($i=0; $i<VALIDATIONCODE_LENGTH; $i++)
|
|
$smsValidationCode .= substr(VALIDATIONCODE_CHARS, mt_rand(0, strlen(VALIDATIONCODE_CHARS)-1), 1);
|
|
|
|
// send sms
|
|
if(!class_exists('BMSMS'))
|
|
include(B1GMAIL_DIR . 'serverlib/sms.class.php');
|
|
|
|
$smsText = GetPhraseForUser($userID != 0 ? $userID : $this->_id, 'lang_custom', 'validationsms2');
|
|
$smsText = str_replace('%%code%%', $smsValidationCode, $smsText);
|
|
|
|
$sms = _new('BMSMS', array(0, false));
|
|
$sms->Send($bm_prefs['mail2sms_abs'], preg_replace('/[^0-9]/', '', str_replace('+', '00', $userRow['mail2sms_nummer'])), $smsText, $bm_prefs['smsvalidation_type'], false, false);
|
|
|
|
// set code
|
|
$db->Query('UPDATE {pre}users SET `sms_validation_code`=?,`sms_validation_time`=?,`sms_validation`=? WHERE `id`=?',
|
|
$smsValidationCode,
|
|
time(),
|
|
0,
|
|
$userID != 0 ? $userID : $this->_id);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
* get user's VCard
|
|
*
|
|
* @return string
|
|
*/
|
|
public function BuildVCard()
|
|
{
|
|
if(!class_exists('VCardBuilder'))
|
|
include(B1GMAIL_DIR . 'serverlib/vcard.class.php');
|
|
|
|
// fields
|
|
$countryList = CountryList();
|
|
$fields = array(
|
|
'vorname' => $this->_row['vorname'],
|
|
'nachname' => $this->_row['nachname'],
|
|
'strassenr' => trim($this->_row['strasse'] . ' ' . $this->_row['hnr']),
|
|
'plz' => $this->_row['plz'],
|
|
'ort' => $this->_row['ort'],
|
|
'land' => $countryList[$this->_row['land']],
|
|
'tel' => $this->_row['tel'],
|
|
'fax' => $this->_row['fax'],
|
|
'handy' => $this->_row['mail2sms_nummer'],
|
|
'firma' => $this->_row['company'],
|
|
'email' => ExtractMailAddress($this->GetDefaultSender())
|
|
);
|
|
|
|
// generate vcf
|
|
$vcardBuilder = _new('VCardBuilder', array($fields));
|
|
return($vcardBuilder->Build());
|
|
}
|
|
|
|
/**
|
|
* get root certificates of user
|
|
*
|
|
* @return array
|
|
*/
|
|
public function GetRootCertificates()
|
|
{
|
|
global $db;
|
|
|
|
$certs = array();
|
|
$res = $db->Query('SELECT `hash`,`pemdata` FROM {pre}certificates WHERE `userid`=? AND `type`=?',
|
|
$this->_id,
|
|
CERTIFICATE_TYPE_ROOT);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$certs[$row['hash']] = $row['pemdata'];
|
|
$res->Free();
|
|
|
|
return($certs);
|
|
}
|
|
|
|
/**
|
|
* get certificate for e-mail address
|
|
*
|
|
* @param string $email E-Mail address
|
|
* @param int $type Certificate type
|
|
* @return mixed Array with certificate info or false on error
|
|
*/
|
|
public function GetCertificateForAddress($email, $type = CERTIFICATE_TYPE_PUBLIC)
|
|
{
|
|
global $db;
|
|
|
|
$result = false;
|
|
$res = $db->Query('SELECT `certificateid`,`hash`,`cn`,`email`,`validfrom`,`validto`,`pemdata`,`type` FROM {pre}certificates WHERE `userid`=? AND `type`=? AND `email`=? AND `validfrom`<=? AND `validto`>=? ORDER BY `validfrom` ASC LIMIT 1',
|
|
$this->_id,
|
|
$type,
|
|
$email,
|
|
time(),
|
|
time());
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$result = $row;
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get keyring of user
|
|
*
|
|
* @return array
|
|
*/
|
|
public function GetKeyRing($sortColumn = 'certificateid', $sortOrder = 'ASC', $type = CERTIFICATE_TYPE_PUBLIC)
|
|
{
|
|
global $db;
|
|
|
|
$certs = array();
|
|
$res = $db->Query('SELECT `certificateid`,`hash`,`cn`,`email`,`validfrom`,`validto`,`pemdata`,`type` FROM {pre}certificates WHERE `userid`=? AND `type`=? ORDER BY ' . $sortColumn . ' ' . $sortOrder,
|
|
$this->_id,
|
|
$type);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$certs[$row['certificateid']] = $row;
|
|
$res->Free();
|
|
|
|
return($certs);
|
|
}
|
|
|
|
/**
|
|
* store a x509-certificate in PEM format in the user's keyring
|
|
*
|
|
* @param string $pemData PEM data
|
|
* @return mixed Certificate hash or false on error
|
|
*/
|
|
public function StoreCertificate($pemData, $certType = CERTIFICATE_TYPE_PUBLIC)
|
|
{
|
|
global $db;
|
|
|
|
// parse cert
|
|
$cert = openssl_x509_read($pemData);
|
|
if(!$cert)
|
|
return(false);
|
|
$certInfo = openssl_x509_parse($cert);
|
|
openssl_x509_free($cert);
|
|
|
|
// check purpose
|
|
$smimeSign = $smimeEncrypt = false;
|
|
foreach($certInfo['purposes'] as $purpose)
|
|
{
|
|
if($purpose[2] == 'smimeencrypt' && $purpose[0])
|
|
$smimeEncrypt = true;
|
|
if($purpose[2] == 'smimesign' && $purpose[0])
|
|
$smimeSign = true;
|
|
if($purpose[2] == 'any' && $purpose[0])
|
|
{
|
|
$smimeEncrypt = true;
|
|
$smimeSign = true;
|
|
}
|
|
}
|
|
if(!$smimeSign && !$smimeEncrypt)
|
|
return(false);
|
|
|
|
// check if exists
|
|
$res = $db->Query('SELECT COUNT(*) FROM {pre}certificates WHERE `hash`=? AND `userid`=? AND `type`=?',
|
|
$certInfo['hash'],
|
|
$this->_id,
|
|
$certType);
|
|
list($certCount) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
// add?
|
|
if($certCount == 0)
|
|
{
|
|
$certMail = '';
|
|
|
|
if(isset($certInfo['extensions']['subjectAltName'])
|
|
&& substr($certInfo['extensions']['subjectAltName'], 0, 6) == 'email:')
|
|
{
|
|
$certMail = substr($certInfo['extensions']['subjectAltName'], 6);
|
|
}
|
|
else if(isset($certInfo['subject']['emailAddress']))
|
|
{
|
|
$certMail = $certInfo['subject']['emailAddress'];
|
|
}
|
|
|
|
$db->Query('INSERT INTO {pre}certificates(`type`,`userid`,`hash`,`cn`,`email`,`validfrom`,`validto`,`pemdata`) VALUES(?,?,?,?,?,?,?,?)',
|
|
$certType,
|
|
$this->_id,
|
|
$certInfo['hash'],
|
|
is_array($certInfo['subject']['CN']) ? array_unshift($certInfo['subject']['CN']) : $certInfo['subject']['CN'],
|
|
$certMail,
|
|
$certInfo['validFrom_time_t'],
|
|
$certInfo['validTo_time_t'],
|
|
$pemData);
|
|
}
|
|
|
|
// return
|
|
return($certInfo['hash']);
|
|
}
|
|
|
|
/**
|
|
* export cert + pk + chain certs as PKCS12 file
|
|
*
|
|
* @param string $hash Certificate hash
|
|
* @param string $pass Password for PKCS12 file
|
|
* @return mixed String with PKCS12 data or false on error
|
|
*/
|
|
public function ExportPrivateCertificateAsPKCS12($hash, $pass)
|
|
{
|
|
$result = false;
|
|
|
|
$certData = $this->GetCertificateByHash($hash);
|
|
if(!$certData)
|
|
return(false);
|
|
|
|
$privKeyPEMData = $this->GetPrivateKey($hash);
|
|
if(!$privKeyPEMData)
|
|
return(false);
|
|
|
|
$privKeyPass = $this->GetPrivateKeyPassword($hash);
|
|
$privKey = !empty($privKeyPass) ? array($privKeyPEMData, $privKeyPass) : $privKeyPEMData;
|
|
|
|
$chainCerts = $this->GetChainCerts($hash);
|
|
if($chainCerts && is_array($chainCerts) && count($chainCerts) > 0)
|
|
$args = array('extracerts' => $chainCerts);
|
|
else
|
|
$args = array();
|
|
|
|
if(openssl_pkcs12_export($certData['pemdata'], $result, $privKey, $pass, $args))
|
|
return($result);
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* store a private certificate
|
|
*
|
|
* @param string $certData Certificate PEM data
|
|
* @param string $keyData Private key PEM data
|
|
* @param string $pw Private key password
|
|
* @param array $chainCerts Chain certs array
|
|
* @return mixed Certificate hash or false on error
|
|
*/
|
|
public function StorePrivateCertificate($certData, $keyData, $pw, $chainCerts = false)
|
|
{
|
|
if($certData && $keyData && strlen($certData) > 5 && strlen($keyData) > 5)
|
|
{
|
|
$certData = str_replace(' TRUSTED ', ' ', $certData);
|
|
$cert = @openssl_x509_read(trim($certData));
|
|
|
|
if($cert)
|
|
{
|
|
// check if PK fits
|
|
if(@openssl_x509_check_private_key($cert,
|
|
!empty($pw) ? array($keyData, $pw) : $keyData))
|
|
{
|
|
$certInfo = openssl_x509_parse($cert);
|
|
|
|
// check purpose
|
|
$smimeSign = $smimeEncrypt = false;
|
|
foreach($certInfo['purposes'] as $purpose)
|
|
{
|
|
if($purpose[2] == 'smimeencrypt' && $purpose[0])
|
|
$smimeEncrypt = true;
|
|
if($purpose[2] == 'smimesign' && $purpose[0])
|
|
$smimeSign = true;
|
|
if($purpose[2] == 'any' && $purpose[0])
|
|
{
|
|
$smimeEncrypt = true;
|
|
$smimeSign = true;
|
|
}
|
|
}
|
|
if(!$smimeSign && !$smimeEncrypt)
|
|
return(false);
|
|
|
|
// add cert
|
|
if(($hash = $this->StoreCertificate($certData, CERTIFICATE_TYPE_PRIVATE)) !== false)
|
|
{
|
|
$this->SetPrivateKey($hash, $keyData);
|
|
if(!empty($pw))
|
|
$this->SetPrivateKeyPassword($hash, $pw);
|
|
if($chainCerts !== false && is_array($chainCerts) && count($chainCerts) > 0)
|
|
$this->SetChainCerts($hash, $chainCerts);
|
|
return($hash);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* delete certificate by supplying the certificate hash
|
|
*
|
|
* @param string $hash Certificate hash
|
|
* @return bool
|
|
*/
|
|
public function DeleteCertificateByHash($hash, $type = 0)
|
|
{
|
|
global $db;
|
|
|
|
if($type == CERTIFICATE_TYPE_PRIVATE)
|
|
{
|
|
$this->DeletePref('ChainCerts_' . $hash);
|
|
$this->DeletePref('PrivateKey_' . $hash);
|
|
$this->DeletePref('PrivateKeyPassword_' . $hash);
|
|
}
|
|
|
|
$db->Query('DELETE FROM {pre}certificates WHERE `hash`=? AND `userid`=?'
|
|
. ($type > 0 ? ' AND `type`=' . (int)$type : ''),
|
|
$hash,
|
|
$this->_id);
|
|
if($db->AffectedRows() == 1)
|
|
return(true);
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* set chain certs
|
|
*
|
|
* @param string $hash Certificate hash
|
|
* @param array $certs Chain certs
|
|
*/
|
|
public function SetChainCerts($hash, $certs)
|
|
{
|
|
$this->SetPref('ChainCerts_' . $hash, serialize($certs));
|
|
}
|
|
|
|
/**
|
|
* get chain certs
|
|
*
|
|
* @param string $hash Certificate hash
|
|
* @return array
|
|
*/
|
|
public function GetChainCerts($hash)
|
|
{
|
|
$result = @unserialize($this->GetPref('ChainCerts_' . $hash));
|
|
return(is_array($result) ? $result : false);
|
|
}
|
|
|
|
/**
|
|
* return an array of recipients with missing certificate
|
|
*
|
|
* @param array $recipients Recipient list
|
|
* @return array
|
|
*/
|
|
public function GetRecipientsWithMissingCertificate($recipients, $type = CERTIFICATE_TYPE_PUBLIC)
|
|
{
|
|
global $db;
|
|
|
|
foreach($recipients as $key=>$val)
|
|
$recipients[$key] = strtolower($val);
|
|
|
|
$res = $db->Query('SELECT `email` FROM {pre}certificates WHERE `userid`=? AND `email` IN ? AND `type`=? AND `validfrom`<=? AND `validto`>=?',
|
|
$this->_id,
|
|
$recipients,
|
|
$type,
|
|
time(),
|
|
time());
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
while(($arrayKey = array_search(strtolower($row['email']), $recipients)) !== false)
|
|
unset($recipients[$arrayKey]);
|
|
}
|
|
$res->Free();
|
|
|
|
return($recipients);
|
|
}
|
|
|
|
/**
|
|
* fetch a certificate from keyring by supplying the certificate hash
|
|
*
|
|
* @param string $hash Certificate hash
|
|
* @return array
|
|
*/
|
|
public function GetCertificateByHash($hash)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT `type`,`userid`,`hash`,`cn`,`email`,`validfrom`,`validto`,`pemdata` FROM {pre}certificates WHERE `userid`=? AND `hash`=? LIMIT 1',
|
|
$this->_id,
|
|
$hash);
|
|
if($res->RowCount() == 1)
|
|
{
|
|
$result = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
/**
|
|
* get the user's xor key salt
|
|
*
|
|
* @return string
|
|
*/
|
|
public function GetXORSalt()
|
|
{
|
|
$salt = $this->GetPref('XORKeySalt');
|
|
|
|
if(!$salt || strlen($salt) < 64)
|
|
{
|
|
$salt = '';
|
|
for($i=0; $i<64; $i++)
|
|
$salt .= chr(mt_rand(0, 255));
|
|
$salt = base64_encode($salt);
|
|
$this->SetPref('XORKeySalt', $salt);
|
|
}
|
|
|
|
$salt = base64_decode($salt);
|
|
return($salt);
|
|
}
|
|
|
|
/**
|
|
* generate XOR crypt key for user
|
|
*
|
|
* @param int $userID User ID
|
|
* @param string $passwordPlain Plaintext user password
|
|
* @return string
|
|
*/
|
|
static function GenerateXORCryptKey($userID, $passwordPlain)
|
|
{
|
|
$user = _new('BMUser', array($userID));
|
|
$salt = $user->GetXORSalt();
|
|
return(md5($passwordPlain . $salt));
|
|
}
|
|
|
|
/**
|
|
* encrypt and set private key password
|
|
*
|
|
* @param string $pw Plaintext password
|
|
* @return bool
|
|
*/
|
|
public function SetPrivateKeyPassword($certID, $pw)
|
|
{
|
|
if(!isset($_SESSION['bm_xorCryptKey']))
|
|
return(false);
|
|
|
|
$encryptedPW = XORCrypt($pw, $_SESSION['bm_xorCryptKey']);
|
|
$this->SetPref('PrivateKeyPassword_' . $certID, base64_encode($encryptedPW));
|
|
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
* get and decrypt private key password
|
|
*
|
|
* @return string Plaintext password
|
|
*/
|
|
public function GetPrivateKeyPassword($certID)
|
|
{
|
|
if(!isset($_SESSION['bm_xorCryptKey']))
|
|
return(false);
|
|
|
|
$encryptedPW = $this->GetPref('PrivateKeyPassword_' . $certID);
|
|
if(!$encryptedPW || strlen($encryptedPW) == 0)
|
|
return('');
|
|
|
|
$pw = XORCrypt(base64_decode($encryptedPW), $_SESSION['bm_xorCryptKey']);
|
|
return($pw);
|
|
}
|
|
|
|
/**
|
|
* get all available private key passwords
|
|
*
|
|
* @return array
|
|
*/
|
|
public function GetPrivateKeyPasswords()
|
|
{
|
|
global $db;
|
|
|
|
if(!isset($_SESSION['bm_xorCryptKey']))
|
|
return(false);
|
|
|
|
$result = array();
|
|
|
|
$res = $db->Query('SELECT `key`,`value` FROM {pre}userprefs WHERE userID=? AND `key` LIKE ?',
|
|
(int)$this->_id,
|
|
'PrivateKeyPassword_%');
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
list(, $certID) = explode('_', $row['key']);
|
|
$result[$certID] = XORCrypt(base64_decode($row['value']), $_SESSION['bm_xorCryptKey']);
|
|
}
|
|
$res->Free();
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* set private key passwords
|
|
*
|
|
* @param array $in Input (hash => pw)
|
|
* @return bool
|
|
*/
|
|
public function SetPrivateKeyPasswords($in)
|
|
{
|
|
if(!isset($_SESSION['bm_xorCryptKey']))
|
|
return(false);
|
|
|
|
foreach($in as $certID=>$pw)
|
|
{
|
|
$encryptedPW = XORCrypt($pw, $_SESSION['bm_xorCryptKey']);
|
|
$this->SetPref('PrivateKeyPassword_' . $certID, base64_encode($encryptedPW));
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
* set private key for cert
|
|
*
|
|
* @param int $certID Certificate hash
|
|
* @param string $data PEM data
|
|
*/
|
|
public function SetPrivateKey($certID, $data)
|
|
{
|
|
$this->SetPref('PrivateKey_' . $certID, $data);
|
|
}
|
|
|
|
/**
|
|
* get private key for cert
|
|
*
|
|
* @param string $certID Certificate hash
|
|
* @return string PEM data
|
|
*/
|
|
public function GetPrivateKey($certID)
|
|
{
|
|
return($this->GetPref('PrivateKey_' . $certID));
|
|
}
|
|
|
|
/**
|
|
* get order list
|
|
*
|
|
* @param string $sortColumn Column to sort by
|
|
* @param string $sortOrder Sort order
|
|
* @return array
|
|
*/
|
|
public function GetOrderList($sortColumn = 'created', $sortOrder = 'DESC')
|
|
{
|
|
global $db, $bm_prefs;
|
|
|
|
if(!class_exists('BMPayment'))
|
|
include(B1GMAIL_DIR . 'serverlib/payment.class.php');
|
|
|
|
// fetch orders
|
|
$result = array();
|
|
$res = $db->Query('SELECT * FROM {pre}orders WHERE `userid`=? ORDER BY `' . $sortColumn . '` ' . $sortOrder,
|
|
$this->_id);
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
$row['cart'] = @unserialize($row['cart']);
|
|
if(!is_array($row['cart']))
|
|
$row['cart'] = array();
|
|
|
|
$row['amountText'] = sprintf('%.02f %s', $row['amount']/100, $bm_prefs['currency']);
|
|
$row['invoiceNo'] = BMPayment::InvoiceNo($row['orderid']);
|
|
$row['invoiceAvailable'] = false; // checked later
|
|
|
|
$result[$row['orderid']] = $row;
|
|
}
|
|
$res->Free();
|
|
|
|
// check for invoices
|
|
if(count($result) > 0)
|
|
{
|
|
$res = $db->Query('SELECT `orderid` FROM {pre}invoices WHERE `orderid` IN ?',
|
|
array_keys($result));
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
$result[$row['orderid']]['invoiceAvailable'] = true;
|
|
$res->Free();
|
|
}
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get order details
|
|
*
|
|
* @param int $orderID Order ID
|
|
* @return array
|
|
*/
|
|
public function GetOrder($orderID)
|
|
{
|
|
global $db;
|
|
|
|
$res = $db->Query('SELECT * FROM {pre}orders WHERE `userid`=? AND `orderid`=?',
|
|
$this->_id,
|
|
$orderID);
|
|
$row = $res->FetchArray(MYSQLI_ASSOC);
|
|
$res->Free();
|
|
|
|
$row['cart'] = @unserialize($row['cart']);
|
|
if(!is_array($row['cart']))
|
|
$row['cart'] = array();
|
|
|
|
return($row);
|
|
}
|
|
|
|
/**
|
|
* get order invoice
|
|
*
|
|
* @param int $orderID Order ID
|
|
* @return string
|
|
*/
|
|
public function GetOrderInvoice($orderID)
|
|
{
|
|
global $db;
|
|
|
|
$result = false;
|
|
|
|
if($this->GetOrder($orderID) !== false)
|
|
{
|
|
$res = $db->Query('SELECT `invoice` FROM {pre}invoices WHERE `orderid`=?',
|
|
$orderID);
|
|
if($res->RowCount() == 1)
|
|
list($result) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
}
|
|
|
|
return($result);
|
|
}
|
|
|
|
/**
|
|
* get all user-specific domains
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function GetUserDomains()
|
|
{
|
|
global $db;
|
|
|
|
$domains = array();
|
|
$res = $db->Query('SELECT saliase FROM {pre}users WHERE LENGTH(saliase)!=0');
|
|
while($row = $res->FetchArray(MYSQLI_ASSOC))
|
|
{
|
|
$userDomains = explode(':', strtolower($row['saliase']));
|
|
foreach($userDomains as $domain)
|
|
if(!in_array($domain, $domains))
|
|
$domains[] = $domain;
|
|
}
|
|
$res->Free();
|
|
|
|
return($domains);
|
|
}
|
|
|
|
/**
|
|
* OTP-encrypt user password and store key in DB
|
|
*
|
|
* @param string $passwordPlain Plaintext password
|
|
* @return string Encrypted password (cookie token)
|
|
*/
|
|
public static function SaveLogin($passwordPlain)
|
|
{
|
|
global $db;
|
|
|
|
$pwLength = strlen($passwordPlain);
|
|
$cookieToken = '';
|
|
$dbToken = '';
|
|
|
|
for($i=0; $i<$pwLength; $i++)
|
|
{
|
|
$rand = mt_rand(0, 255);
|
|
$dbToken .= chr($rand);
|
|
$cookieToken .= chr(ord($passwordPlain[$i]) ^ $rand);
|
|
}
|
|
|
|
$dbToken = base64_encode($dbToken);
|
|
$cookieToken = base64_encode($cookieToken);
|
|
|
|
$db->Query('INSERT INTO {pre}savedlogins(`expires`,`token`) VALUES(?,?)',
|
|
time()+TIME_ONE_YEAR,
|
|
$dbToken);
|
|
return($db->InsertId() . ':' . $cookieToken);
|
|
}
|
|
|
|
/**
|
|
* decrypt saved password using DB token
|
|
*
|
|
* @param string $token Cookie token
|
|
* @return string
|
|
*/
|
|
public static function LoadLogin($token)
|
|
{
|
|
global $db;
|
|
|
|
if(strlen($token) < 3 || strpos($token, ':') === false)
|
|
return(false);
|
|
|
|
list($tokenID, $encryptedPW) = explode(':', $token);
|
|
$res = $db->Query('SELECT `token` FROM {pre}savedlogins WHERE `id`=?',
|
|
$tokenID);
|
|
if($res->RowCount() != 1)
|
|
return(false);
|
|
list($dbToken) = $res->FetchArray(MYSQLI_NUM);
|
|
$res->Free();
|
|
|
|
$dbToken = base64_decode($dbToken);
|
|
$encryptedPW = base64_decode($encryptedPW);
|
|
|
|
if(strlen($dbToken) != strlen($encryptedPW))
|
|
return(false);
|
|
|
|
$passwordPlain = '';
|
|
for($i=0; $i<strlen($dbToken); $i++)
|
|
$passwordPlain .= chr(ord($encryptedPW[$i]) ^ ord($dbToken[$i]));
|
|
|
|
return($passwordPlain);
|
|
}
|
|
|
|
/**
|
|
* delete a saved login token
|
|
*
|
|
* @param string $token Cookie token
|
|
*/
|
|
public static function DeleteSavedLogin($token)
|
|
{
|
|
global $db;
|
|
|
|
if(strlen($token) < 3 || strpos($token, ':') === false)
|
|
return(false);
|
|
|
|
list($tokenID, $encryptedPW) = explode(':', $token);
|
|
$db->Query('DELETE FROM {pre}savedlogins WHERE `id`=?',
|
|
$tokenID);
|
|
return(true);
|
|
}
|
|
}
|