3 use Friendica\Core\Config;
4 use Friendica\Core\System;
5 use Friendica\Database\DBM;
7 require_once('include/network.php');
8 require_once('include/plugin.php');
9 require_once('include/text.php');
10 require_once('include/pgettext.php');
11 require_once('include/datetime.php');
12 require_once('include/enotify.php');
15 function create_user($arr) {
17 // Required: { username, nickname, email } or { openid_url }
20 $result = array('success' => false, 'user' => null, 'password' => '', 'message' => '');
22 $using_invites = Config::get('system','invitation_only');
23 $num_invites = Config::get('system','number_invites');
26 $invite_id = ((x($arr,'invite_id')) ? notags(trim($arr['invite_id'])) : '');
27 $username = ((x($arr,'username')) ? notags(trim($arr['username'])) : '');
28 $nickname = ((x($arr,'nickname')) ? notags(trim($arr['nickname'])) : '');
29 $email = ((x($arr,'email')) ? notags(trim($arr['email'])) : '');
30 $openid_url = ((x($arr,'openid_url')) ? notags(trim($arr['openid_url'])) : '');
31 $photo = ((x($arr,'photo')) ? notags(trim($arr['photo'])) : '');
32 $password = ((x($arr,'password')) ? trim($arr['password']) : '');
33 $password1 = ((x($arr,'password1')) ? trim($arr['password1']) : '');
34 $confirm = ((x($arr,'confirm')) ? trim($arr['confirm']) : '');
35 $blocked = ((x($arr,'blocked')) ? intval($arr['blocked']) : 0);
36 $verified = ((x($arr,'verified')) ? intval($arr['verified']) : 0);
38 $publish = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
39 $netpublish = ((strlen(Config::get('system','directory'))) ? $publish : 0);
41 if ($password1 != $confirm) {
42 $result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
44 } elseif ($password1 != "")
45 $password = $password1;
47 $tmp_str = $openid_url;
51 $result['message'] .= t('An invitation is required.') . EOL;
54 $r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
56 $result['message'] .= t('Invitation could not be verified.') . EOL;
61 if((! x($username)) || (! x($email)) || (! x($nickname))) {
63 if(! validate_url($tmp_str)) {
64 $result['message'] .= t('Invalid OpenID url') . EOL;
67 $_SESSION['register'] = 1;
68 $_SESSION['openid'] = $openid_url;
69 require_once('library/openid.php');
70 $openid = new LightOpenID;
71 $openid->identity = $openid_url;
72 $openid->returnUrl = System::baseUrl() . '/openid';
73 $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson');
74 $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
76 $authurl = $openid->authUrl();
77 } catch (Exception $e){
78 $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;
85 notice( t('Please enter the required information.') . EOL );
89 if(! validate_url($tmp_str))
95 // collapse multiple spaces in name
96 $username = preg_replace('/ +/',' ',$username);
98 if(mb_strlen($username) > 48)
99 $result['message'] .= t('Please use a shorter name.') . EOL;
100 if(mb_strlen($username) < 3)
101 $result['message'] .= t('Name too short.') . EOL;
103 // So now we are just looking for a space in the full name.
105 $loose_reg = Config::get('system','no_regfullname');
107 $username = mb_convert_case($username,MB_CASE_TITLE,'UTF-8');
108 if(! strpos($username,' '))
109 $result['message'] .= t("That doesn't appear to be your full \x28First Last\x29 name.") . EOL;
113 if(! allowed_email($email))
114 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
116 if((! valid_email($email)) || (! validate_email($email)))
117 $result['message'] .= t('Not a valid email address.') . EOL;
119 // Disallow somebody creating an account using openid that uses the admin email address,
120 // since openid bypasses email verification. We'll allow it if there is not yet an admin account.
122 $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
124 //if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) {
125 if((x($a->config,'admin_email')) && in_array(strtolower($email), $adminlist) && strlen($openid_url)) {
126 $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
129 if (DBM::is_result($r))
130 $result['message'] .= t('Cannot use that email.') . EOL;
133 $nickname = $arr['nickname'] = strtolower($nickname);
135 if(! preg_match("/^[a-z0-9][a-z0-9\_]*$/",$nickname))
136 $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9" and "_".') . EOL;
138 $r = q("SELECT `uid` FROM `user`
139 WHERE `nickname` = '%s' LIMIT 1",
142 if (DBM::is_result($r))
143 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
145 // Check deleted accounts that had this nickname. Doesn't matter to us,
146 // but could be a security issue for federated platforms.
148 $r = q("SELECT * FROM `userd`
149 WHERE `username` = '%s' LIMIT 1",
152 if (DBM::is_result($r))
153 $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
155 if(strlen($result['message'])) {
159 $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
160 $new_password_encoded = hash('whirlpool',$new_password);
162 $result['password'] = $new_password;
164 require_once('include/crypto.php');
166 $keys = new_keypair(4096);
168 if($keys === false) {
169 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
173 $prvkey = $keys['prvkey'];
174 $pubkey = $keys['pubkey'];
176 // Create another keypair for signing/verifying salmon protocol messages.
177 $sres = new_keypair(512);
178 $sprvkey = $sres['prvkey'];
179 $spubkey = $sres['pubkey'];
181 $r = q("INSERT INTO `user` (`guid`, `username`, `password`, `email`, `openid`, `nickname`,
182 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `default-location`)
183 VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '')",
184 dbesc(generate_user_guid()),
186 dbesc($new_password_encoded),
194 dbesc(datetime_convert()),
200 $r = q("SELECT * FROM `user`
201 WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
203 dbesc($new_password_encoded)
205 if (DBM::is_result($r)) {
207 $newuid = intval($r[0]['uid']);
211 $result['message'] .= t('An error occurred during registration. Please try again.') . EOL ;
216 * if somebody clicked submit twice very quickly, they could end up with two accounts
217 * due to race condition. Remove this one.
220 $r = q("SELECT `uid` FROM `user`
221 WHERE `nickname` = '%s' ",
224 if ((DBM::is_result($r)) && (count($r) > 1) && $newuid) {
225 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
226 dba::delete('user', array('uid' => $newuid));
230 if(x($newuid) !== false) {
231 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
232 VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
237 dbesc(System::baseUrl() . "/photo/profile/{$newuid}.jpg"),
238 dbesc(System::baseUrl() . "/photo/avatar/{$newuid}.jpg"),
244 $result['message'] .= t('An error occurred creating your default profile. Please try again.') . EOL;
245 // Start fresh next time.
246 dba::delete('user', array('uid' => $newuid));
250 // Create the self contact
251 user_create_self_contact($newuid);
253 // Create a group with no members. This allows somebody to use it
254 // right away as a default group for new contacts.
256 require_once('include/group.php');
257 group_add($newuid, t('Friends'));
259 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
263 if (DBM::is_result($r)) {
264 $def_gid = $r[0]['id'];
266 q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
272 if(Config::get('system', 'newuser_private') && $def_gid) {
273 q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
274 dbesc("<" . $def_gid . ">"),
281 // if we have no OpenID photo try to look up an avatar
283 $photo = avatar_img($email);
285 // unless there is no avatar-plugin loaded
287 require_once('include/Photo.php');
288 $photo_failure = false;
290 $filename = basename($photo);
291 $img_str = fetch_url($photo,true);
292 // guess mimetype from headers or filename
293 $type = guess_image_type($photo,true);
296 $img = new Photo($img_str, $type);
297 if($img->is_valid()) {
299 $img->scaleImageSquare(175);
301 $hash = photo_new_resource();
303 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
306 $photo_failure = true;
309 $img->scaleImage(80);
311 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
314 $photo_failure = true;
317 $img->scaleImage(48);
319 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
322 $photo_failure = true;
325 if (! $photo_failure) {
326 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
333 call_hooks('register_account', $newuid);
335 $result['success'] = true;
336 $result['user'] = $u;
342 * @brief create the "self" contact from data from the user table
344 * @param integer $uid
346 function user_create_self_contact($uid) {
348 // Only create the entry if it doesn't exist yet
349 $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
350 if (DBM::is_result($r)) {
354 $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
355 if (!DBM::is_result($r)) {
361 q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
362 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
363 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
364 intval($user['uid']),
366 dbesc($user['username']),
367 dbesc($user['nickname']),
368 dbesc(System::baseUrl()."/photo/profile/".$user['uid'].".jpg"),
369 dbesc(System::baseUrl()."/photo/avatar/".$user['uid'].".jpg"),
370 dbesc(System::baseUrl()."/photo/micro/".$user['uid'].".jpg"),
371 dbesc(System::baseUrl()."/profile/".$user['nickname']),
372 dbesc(normalise_link(System::baseUrl()."/profile/".$user['nickname'])),
373 dbesc($user['nickname'].'@'.substr(System::baseUrl(), strpos(System::baseUrl(),'://') + 3)),
374 dbesc(System::baseUrl()."/dfrn_request/".$user['nickname']),
375 dbesc(System::baseUrl()."/dfrn_notify/".$user['nickname']),
376 dbesc(System::baseUrl()."/dfrn_poll/".$user['nickname']),
377 dbesc(System::baseUrl()."/dfrn_confirm/".$user['nickname']),
378 dbesc(System::baseUrl()."/poco/".$user['nickname']),
379 dbesc(datetime_convert()),
380 dbesc(datetime_convert()),
381 dbesc(datetime_convert())
386 * @brief send registration confiĆmation with the intormation that reg is pending
388 * @param string $email
389 * @param string $sitename
390 * @param string $username
391 * @return NULL|boolean from notification() and email() inherited
393 function send_register_pending_eml($email, $sitename, $username) {
396 Thank you for registering at %2$s. Your account is pending for approval by the administrator.
399 $body = sprintf($body, $username, $sitename);
401 return notification(array(
402 'type' => SYSTEM_EMAIL,
403 'to_email' => $email,
404 'subject'=> sprintf( t('Registration at %s'), $sitename),
409 * send registration confirmation.
410 * It's here as a function because the mail is sent
411 * from different parts
413 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
414 $preamble = deindent(t('
416 Thank you for registering at %2$s. Your account has been created.
419 The login details are as follows:
424 You may change your password from your account "Settings" page after logging
427 Please take a few moments to review the other account settings on that page.
429 You may also wish to add some basic information to your default profile
430 (on the "Profiles" page) so that other people can easily find you.
432 We recommend setting your full name, adding a profile photo,
433 adding some profile "keywords" (very useful in making new friends) - and
434 perhaps what country you live in; if you do not wish to be more specific
437 We fully respect your right to privacy, and none of these items are necessary.
438 If you are new and do not know anybody here, they may help
439 you to make some new and interesting friends.
442 Thank you and welcome to %2$s.'));
444 $preamble = sprintf($preamble, $username, $sitename);
445 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
447 return notification(array(
448 'type' => SYSTEM_EMAIL,
449 'to_email' => $email,
450 'subject'=> sprintf( t('Registration details for %s'), $sitename),
451 'preamble'=> $preamble,