1<?php
2
3/*
4	[UCenter] (C)2001-2099 Comsenz Inc.
5	This is NOT a freeware, use is subject to license terms
6
7	$Id: user.php 1179 2014-11-03 07:11:25Z hypowang $
8*/
9
10!defined('IN_UC') && exit('Access Denied');
11
12class usermodel {
13
14	var $db;
15	var $base;
16
17	function __construct(&$base) {
18		$this->usermodel($base);
19	}
20
21	function usermodel(&$base) {
22		$this->base = $base;
23		$this->db = $base->db;
24	}
25
26	function get_user_by_uid($uid) {
27		$arr = $this->db->fetch_first("SELECT * FROM ".UC_DBTABLEPRE."members WHERE uid='$uid'");
28		return $arr;
29	}
30
31	function get_user_by_username($username) {
32		$arr = $this->db->fetch_first("SELECT * FROM ".UC_DBTABLEPRE."members WHERE username='$username'");
33		return $arr;
34	}
35
36	function get_user_by_email($email) {
37		$arr = $this->db->fetch_first("SELECT * FROM ".UC_DBTABLEPRE."members WHERE email='$email'");
38		return $arr;
39	}
40
41	function check_username($username) {
42		$guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
43		$len = $this->dstrlen($username);
44		if($len > 15 || $len < 3 || preg_match("/\s+|^c:\\con\\con|[%,\*\"\s\<\>\&]|$guestexp/is", $username)) {
45			return FALSE;
46		} else {
47			return TRUE;
48		}
49	}
50
51	function dstrlen($str) {
52		if(strtolower(UC_CHARSET) != 'utf-8') {
53			return strlen($str);
54		}
55		$count = 0;
56		for($i = 0; $i < strlen($str); $i++){
57			$value = ord($str[$i]);
58			if($value > 127) {
59				$count++;
60				if($value >= 192 && $value <= 223) $i++;
61				elseif($value >= 224 && $value <= 239) $i = $i + 2;
62				elseif($value >= 240 && $value <= 247) $i = $i + 3;
63		    	}
64	    		$count++;
65		}
66		return $count;
67	}
68
69	function check_mergeuser($username) {
70		$data = $this->db->result_first("SELECT count(*) FROM ".UC_DBTABLEPRE."mergemembers WHERE appid='".$this->base->app['appid']."' AND username='$username'");
71		return $data;
72	}
73
74	function check_usernamecensor($username) {
75		$_CACHE['badwords'] = $this->base->cache('badwords');
76		$censorusername = $this->base->get_setting('censorusername');
77		$censorusername = $censorusername['censorusername'];
78		$censorexp = '/^('.str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censorusername = trim($censorusername)), '/')).')$/i';
79		$usernamereplaced = isset($_CACHE['badwords']['findpattern']) && !empty($_CACHE['badwords']['findpattern']) ? @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username) : $username;
80		if(($usernamereplaced != $username) || ($censorusername && preg_match($censorexp, $username))) {
81			return FALSE;
82		} else {
83			return TRUE;
84		}
85	}
86
87	function check_usernameexists($username) {
88		$data = $this->db->result_first("SELECT username FROM ".UC_DBTABLEPRE."members WHERE username='$username'");
89		return $data;
90	}
91
92	function check_emailformat($email) {
93		return strlen($email) > 6 && strlen($email) <= 32 && preg_match("/^([a-z0-9\-_.+]+)@([a-z0-9\-]+[.][a-z0-9\-.]+)$/", $email);
94	}
95
96	function check_emailaccess($email) {
97		$setting = $this->base->get_setting(array('accessemail', 'censoremail'));
98		$accessemail = $setting['accessemail'];
99		$censoremail = $setting['censoremail'];
100		$accessexp = '/('.str_replace("\r\n", '|', preg_quote(trim($accessemail), '/')).')$/i';
101		$censorexp = '/('.str_replace("\r\n", '|', preg_quote(trim($censoremail), '/')).')$/i';
102		if($accessemail || $censoremail) {
103			if(($accessemail && !preg_match($accessexp, $email)) || ($censoremail && preg_match($censorexp, $email))) {
104				return FALSE;
105			} else {
106				return TRUE;
107			}
108		} else {
109			return TRUE;
110		}
111	}
112
113	function check_emailexists($email, $username = '') {
114		$sqladd = $username !== '' ? "AND username<>'$username'" : '';
115		$email = $this->db->result_first("SELECT email FROM  ".UC_DBTABLEPRE."members WHERE email='$email' $sqladd");
116		return $email;
117	}
118
119	function check_login($username, $password, &$user) {
120		$user = $this->get_user_by_username($username);
121		if(empty($user['username'])) {
122			return -1;
123		} elseif($user['password'] != md5(md5($password).$user['salt'])) {
124			return -2;
125		}
126		return $user['uid'];
127	}
128
129	function add_user($username, $password, $email, $uid = 0, $questionid = '', $answer = '', $regip = '') {
130		$regip = empty($regip) ? $this->base->onlineip : $regip;
131		$salt = substr(uniqid(rand()), -6);
132		$password = md5(md5($password).$salt);
133		$sqladd = $uid ? "uid='".intval($uid)."'," : '';
134		$sqladd .= $questionid > 0 ? " secques='".$this->quescrypt($questionid, $answer)."'," : " secques='',";
135		$this->db->query("INSERT INTO ".UC_DBTABLEPRE."members SET $sqladd username='$username', password='$password', email='$email', regip='$regip', regdate='".$this->base->time."', salt='$salt'");
136		$uid = $this->db->insert_id();
137		$this->db->query("INSERT INTO ".UC_DBTABLEPRE."memberfields SET uid='$uid'");
138		return $uid;
139	}
140
141	function edit_user($username, $oldpw, $newpw, $email, $ignoreoldpw = 0, $questionid = '', $answer = '') {
142		$data = $this->db->fetch_first("SELECT username, uid, password, salt FROM ".UC_DBTABLEPRE."members WHERE username='$username'");
143
144		if($ignoreoldpw) {
145			$isprotected = $this->db->result_first("SELECT COUNT(*) FROM ".UC_DBTABLEPRE."protectedmembers WHERE uid = '$data[uid]'");
146			if($isprotected) {
147				return -8;
148			}
149		}
150
151		if(!$ignoreoldpw && $data['password'] != md5(md5($oldpw).$data['salt'])) {
152			return -1;
153		}
154
155		$sqladd = $newpw ? "password='".md5(md5($newpw).$data['salt'])."'" : '';
156		$sqladd .= $email ? ($sqladd ? ',' : '')." email='$email'" : '';
157		if($questionid !== '') {
158			if($questionid > 0) {
159				$sqladd .= ($sqladd ? ',' : '')." secques='".$this->quescrypt($questionid, $answer)."'";
160			} else {
161				$sqladd .= ($sqladd ? ',' : '')." secques=''";
162			}
163		}
164		if($sqladd || $emailadd) {
165			$this->db->query("UPDATE ".UC_DBTABLEPRE."members SET $sqladd WHERE username='$username'");
166			return $this->db->affected_rows();
167		} else {
168			return -7;
169		}
170	}
171
172	function delete_user($uidsarr) {
173		$uidsarr = (array)$uidsarr;
174		if(!$uidsarr) {
175			return 0;
176		}
177		$uids = $this->base->implode($uidsarr);
178		$arr = $this->db->fetch_all("SELECT uid FROM ".UC_DBTABLEPRE."protectedmembers WHERE uid IN ($uids)");
179		$puids = array();
180		foreach((array)$arr as $member) {
181			$puids[] = $member['uid'];
182		}
183		$uids = $this->base->implode(array_diff($uidsarr, $puids));
184		if($uids) {
185			$this->db->query("DELETE FROM ".UC_DBTABLEPRE."members WHERE uid IN($uids)");
186			$this->db->query("DELETE FROM ".UC_DBTABLEPRE."memberfields WHERE uid IN($uids)");
187			uc_user_deleteavatar($uidsarr);
188			$this->base->load('note');
189			$_ENV['note']->add('deleteuser', "ids=$uids");
190			return $this->db->affected_rows();
191		} else {
192			return 0;
193		}
194	}
195
196	function get_total_num($sqladd = '') {
197		$data = $this->db->result_first("SELECT COUNT(*) FROM ".UC_DBTABLEPRE."members $sqladd");
198		return $data;
199	}
200
201	function get_list($page, $ppp, $totalnum, $sqladd) {
202		$start = $this->base->page_get_start($page, $ppp, $totalnum);
203		$data = $this->db->fetch_all("SELECT * FROM ".UC_DBTABLEPRE."members $sqladd LIMIT $start, $ppp");
204		return $data;
205	}
206
207	function name2id($usernamesarr) {
208		$usernamesarr = uc_addslashes($usernamesarr, 1, TRUE);
209		$usernames = $this->base->implode($usernamesarr);
210		$query = $this->db->query("SELECT uid FROM ".UC_DBTABLEPRE."members WHERE username IN($usernames)");
211		$arr = array();
212		while($user = $this->db->fetch_array($query)) {
213			$arr[] = $user['uid'];
214		}
215		return $arr;
216	}
217
218	function id2name($uidarr) {
219		$arr = array();
220		$query = $this->db->query("SELECT uid, username FROM ".UC_DBTABLEPRE."members WHERE uid IN (".$this->base->implode($uidarr).")");
221		while($user = $this->db->fetch_array($query)) {
222			$arr[$user['uid']] = $user['username'];
223		}
224		return $arr;
225	}
226
227	function quescrypt($questionid, $answer) {
228		return $questionid > 0 && $answer != '' ? substr(md5($answer.md5($questionid)), 16, 8) : '';
229	}
230
231	function can_do_login($username, $ip = '') {
232
233		$check_times = $this->base->settings['login_failedtime'] < 1 ? 5 : $this->base->settings['login_failedtime'];
234
235		$username = substr(md5($username), 8, 15);
236		$expire = 15 * 60;
237		if(!$ip) {
238			$ip = $this->base->onlineip;
239		}
240
241		$ip_check = $user_check = array();
242		$query = $this->db->query("SELECT * FROM ".UC_DBTABLEPRE."failedlogins WHERE ip='".$ip."' OR ip='$username'");
243		while($row = $this->db->fetch_array($query)) {
244			if($row['ip'] === $username) {
245				$user_check = $row;
246			} elseif($row['ip'] === $ip) {
247				$ip_check = $row;
248			}
249		}
250
251		if(empty($ip_check) || ($this->base->time - $ip_check['lastupdate'] > $expire)) {
252			$ip_check = array();
253			$this->db->query("REPLACE INTO ".UC_DBTABLEPRE."failedlogins (ip, count, lastupdate) VALUES ('{$ip}', '0', '{$this->base->time}')");
254		}
255
256		if(empty($user_check) || ($this->base->time - $user_check['lastupdate'] > $expire)) {
257			$user_check = array();
258			$this->db->query("REPLACE INTO ".UC_DBTABLEPRE."failedlogins (ip, count, lastupdate) VALUES ('{$username}', '0', '{$this->base->time}')");
259		}
260
261		if ($ip_check || $user_check) {
262			$time_left = min(($check_times - $ip_check['count']), ($check_times - $user_check['count']));
263			return $time_left;
264
265		}
266
267		$this->db->query("DELETE FROM ".UC_DBTABLEPRE."failedlogins WHERE lastupdate<".($this->base->time - ($expire + 1)), 'UNBUFFERED');
268
269		return $check_times;
270	}
271
272	function loginfailed($username, $ip = '') {
273		$username = substr(md5($username), 8, 15);
274		if(!$ip) {
275			$ip = $this->base->onlineip;
276		}
277		$this->db->query("UPDATE ".UC_DBTABLEPRE."failedlogins SET count=count+1, lastupdate='".$this->base->time."' WHERE ip='".$ip."' OR ip='$username'");
278	}
279
280}
281