3 require_once('include/config.php');
4 require_once('include/network.php');
5 require_once('include/plugin.php');
6 require_once('include/text.php');
7 require_once('include/pgettext.php');
8 require_once('include/datetime.php');
9 require_once('include/enotify.php');
12 function create_user($arr) {
14 // Required: { username, nickname, email } or { openid_url }
17 $result = array('success' => false, 'user' => null, 'password' => '', 'message' => '');
19 $using_invites = get_config('system','invitation_only');
20 $num_invites = get_config('system','number_invites');
23 $invite_id = ((x($arr,'invite_id')) ? notags(trim($arr['invite_id'])) : '');
24 $username = ((x($arr,'username')) ? notags(trim($arr['username'])) : '');
25 $nickname = ((x($arr,'nickname')) ? notags(trim($arr['nickname'])) : '');
26 $email = ((x($arr,'email')) ? notags(trim($arr['email'])) : '');
27 $openid_url = ((x($arr,'openid_url')) ? notags(trim($arr['openid_url'])) : '');
28 $photo = ((x($arr,'photo')) ? notags(trim($arr['photo'])) : '');
29 $password = ((x($arr,'password')) ? trim($arr['password']) : '');
30 $password1 = ((x($arr,'password1')) ? trim($arr['password1']) : '');
31 $confirm = ((x($arr,'confirm')) ? trim($arr['confirm']) : '');
32 $blocked = ((x($arr,'blocked')) ? intval($arr['blocked']) : 0);
33 $verified = ((x($arr,'verified')) ? intval($arr['verified']) : 0);
35 $publish = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
36 $netpublish = ((strlen(get_config('system','directory'))) ? $publish : 0);
38 if ($password1 != $confirm) {
39 $result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
41 } elseif ($password1 != "")
42 $password = $password1;
44 $tmp_str = $openid_url;
48 $result['message'] .= t('An invitation is required.') . EOL;
51 $r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
53 $result['message'] .= t('Invitation could not be verified.') . EOL;
58 if((! x($username)) || (! x($email)) || (! x($nickname))) {
60 if(! validate_url($tmp_str)) {
61 $result['message'] .= t('Invalid OpenID url') . EOL;
64 $_SESSION['register'] = 1;
65 $_SESSION['openid'] = $openid_url;
66 require_once('library/openid.php');
67 $openid = new LightOpenID;
68 $openid->identity = $openid_url;
69 $openid->returnUrl = z_root() . '/openid';
70 $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson');
71 $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
73 $authurl = $openid->authUrl();
74 } catch (Exception $e){
75 $result['message'] .= t("We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID."). EOL . EOL . t("The error message was:") . $e->getMessage() . EOL;
82 notice( t('Please enter the required information.') . EOL );
86 if(! validate_url($tmp_str))
92 // collapse multiple spaces in name
93 $username = preg_replace('/ +/',' ',$username);
95 if(mb_strlen($username) > 48)
96 $result['message'] .= t('Please use a shorter name.') . EOL;
97 if(mb_strlen($username) < 3)
98 $result['message'] .= t('Name too short.') . EOL;
100 // So now we are just looking for a space in the full name.
102 $loose_reg = get_config('system','no_regfullname');
104 $username = mb_convert_case($username,MB_CASE_TITLE,'UTF-8');
105 if(! strpos($username,' '))
106 $result['message'] .= t("That doesn't appear to be your full \x28First Last\x29 name.") . EOL;
110 if(! allowed_email($email))
111 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
113 if((! valid_email($email)) || (! validate_email($email)))
114 $result['message'] .= t('Not a valid email address.') . EOL;
116 // Disallow somebody creating an account using openid that uses the admin email address,
117 // since openid bypasses email verification. We'll allow it if there is not yet an admin account.
119 $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
121 //if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) {
122 if((x($a->config,'admin_email')) && in_array(strtolower($email), $adminlist) && strlen($openid_url)) {
123 $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
126 if (dbm::is_result($r))
127 $result['message'] .= t('Cannot use that email.') . EOL;
130 $nickname = $arr['nickname'] = strtolower($nickname);
132 if(! preg_match("/^[a-z0-9][a-z0-9\_]*$/",$nickname))
133 $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9" and "_".') . EOL;
135 $r = q("SELECT `uid` FROM `user`
136 WHERE `nickname` = '%s' LIMIT 1",
139 if (dbm::is_result($r))
140 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
142 // Check deleted accounts that had this nickname. Doesn't matter to us,
143 // but could be a security issue for federated platforms.
145 $r = q("SELECT * FROM `userd`
146 WHERE `username` = '%s' LIMIT 1",
149 if (dbm::is_result($r))
150 $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
152 if(strlen($result['message'])) {
156 $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
157 $new_password_encoded = hash('whirlpool',$new_password);
159 $result['password'] = $new_password;
161 require_once('include/crypto.php');
163 $keys = new_keypair(4096);
165 if($keys === false) {
166 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
170 $default_service_class = get_config('system','default_service_class');
171 if(! $default_service_class)
172 $default_service_class = '';
175 $prvkey = $keys['prvkey'];
176 $pubkey = $keys['pubkey'];
180 * Create another keypair for signing/verifying
181 * salmon protocol messages. We have to use a slightly
182 * less robust key because this won't be using openssl
183 * but the phpseclib. Since it is PHP interpreted code
184 * it is not nearly as efficient, and the larger keys
185 * will take several minutes each to process.
189 $sres = new_keypair(512);
190 $sprvkey = $sres['prvkey'];
191 $spubkey = $sres['pubkey'];
193 $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,
194 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `service_class`, `default-location` )
195 VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '%s', '' )",
196 dbesc(generate_user_guid()),
198 dbesc($new_password_encoded),
206 dbesc(datetime_convert()),
209 dbesc($default_service_class)
213 $r = q("SELECT * FROM `user`
214 WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
216 dbesc($new_password_encoded)
218 if (dbm::is_result($r)) {
220 $newuid = intval($r[0]['uid']);
224 $result['message'] .= t('An error occurred during registration. Please try again.') . EOL ;
229 * if somebody clicked submit twice very quickly, they could end up with two accounts
230 * due to race condition. Remove this one.
233 $r = q("SELECT `uid` FROM `user`
234 WHERE `nickname` = '%s' ",
237 if ((dbm::is_result($r)) && (count($r) > 1) && $newuid) {
238 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
239 q("DELETE FROM `user` WHERE `uid` = %d",
245 if(x($newuid) !== false) {
246 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
247 VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
252 dbesc(z_root() . "/photo/profile/{$newuid}.jpg"),
253 dbesc(z_root() . "/photo/avatar/{$newuid}.jpg"),
259 $result['message'] .= t('An error occurred creating your default profile. Please try again.') . EOL;
260 // Start fresh next time.
261 $r = q("DELETE FROM `user` WHERE `uid` = %d",
266 // Create the self contact
267 user_create_self_contact($newuid);
269 // Create a group with no members. This allows somebody to use it
270 // right away as a default group for new contacts.
272 require_once('include/group.php');
273 group_add($newuid, t('Friends'));
275 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
279 if (dbm::is_result($r)) {
280 $def_gid = $r[0]['id'];
282 q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
288 if(get_config('system', 'newuser_private') && $def_gid) {
289 q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
290 dbesc("<" . $def_gid . ">"),
297 // if we have no OpenID photo try to look up an avatar
299 $photo = avatar_img($email);
301 // unless there is no avatar-plugin loaded
303 require_once('include/Photo.php');
304 $photo_failure = false;
306 $filename = basename($photo);
307 $img_str = fetch_url($photo,true);
308 // guess mimetype from headers or filename
309 $type = guess_image_type($photo,true);
312 $img = new Photo($img_str, $type);
313 if($img->is_valid()) {
315 $img->scaleImageSquare(175);
317 $hash = photo_new_resource();
319 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
322 $photo_failure = true;
325 $img->scaleImage(80);
327 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
330 $photo_failure = true;
333 $img->scaleImage(48);
335 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
338 $photo_failure = true;
341 if (! $photo_failure) {
342 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
349 call_hooks('register_account', $newuid);
351 $result['success'] = true;
352 $result['user'] = $u;
358 * @brief create the "self" contact from data from the user table
360 * @param integer $uid
362 function user_create_self_contact($uid) {
364 // Only create the entry if it doesn't exist yet
365 $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
366 if (dbm::is_result($r)) {
370 $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
371 if (!dbm::is_result($r)) {
377 q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
378 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
379 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
380 intval($user['uid']),
382 dbesc($user['username']),
383 dbesc($user['nickname']),
384 dbesc(z_root()."/photo/profile/".$user['uid'].".jpg"),
385 dbesc(z_root()."/photo/avatar/".$user['uid'].".jpg"),
386 dbesc(z_root()."/photo/micro/".$user['uid'].".jpg"),
387 dbesc(z_root()."/profile/".$user['nickname']),
388 dbesc(normalise_link(z_root()."/profile/".$user['nickname'])),
389 dbesc($user['nickname'].'@'.substr(z_root(), strpos(z_root(),'://') + 3)),
390 dbesc(z_root()."/dfrn_request/".$user['nickname']),
391 dbesc(z_root()."/dfrn_notify/".$user['nickname']),
392 dbesc(z_root()."/dfrn_poll/".$user['nickname']),
393 dbesc(z_root()."/dfrn_confirm/".$user['nickname']),
394 dbesc(z_root()."/poco/".$user['nickname']),
395 dbesc(datetime_convert()),
396 dbesc(datetime_convert()),
397 dbesc(datetime_convert())
402 * @brief send registration confiĆmation with the intormation that reg is pending
404 * @param string $email
405 * @param string $sitename
406 * @param string $username
407 * @return NULL|boolean from notification() and email() inherited
409 function send_register_pending_eml($email, $sitename, $username) {
412 Thank you for registering at %2$s. Your account is pending for approval by the administrator.
415 $body = sprintf($body, $username, $sitename);
417 return notification(array(
418 'type' => "SYSTEM_EMAIL",
419 'to_email' => $email,
420 'subject'=> sprintf( t('Registration at %s'), $sitename),
425 * send registration confirmation.
426 * It's here as a function because the mail is sent
427 * from different parts
429 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
430 $preamble = deindent(t('
432 Thank you for registering at %2$s. Your account has been created.
435 The login details are as follows:
440 You may change your password from your account "Settings" page after logging
443 Please take a few moments to review the other account settings on that page.
445 You may also wish to add some basic information to your default profile
446 (on the "Profiles" page) so that other people can easily find you.
448 We recommend setting your full name, adding a profile photo,
449 adding some profile "keywords" (very useful in making new friends) - and
450 perhaps what country you live in; if you do not wish to be more specific
453 We fully respect your right to privacy, and none of these items are necessary.
454 If you are new and do not know anybody here, they may help
455 you to make some new and interesting friends.
458 Thank you and welcome to %2$s.'));
460 $preamble = sprintf($preamble, $username, $sitename);
461 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
463 return notification(array(
464 'type' => "SYSTEM_EMAIL",
465 'to_email' => $email,
466 'subject'=> sprintf( t('Registration details for %s'), $sitename),
467 'preamble'=> $preamble,