user.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. <?php
  2. /*
  3. [UCenter] (C)2001-2099 Comsenz Inc.
  4. This is NOT a freeware, use is subject to license terms
  5. $Id: user.php 1179 2014-11-03 07:11:25Z hypowang $
  6. */
  7. !defined('IN_UC') && exit('Access Denied');
  8. class usermodel
  9. {
  10. var $db;
  11. var $base;
  12. function __construct(&$base)
  13. {
  14. $this->usermodel($base);
  15. }
  16. function usermodel(&$base)
  17. {
  18. $this->base = $base;
  19. $this->db = $base->db;
  20. }
  21. function get_user_by_uid($uid)
  22. {
  23. $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'");
  24. return $arr;
  25. }
  26. function get_user_by_username($username)
  27. {
  28. $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE username='$username'");
  29. return $arr;
  30. }
  31. function get_user_by_email($email)
  32. {
  33. $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE email='$email'");
  34. return $arr;
  35. }
  36. function get_user_by_mobile($mobile)
  37. {
  38. $arr = $this->db->fetch_first("SELECT * FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile'");
  39. return $arr;
  40. }
  41. function check_username($username)
  42. {
  43. $guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
  44. $len = $this->dstrlen($username);
  45. if ($len > 15 || $len < 3 || preg_match("/\s+|^c:\\con\\con|[%,\*\"\s\<\>\&]|$guestexp/is", $username))
  46. {
  47. return FALSE;
  48. }
  49. else
  50. {
  51. return TRUE;
  52. }
  53. }
  54. function dstrlen($str)
  55. {
  56. if (strtolower(UC_CHARSET) != 'utf-8')
  57. {
  58. return strlen($str);
  59. }
  60. $count = 0;
  61. for ($i = 0; $i < strlen($str); $i++)
  62. {
  63. $value = ord($str[$i]);
  64. if ($value > 127)
  65. {
  66. $count++;
  67. if ($value >= 192 && $value <= 223)
  68. $i++;
  69. elseif ($value >= 224 && $value <= 239)
  70. $i = $i + 2;
  71. elseif ($value >= 240 && $value <= 247)
  72. $i = $i + 3;
  73. }
  74. $count++;
  75. }
  76. return $count;
  77. }
  78. function check_mergeuser($username)
  79. {
  80. $data = $this->db->result_first("SELECT count(*) FROM " . UC_DBTABLEPRE . "mergemembers WHERE appid='" . $this->base->app['appid'] . "' AND username='$username'");
  81. return $data;
  82. }
  83. function check_usernamecensor($username)
  84. {
  85. $_CACHE['badwords'] = $this->base->cache('badwords');
  86. $censorusername = $this->base->get_setting('censorusername');
  87. $censorusername = $censorusername['censorusername'];
  88. $censorexp = '/^(' . str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censorusername = trim($censorusername)), '/')) . ')$/i';
  89. $usernamereplaced = isset($_CACHE['badwords']['findpattern']) && !empty($_CACHE['badwords']['findpattern']) ? @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username) : $username;
  90. return !(($usernamereplaced != $username) || ($censorusername && preg_match($censorexp, $username)));
  91. }
  92. function check_usernameexists($username)
  93. {
  94. $data = $this->db->result_first("SELECT username FROM " . UC_DBTABLEPRE . "members WHERE username='$username'");
  95. return $data;
  96. }
  97. function check_emailformat($email)
  98. {
  99. return strlen($email) > 6 && strlen($email) <= 32 && preg_match("/^([a-z0-9\-_.+]+)@([a-z0-9\-]+[.][a-z0-9\-.]+)$/", $email);
  100. }
  101. function check_emailaccess($email)
  102. {
  103. $setting = $this->base->get_setting(array('accessemail', 'censoremail'));
  104. $accessemail = $setting['accessemail'];
  105. $censoremail = $setting['censoremail'];
  106. $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessemail), '/')) . ')$/i';
  107. $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censoremail), '/')) . ')$/i';
  108. if ($accessemail || $censoremail)
  109. {
  110. return !(($accessemail && !preg_match($accessexp, $email)) || ($censoremail && preg_match($censorexp, $email)));
  111. }
  112. else
  113. {
  114. return TRUE;
  115. }
  116. }
  117. function check_emailexists($email, $username = '')
  118. {
  119. $sqladd = $username !== '' ? "AND username<>'$username'" : '';
  120. $email = $this->db->result_first("SELECT email FROM " . UC_DBTABLEPRE . "members WHERE email='$email' $sqladd");
  121. return $email;
  122. }
  123. function check_mobileformat($mobile)
  124. {
  125. return strlen($mobile) >= 11 && preg_match("/^1[34578]\d{9}$/", $mobile);
  126. }
  127. function check_mobileaccess($mobile)
  128. {
  129. $setting = $this->base->get_setting(array('accessmobile', 'censormobile'));
  130. $accessmobile = $setting['accessmobile'];
  131. $censormobile = $setting['censormobile'];
  132. $accessexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($accessmobile), '/')) . ')$/i';
  133. $censorexp = '/(' . str_replace("\r\n", '|', preg_quote(trim($censormobile), '/')) . ')$/i';
  134. if ($accessmobile || $censormobile)
  135. {
  136. return !(($accessmobile && !preg_match($accessexp, $mobile)) || ($censormobile && preg_match($censorexp, $mobile)));
  137. }
  138. else
  139. {
  140. return TRUE;
  141. }
  142. }
  143. function check_mobileexists($mobile, $username = '')
  144. {
  145. $sqladd = $username !== '' ? "AND username<>'$username'" : '';
  146. $mobile = $this->db->result_first("SELECT mobile FROM " . UC_DBTABLEPRE . "members WHERE mobile='$mobile' $sqladd");
  147. return $mobile;
  148. }
  149. /**
  150. * 检测是否登录
  151. * @param string $username
  152. * @param string $password
  153. * @param array $user
  154. * @return int
  155. */
  156. function check_login($username, $password, &$user)
  157. {
  158. $user = $this->get_user_by_username($username);
  159. if (empty($user['username']))
  160. {
  161. return -1;
  162. }
  163. elseif ($user['password'] != md5(md5($password) . $user['salt']))
  164. {
  165. return -2;
  166. }
  167. return $user['uid'];
  168. }
  169. /**
  170. * 在Ucenter中添加一个账号
  171. * @param string $username
  172. * @param string $password
  173. * @param string $email
  174. * @param string $mobile
  175. * @param int $uid
  176. * @param array $extend
  177. * @return int
  178. */
  179. function add_user($username, $password, $email = '', $mobile = '', $uid = 0, $extend = [])
  180. {
  181. $regip = $this->base->onlineip;
  182. $salt = substr(uniqid(rand()), -6);
  183. $password = md5(md5($password) . $salt);
  184. $values = $uid ? "uid='" . intval($uid) . "'," : '';
  185. $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "members SET $values username='$username', password='$password', email='$email', regip='$regip', regdate='" . $this->base->time . "', salt='$salt'");
  186. $uid = $this->db->insert_id();
  187. $extendfields = [];
  188. foreach ($extend as $k => $v)
  189. {
  190. $extendfields[] = "{$k} = '{$v}'";
  191. }
  192. $extendfields = $extendfields ? ',' . implode(',', $extendfields) : '';
  193. $this->db->query("INSERT INTO " . UC_DBTABLEPRE . "memberfields SET uid='$uid' {$extendfields}");
  194. return $uid;
  195. }
  196. /**
  197. * 编辑Ucenter中的账号
  198. * @param string $username
  199. * @param string $password
  200. * @param string $email
  201. * @param string $mobile
  202. * @return int
  203. */
  204. function edit_user($username, $password = '', $email = '', $mobile = '', $uid = 0, $extend = [])
  205. {
  206. $uid = intval($uid);
  207. $data = $this->db->fetch_first("SELECT username, uid, password, salt FROM " . UC_DBTABLEPRE . "members WHERE uid='$uid'");
  208. if (!$data)
  209. {
  210. return -7;
  211. }
  212. $isprotected = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid = '{$data['uid']}'");
  213. if ($isprotected)
  214. {
  215. return -8;
  216. }
  217. $fields = [];
  218. if ($username)
  219. $fields[] = "username = '{$username}'";
  220. if ($email)
  221. $fields[] = "email = '{$email}'";
  222. if ($mobile)
  223. $fields[] = "mobile = '{$mobile}'";
  224. if ($password)
  225. $fields[] = "password = '" . md5(md5($password) . $data['salt']) . "'";
  226. $values = implode(',', $fields);
  227. if ($values || $extend)
  228. {
  229. if ($values)
  230. {
  231. $this->db->query("UPDATE " . UC_DBTABLEPRE . "members SET $values WHERE uid='{$data['uid']}'");
  232. }
  233. $extendfields = [];
  234. foreach ($extend as $k => $v)
  235. {
  236. $extendfields[] = "{$k} = '{$v}'";
  237. }
  238. $extendfields = $extendfields ? implode(',', $extendfields) : '';
  239. if ($extendfields)
  240. {
  241. $this->db->query("UPDATE " . UC_DBTABLEPRE . "memberfields SET {$extendfields} WHERE uid='{$data['uid']}'");
  242. }
  243. return 1;
  244. }
  245. else
  246. {
  247. return -7;
  248. }
  249. }
  250. /**
  251. * 删除一个账号
  252. * @param array $uidsarr
  253. * @return int
  254. */
  255. function delete_user($uidsarr)
  256. {
  257. $uidsarr = (array) $uidsarr;
  258. if (!$uidsarr)
  259. {
  260. return 0;
  261. }
  262. $uids = $this->base->implode($uidsarr);
  263. $arr = $this->db->fetch_all("SELECT uid FROM " . UC_DBTABLEPRE . "protectedmembers WHERE uid IN ($uids)");
  264. $puids = array();
  265. foreach ((array) $arr as $member)
  266. {
  267. $puids[] = $member['uid'];
  268. }
  269. $uids = $this->base->implode(array_diff($uidsarr, $puids));
  270. if ($uids)
  271. {
  272. $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "members WHERE uid IN($uids)");
  273. $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "memberfields WHERE uid IN($uids)");
  274. uc_user_deleteavatar($uidsarr);
  275. $this->base->load('note');
  276. $_ENV['note']->add('deleteuser', "ids=$uids");
  277. return $this->db->affected_rows();
  278. }
  279. else
  280. {
  281. return 0;
  282. }
  283. }
  284. function delete_useravatar($uidsarr)
  285. {
  286. $uidsarr = (array) $uidsarr;
  287. foreach ((array) $uidsarr as $uid)
  288. {
  289. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big', 'real')) && unlink($avatar_file);
  290. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle', 'real')) && unlink($avatar_file);
  291. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small', 'real')) && unlink($avatar_file);
  292. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'big')) && unlink($avatar_file);
  293. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'middle')) && unlink($avatar_file);
  294. file_exists($avatar_file = UC_DATADIR . './avatar/' . $this->base->get_avatar($uid, 'small')) && unlink($avatar_file);
  295. }
  296. }
  297. /**
  298. * 获取账号总数
  299. * @param string $sqladd
  300. * @return int
  301. */
  302. function get_total_num($sqladd = '')
  303. {
  304. $data = $this->db->result_first("SELECT COUNT(*) FROM " . UC_DBTABLEPRE . "members $sqladd");
  305. return $data;
  306. }
  307. /**
  308. * 获取列表
  309. * @param int $page
  310. * @param int $ppp
  311. * @param int $totalnum
  312. * @param string $sqladd
  313. * @return array
  314. */
  315. function get_list($page, $ppp, $totalnum, $sqladd)
  316. {
  317. $start = $this->base->page_get_start($page, $ppp, $totalnum);
  318. $data = $this->db->fetch_all("SELECT * FROM " . UC_DBTABLEPRE . "members $sqladd LIMIT $start, $ppp");
  319. return $data;
  320. }
  321. function name2id($usernamesarr)
  322. {
  323. $usernamesarr = uc_addslashes($usernamesarr, 1, TRUE);
  324. $usernames = $this->base->implode($usernamesarr);
  325. $query = $this->db->query("SELECT uid FROM " . UC_DBTABLEPRE . "members WHERE username IN($usernames)");
  326. $arr = array();
  327. while ($user = $this->db->fetch_array($query))
  328. {
  329. $arr[] = $user['uid'];
  330. }
  331. return $arr;
  332. }
  333. function id2name($uidarr)
  334. {
  335. $arr = array();
  336. $query = $this->db->query("SELECT uid, username FROM " . UC_DBTABLEPRE . "members WHERE uid IN (" . $this->base->implode($uidarr) . ")");
  337. while ($user = $this->db->fetch_array($query))
  338. {
  339. $arr[$user['uid']] = $user['username'];
  340. }
  341. return $arr;
  342. }
  343. function quescrypt($questionid, $answer)
  344. {
  345. return $questionid > 0 && $answer != '' ? substr(md5($answer . md5($questionid)), 16, 8) : '';
  346. }
  347. function can_do_login($username, $ip = '')
  348. {
  349. $check_times = $this->base->settings['login_failedtime'] < 1 ? 5 : $this->base->settings['login_failedtime'];
  350. $username = substr(md5($username), 8, 15);
  351. $expire = 15 * 60;
  352. if (!$ip)
  353. {
  354. $ip = $this->base->onlineip;
  355. }
  356. $ip_check = $user_check = array();
  357. $query = $this->db->query("SELECT * FROM " . UC_DBTABLEPRE . "failedlogins WHERE ip='" . $ip . "' OR ip='$username'");
  358. while ($row = $this->db->fetch_array($query))
  359. {
  360. if ($row['ip'] === $username)
  361. {
  362. $user_check = $row;
  363. }
  364. elseif ($row['ip'] === $ip)
  365. {
  366. $ip_check = $row;
  367. }
  368. }
  369. if (empty($ip_check) || ($this->base->time - $ip_check['lastupdate'] > $expire))
  370. {
  371. $ip_check = array();
  372. $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$ip}', '0', '{$this->base->time}')");
  373. }
  374. if (empty($user_check) || ($this->base->time - $user_check['lastupdate'] > $expire))
  375. {
  376. $user_check = array();
  377. $this->db->query("REPLACE INTO " . UC_DBTABLEPRE . "failedlogins (ip, count, lastupdate) VALUES ('{$username}', '0', '{$this->base->time}')");
  378. }
  379. if ($ip_check || $user_check)
  380. {
  381. $time_left = min(($check_times - $ip_check['count']), ($check_times - $user_check['count']));
  382. return $time_left;
  383. }
  384. $this->db->query("DELETE FROM " . UC_DBTABLEPRE . "failedlogins WHERE lastupdate<" . ($this->base->time - ($expire + 1)), 'UNBUFFERED');
  385. return $check_times;
  386. }
  387. function loginfailed($username, $ip = '')
  388. {
  389. $username = substr(md5($username), 8, 15);
  390. if (!$ip)
  391. {
  392. $ip = $this->base->onlineip;
  393. }
  394. $this->db->query("UPDATE " . UC_DBTABLEPRE . "failedlogins SET count=count+1, lastupdate='" . $this->base->time . "' WHERE ip='" . $ip . "' OR ip='$username'");
  395. }
  396. }