]> git.mxchange.org Git - friendica.git/blob - include/user.php
Merge remote-tracking branch 'refs/remotes/friendica/develop' into develop
[friendica.git] / include / user.php
1 <?php
2
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');
10
11
12 function create_user($arr) {
13
14         // Required: { username, nickname, email } or { openid_url }
15
16         $a = get_app();
17         $result = array('success' => false, 'user' => null, 'password' => '', 'message' => '');
18
19         $using_invites = get_config('system','invitation_only');
20         $num_invites   = get_config('system','number_invites');
21
22
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);
34
35         $publish    = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
36         $netpublish = ((strlen(get_config('system','directory'))) ? $publish : 0);
37
38         if ($password1 != $confirm) {
39                 $result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
40                 return $result;
41         } elseif ($password1 != "")
42                 $password = $password1;
43
44         $tmp_str = $openid_url;
45
46         if($using_invites) {
47                 if(! $invite_id) {
48                         $result['message'] .= t('An invitation is required.') . EOL;
49                         return $result;
50                 }
51                 $r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
52                 if(! results($r)) {
53                         $result['message'] .= t('Invitation could not be verified.') . EOL;
54                         return $result;
55                 }
56         }
57
58         if((! x($username)) || (! x($email)) || (! x($nickname))) {
59                 if($openid_url) {
60                         if(! validate_url($tmp_str)) {
61                                 $result['message'] .= t('Invalid OpenID url') . EOL;
62                                 return $result;
63                         }
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');
72                         try {
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;
76                                 return $result;
77                         }
78                         goaway($authurl);
79                         // NOTREACHED
80                 }
81
82                 notice( t('Please enter the required information.') . EOL );
83                 return;
84         }
85
86         if(! validate_url($tmp_str))
87                 $openid_url = '';
88
89
90         $err = '';
91
92         // collapse multiple spaces in name
93         $username = preg_replace('/ +/',' ',$username);
94
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;
99
100         // So now we are just looking for a space in the full name.
101
102         $loose_reg = get_config('system','no_regfullname');
103         if(! $loose_reg) {
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;
107         }
108
109
110         if(! allowed_email($email))
111                 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
112
113         if((! valid_email($email)) || (! validate_email($email)))
114                 $result['message'] .= t('Not a valid email address.') . EOL;
115
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.
118
119         $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
120
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",
124                         dbesc($email)
125                 );
126                 if (dbm::is_result($r))
127                         $result['message'] .= t('Cannot use that email.') . EOL;
128         }
129
130         $nickname = $arr['nickname'] = strtolower($nickname);
131
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;
134
135         $r = q("SELECT `uid` FROM `user`
136                 WHERE `nickname` = '%s' LIMIT 1",
137                 dbesc($nickname)
138         );
139         if (dbm::is_result($r))
140                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
141
142         // Check deleted accounts that had this nickname. Doesn't matter to us,
143         // but could be a security issue for federated platforms.
144
145         $r = q("SELECT * FROM `userd`
146                 WHERE `username` = '%s' LIMIT 1",
147                 dbesc($nickname)
148         );
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;
151
152         if(strlen($result['message'])) {
153                 return $result;
154         }
155
156         $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
157         $new_password_encoded = hash('whirlpool',$new_password);
158
159         $result['password'] = $new_password;
160
161         require_once('include/crypto.php');
162
163         $keys = new_keypair(4096);
164
165         if($keys === false) {
166                 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
167                 return $result;
168         }
169
170         $default_service_class = get_config('system','default_service_class');
171         if(! $default_service_class)
172                 $default_service_class = '';
173
174
175         $prvkey = $keys['prvkey'];
176         $pubkey = $keys['pubkey'];
177
178         /**
179          *
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.
186          *
187          */
188
189         $sres    = new_keypair(512);
190         $sprvkey = $sres['prvkey'];
191         $spubkey = $sres['pubkey'];
192
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()),
197                 dbesc($username),
198                 dbesc($new_password_encoded),
199                 dbesc($email),
200                 dbesc($openid_url),
201                 dbesc($nickname),
202                 dbesc($pubkey),
203                 dbesc($prvkey),
204                 dbesc($spubkey),
205                 dbesc($sprvkey),
206                 dbesc(datetime_convert()),
207                 intval($verified),
208                 intval($blocked),
209                 dbesc($default_service_class)
210         );
211
212         if ($r) {
213                 $r = q("SELECT * FROM `user`
214                         WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
215                         dbesc($username),
216                         dbesc($new_password_encoded)
217                 );
218                 if (dbm::is_result($r)) {
219                         $u = $r[0];
220                         $newuid = intval($r[0]['uid']);
221                 }
222         }
223         else {
224                 $result['message'] .=  t('An error occurred during registration. Please try again.') . EOL ;
225                 return $result;
226         }
227
228         /**
229          * if somebody clicked submit twice very quickly, they could end up with two accounts
230          * due to race condition. Remove this one.
231          */
232
233         $r = q("SELECT `uid` FROM `user`
234                 WHERE `nickname` = '%s' ",
235                 dbesc($nickname)
236         );
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",
240                         intval($newuid)
241                 );
242                 return $result;
243         }
244
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 ) ",
248                         intval($newuid),
249                         t('default'),
250                         1,
251                         dbesc($username),
252                         dbesc(z_root() . "/photo/profile/{$newuid}.jpg"),
253                         dbesc(z_root() . "/photo/avatar/{$newuid}.jpg"),
254                         intval($publish),
255                         intval($netpublish)
256
257                 );
258                 if ($r === false) {
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",
262                                 intval($newuid));
263                         return $result;
264                 }
265
266                 // Create the self contact
267                 user_create_self_contact($newuid);
268
269                 // Create a group with no members. This allows somebody to use it
270                 // right away as a default group for new contacts.
271
272                 require_once('include/group.php');
273                 group_add($newuid, t('Friends'));
274
275                 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
276                         intval($newuid),
277                         dbesc(t('Friends'))
278                 );
279                 if (dbm::is_result($r)) {
280                         $def_gid = $r[0]['id'];
281
282                         q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
283                                 intval($r[0]['id']),
284                                 intval($newuid)
285                         );
286                 }
287
288                 if(get_config('system', 'newuser_private') && $def_gid) {
289                         q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
290                                 dbesc("<" . $def_gid . ">"),
291                                 intval($newuid)
292                         );
293                 }
294
295         }
296
297         // if we have no OpenID photo try to look up an avatar
298         if(! strlen($photo))
299                 $photo = avatar_img($email);
300
301         // unless there is no avatar-plugin loaded
302         if(strlen($photo)) {
303                 require_once('include/Photo.php');
304                 $photo_failure = false;
305
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);
310
311
312                 $img = new Photo($img_str, $type);
313                 if($img->is_valid()) {
314
315                         $img->scaleImageSquare(175);
316
317                         $hash = photo_new_resource();
318
319                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
320
321                         if ($r === false) {
322                                 $photo_failure = true;
323                         }
324
325                         $img->scaleImage(80);
326
327                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
328
329                         if ($r === false) {
330                                 $photo_failure = true;
331                         }
332
333                         $img->scaleImage(48);
334
335                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
336
337                         if ($r === false) {
338                                 $photo_failure = true;
339                         }
340
341                         if (! $photo_failure) {
342                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
343                                         dbesc($hash)
344                                 );
345                         }
346                 }
347         }
348
349         call_hooks('register_account', $newuid);
350
351         $result['success'] = true;
352         $result['user'] = $u;
353         return $result;
354
355 }
356
357 /**
358  * @brief create the "self" contact from data from the user table
359  *
360  * @param integer $uid
361  */
362 function user_create_self_contact($uid) {
363
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)) {
367                 return;
368         }
369
370         $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
371         if (!dbm::is_result($r)) {
372                 return;
373         }
374
375         $user = $r[0];
376
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']),
381                 datetime_convert(),
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())
398         );
399 }
400
401 /**
402  * @brief send registration confiƕmation with the intormation that reg is pending
403  *
404  * @param string $email
405  * @param string $sitename
406  * @param string $username
407  * @return NULL|boolean from notification() and email() inherited 
408  */
409 function send_register_pending_eml($email, $sitename, $username) {
410         $body = deindent(t('
411                 Dear %1$s,
412                         Thank you for registering at %2$s. Your account is pending for approval by the administrator.
413         '));
414
415         $body = sprintf($body, $username, $sitename);
416
417         return notification(array(
418                 'type' => "SYSTEM_EMAIL",
419                 'to_email' => $email,
420                 'subject'=> sprintf( t('Registration at %s'), $sitename),
421                 'body' => $body));
422 }
423
424 /*
425  * send registration confirmation.
426  * It's here as a function because the mail is sent
427  * from different parts
428  */
429 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
430         $preamble = deindent(t('
431                 Dear %1$s,
432                         Thank you for registering at %2$s. Your account has been created.
433         '));
434         $body = deindent(t('
435                 The login details are as follows:
436                         Site Location:  %3$s
437                         Login Name:     %1$s
438                         Password:       %5$s
439
440                 You may change your password from your account "Settings" page after logging
441                 in.
442
443                 Please take a few moments to review the other account settings on that page.
444
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.
447
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
451                 than that.
452
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.
456
457
458                 Thank you and welcome to %2$s.'));
459
460                 $preamble = sprintf($preamble, $username, $sitename);
461                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
462
463                 return notification(array(
464                         'type' => "SYSTEM_EMAIL",
465                         'to_email' => $email,
466                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
467                         'preamble'=> $preamble,
468                         'body' => $body));
469 }