3 use Friendica\Core\System;
5 require_once('include/config.php');
6 require_once('include/network.php');
7 require_once('include/plugin.php');
8 require_once('include/text.php');
9 require_once('include/pgettext.php');
10 require_once('include/datetime.php');
11 require_once('include/enotify.php');
14 function create_user($arr) {
16 // Required: { username, nickname, email } or { openid_url }
19 $result = array('success' => false, 'user' => null, 'password' => '', 'message' => '');
21 $using_invites = get_config('system','invitation_only');
22 $num_invites = get_config('system','number_invites');
25 $invite_id = ((x($arr,'invite_id')) ? notags(trim($arr['invite_id'])) : '');
26 $username = ((x($arr,'username')) ? notags(trim($arr['username'])) : '');
27 $nickname = ((x($arr,'nickname')) ? notags(trim($arr['nickname'])) : '');
28 $email = ((x($arr,'email')) ? notags(trim($arr['email'])) : '');
29 $openid_url = ((x($arr,'openid_url')) ? notags(trim($arr['openid_url'])) : '');
30 $photo = ((x($arr,'photo')) ? notags(trim($arr['photo'])) : '');
31 $password = ((x($arr,'password')) ? trim($arr['password']) : '');
32 $password1 = ((x($arr,'password1')) ? trim($arr['password1']) : '');
33 $confirm = ((x($arr,'confirm')) ? trim($arr['confirm']) : '');
34 $blocked = ((x($arr,'blocked')) ? intval($arr['blocked']) : 0);
35 $verified = ((x($arr,'verified')) ? intval($arr['verified']) : 0);
37 $publish = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
38 $netpublish = ((strlen(get_config('system','directory'))) ? $publish : 0);
40 if ($password1 != $confirm) {
41 $result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
43 } elseif ($password1 != "")
44 $password = $password1;
46 $tmp_str = $openid_url;
50 $result['message'] .= t('An invitation is required.') . EOL;
53 $r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
55 $result['message'] .= t('Invitation could not be verified.') . EOL;
60 if((! x($username)) || (! x($email)) || (! x($nickname))) {
62 if(! validate_url($tmp_str)) {
63 $result['message'] .= t('Invalid OpenID url') . EOL;
66 $_SESSION['register'] = 1;
67 $_SESSION['openid'] = $openid_url;
68 require_once('library/openid.php');
69 $openid = new LightOpenID;
70 $openid->identity = $openid_url;
71 $openid->returnUrl = System::baseUrl() . '/openid';
72 $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson');
73 $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
75 $authurl = $openid->authUrl();
76 } catch (Exception $e){
77 $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;
84 notice( t('Please enter the required information.') . EOL );
88 if(! validate_url($tmp_str))
94 // collapse multiple spaces in name
95 $username = preg_replace('/ +/',' ',$username);
97 if(mb_strlen($username) > 48)
98 $result['message'] .= t('Please use a shorter name.') . EOL;
99 if(mb_strlen($username) < 3)
100 $result['message'] .= t('Name too short.') . EOL;
102 // So now we are just looking for a space in the full name.
104 $loose_reg = get_config('system','no_regfullname');
106 $username = mb_convert_case($username,MB_CASE_TITLE,'UTF-8');
107 if(! strpos($username,' '))
108 $result['message'] .= t("That doesn't appear to be your full \x28First Last\x29 name.") . EOL;
112 if(! allowed_email($email))
113 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
115 if((! valid_email($email)) || (! validate_email($email)))
116 $result['message'] .= t('Not a valid email address.') . EOL;
118 // Disallow somebody creating an account using openid that uses the admin email address,
119 // since openid bypasses email verification. We'll allow it if there is not yet an admin account.
121 $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
123 //if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) {
124 if((x($a->config,'admin_email')) && in_array(strtolower($email), $adminlist) && strlen($openid_url)) {
125 $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
128 if (dbm::is_result($r))
129 $result['message'] .= t('Cannot use that email.') . EOL;
132 $nickname = $arr['nickname'] = strtolower($nickname);
134 if(! preg_match("/^[a-z0-9][a-z0-9\_]*$/",$nickname))
135 $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9" and "_".') . EOL;
137 $r = q("SELECT `uid` FROM `user`
138 WHERE `nickname` = '%s' LIMIT 1",
141 if (dbm::is_result($r))
142 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
144 // Check deleted accounts that had this nickname. Doesn't matter to us,
145 // but could be a security issue for federated platforms.
147 $r = q("SELECT * FROM `userd`
148 WHERE `username` = '%s' LIMIT 1",
151 if (dbm::is_result($r))
152 $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
154 if(strlen($result['message'])) {
158 $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
159 $new_password_encoded = hash('whirlpool',$new_password);
161 $result['password'] = $new_password;
163 require_once('include/crypto.php');
165 $keys = new_keypair(4096);
167 if($keys === false) {
168 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
172 $default_service_class = get_config('system','default_service_class');
173 if(! $default_service_class)
174 $default_service_class = '';
177 $prvkey = $keys['prvkey'];
178 $pubkey = $keys['pubkey'];
180 // Create another keypair for signing/verifying salmon protocol messages.
181 $sres = new_keypair(512);
182 $sprvkey = $sres['prvkey'];
183 $spubkey = $sres['pubkey'];
185 $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,
186 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `service_class`, `default-location` )
187 VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '%s', '' )",
188 dbesc(generate_user_guid()),
190 dbesc($new_password_encoded),
198 dbesc(datetime_convert()),
201 dbesc($default_service_class)
205 $r = q("SELECT * FROM `user`
206 WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
208 dbesc($new_password_encoded)
210 if (dbm::is_result($r)) {
212 $newuid = intval($r[0]['uid']);
216 $result['message'] .= t('An error occurred during registration. Please try again.') . EOL ;
221 * if somebody clicked submit twice very quickly, they could end up with two accounts
222 * due to race condition. Remove this one.
225 $r = q("SELECT `uid` FROM `user`
226 WHERE `nickname` = '%s' ",
229 if ((dbm::is_result($r)) && (count($r) > 1) && $newuid) {
230 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
231 dba::delete('user', array('uid' => $newuid));
235 if(x($newuid) !== false) {
236 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
237 VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
242 dbesc(System::baseUrl() . "/photo/profile/{$newuid}.jpg"),
243 dbesc(System::baseUrl() . "/photo/avatar/{$newuid}.jpg"),
249 $result['message'] .= t('An error occurred creating your default profile. Please try again.') . EOL;
250 // Start fresh next time.
251 dba::delete('user', array('uid' => $newuid));
255 // Create the self contact
256 user_create_self_contact($newuid);
258 // Create a group with no members. This allows somebody to use it
259 // right away as a default group for new contacts.
261 require_once('include/group.php');
262 group_add($newuid, t('Friends'));
264 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
268 if (dbm::is_result($r)) {
269 $def_gid = $r[0]['id'];
271 q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
277 if(get_config('system', 'newuser_private') && $def_gid) {
278 q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
279 dbesc("<" . $def_gid . ">"),
286 // if we have no OpenID photo try to look up an avatar
288 $photo = avatar_img($email);
290 // unless there is no avatar-plugin loaded
292 require_once('include/Photo.php');
293 $photo_failure = false;
295 $filename = basename($photo);
296 $img_str = fetch_url($photo,true);
297 // guess mimetype from headers or filename
298 $type = guess_image_type($photo,true);
301 $img = new Photo($img_str, $type);
302 if($img->is_valid()) {
304 $img->scaleImageSquare(175);
306 $hash = photo_new_resource();
308 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
311 $photo_failure = true;
314 $img->scaleImage(80);
316 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
319 $photo_failure = true;
322 $img->scaleImage(48);
324 $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
327 $photo_failure = true;
330 if (! $photo_failure) {
331 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
338 call_hooks('register_account', $newuid);
340 $result['success'] = true;
341 $result['user'] = $u;
347 * @brief create the "self" contact from data from the user table
349 * @param integer $uid
351 function user_create_self_contact($uid) {
353 // Only create the entry if it doesn't exist yet
354 $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
355 if (dbm::is_result($r)) {
359 $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
360 if (!dbm::is_result($r)) {
366 q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
367 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
368 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
369 intval($user['uid']),
371 dbesc($user['username']),
372 dbesc($user['nickname']),
373 dbesc(System::baseUrl()."/photo/profile/".$user['uid'].".jpg"),
374 dbesc(System::baseUrl()."/photo/avatar/".$user['uid'].".jpg"),
375 dbesc(System::baseUrl()."/photo/micro/".$user['uid'].".jpg"),
376 dbesc(System::baseUrl()."/profile/".$user['nickname']),
377 dbesc(normalise_link(System::baseUrl()."/profile/".$user['nickname'])),
378 dbesc($user['nickname'].'@'.substr(System::baseUrl(), strpos(System::baseUrl(),'://') + 3)),
379 dbesc(System::baseUrl()."/dfrn_request/".$user['nickname']),
380 dbesc(System::baseUrl()."/dfrn_notify/".$user['nickname']),
381 dbesc(System::baseUrl()."/dfrn_poll/".$user['nickname']),
382 dbesc(System::baseUrl()."/dfrn_confirm/".$user['nickname']),
383 dbesc(System::baseUrl()."/poco/".$user['nickname']),
384 dbesc(datetime_convert()),
385 dbesc(datetime_convert()),
386 dbesc(datetime_convert())
391 * @brief send registration confiĆmation with the intormation that reg is pending
393 * @param string $email
394 * @param string $sitename
395 * @param string $username
396 * @return NULL|boolean from notification() and email() inherited
398 function send_register_pending_eml($email, $sitename, $username) {
401 Thank you for registering at %2$s. Your account is pending for approval by the administrator.
404 $body = sprintf($body, $username, $sitename);
406 return notification(array(
407 'type' => "SYSTEM_EMAIL",
408 'to_email' => $email,
409 'subject'=> sprintf( t('Registration at %s'), $sitename),
414 * send registration confirmation.
415 * It's here as a function because the mail is sent
416 * from different parts
418 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
419 $preamble = deindent(t('
421 Thank you for registering at %2$s. Your account has been created.
424 The login details are as follows:
429 You may change your password from your account "Settings" page after logging
432 Please take a few moments to review the other account settings on that page.
434 You may also wish to add some basic information to your default profile
435 (on the "Profiles" page) so that other people can easily find you.
437 We recommend setting your full name, adding a profile photo,
438 adding some profile "keywords" (very useful in making new friends) - and
439 perhaps what country you live in; if you do not wish to be more specific
442 We fully respect your right to privacy, and none of these items are necessary.
443 If you are new and do not know anybody here, they may help
444 you to make some new and interesting friends.
447 Thank you and welcome to %2$s.'));
449 $preamble = sprintf($preamble, $username, $sitename);
450 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
452 return notification(array(
453 'type' => "SYSTEM_EMAIL",
454 'to_email' => $email,
455 'subject'=> sprintf( t('Registration details for %s'), $sitename),
456 'preamble'=> $preamble,