]> git.mxchange.org Git - friendica.git/blob - include/user.php
7eb1058dc05655a9a174b460748ab4ae44ddd9e7
[friendica.git] / include / user.php
1 <?php
2
3 use Friendica\Core\Config;
4 use Friendica\Core\System;
5
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');
12
13
14 function create_user($arr) {
15
16         // Required: { username, nickname, email } or { openid_url }
17
18         $a = get_app();
19         $result = array('success' => false, 'user' => null, 'password' => '', 'message' => '');
20
21         $using_invites = Config::get('system','invitation_only');
22         $num_invites   = Config::get('system','number_invites');
23
24
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);
36
37         $publish    = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
38         $netpublish = ((strlen(Config::get('system','directory'))) ? $publish : 0);
39
40         if ($password1 != $confirm) {
41                 $result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
42                 return $result;
43         } elseif ($password1 != "")
44                 $password = $password1;
45
46         $tmp_str = $openid_url;
47
48         if($using_invites) {
49                 if(! $invite_id) {
50                         $result['message'] .= t('An invitation is required.') . EOL;
51                         return $result;
52                 }
53                 $r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
54                 if(! results($r)) {
55                         $result['message'] .= t('Invitation could not be verified.') . EOL;
56                         return $result;
57                 }
58         }
59
60         if((! x($username)) || (! x($email)) || (! x($nickname))) {
61                 if($openid_url) {
62                         if(! validate_url($tmp_str)) {
63                                 $result['message'] .= t('Invalid OpenID url') . EOL;
64                                 return $result;
65                         }
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');
74                         try {
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;
78                                 return $result;
79                         }
80                         goaway($authurl);
81                         // NOTREACHED
82                 }
83
84                 notice( t('Please enter the required information.') . EOL );
85                 return;
86         }
87
88         if(! validate_url($tmp_str))
89                 $openid_url = '';
90
91
92         $err = '';
93
94         // collapse multiple spaces in name
95         $username = preg_replace('/ +/',' ',$username);
96
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;
101
102         // So now we are just looking for a space in the full name.
103
104         $loose_reg = Config::get('system','no_regfullname');
105         if(! $loose_reg) {
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;
109         }
110
111
112         if(! allowed_email($email))
113                 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
114
115         if((! valid_email($email)) || (! validate_email($email)))
116                 $result['message'] .= t('Not a valid email address.') . EOL;
117
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.
120
121         $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
122
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",
126                         dbesc($email)
127                 );
128                 if (dbm::is_result($r))
129                         $result['message'] .= t('Cannot use that email.') . EOL;
130         }
131
132         $nickname = $arr['nickname'] = strtolower($nickname);
133
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;
136
137         $r = q("SELECT `uid` FROM `user`
138                 WHERE `nickname` = '%s' LIMIT 1",
139                 dbesc($nickname)
140         );
141         if (dbm::is_result($r))
142                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
143
144         // Check deleted accounts that had this nickname. Doesn't matter to us,
145         // but could be a security issue for federated platforms.
146
147         $r = q("SELECT * FROM `userd`
148                 WHERE `username` = '%s' LIMIT 1",
149                 dbesc($nickname)
150         );
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;
153
154         if(strlen($result['message'])) {
155                 return $result;
156         }
157
158         $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
159         $new_password_encoded = hash('whirlpool',$new_password);
160
161         $result['password'] = $new_password;
162
163         require_once('include/crypto.php');
164
165         $keys = new_keypair(4096);
166
167         if($keys === false) {
168                 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
169                 return $result;
170         }
171
172         $prvkey = $keys['prvkey'];
173         $pubkey = $keys['pubkey'];
174
175         // Create another keypair for signing/verifying salmon protocol messages.
176         $sres    = new_keypair(512);
177         $sprvkey = $sres['prvkey'];
178         $spubkey = $sres['pubkey'];
179
180         $r = q("INSERT INTO `user` (`guid`, `username`, `password`, `email`, `openid`, `nickname`,
181                 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `default-location`)
182                 VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '')",
183                 dbesc(generate_user_guid()),
184                 dbesc($username),
185                 dbesc($new_password_encoded),
186                 dbesc($email),
187                 dbesc($openid_url),
188                 dbesc($nickname),
189                 dbesc($pubkey),
190                 dbesc($prvkey),
191                 dbesc($spubkey),
192                 dbesc($sprvkey),
193                 dbesc(datetime_convert()),
194                 intval($verified),
195                 intval($blocked)
196         );
197
198         if ($r) {
199                 $r = q("SELECT * FROM `user`
200                         WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
201                         dbesc($username),
202                         dbesc($new_password_encoded)
203                 );
204                 if (dbm::is_result($r)) {
205                         $u = $r[0];
206                         $newuid = intval($r[0]['uid']);
207                 }
208         }
209         else {
210                 $result['message'] .=  t('An error occurred during registration. Please try again.') . EOL ;
211                 return $result;
212         }
213
214         /**
215          * if somebody clicked submit twice very quickly, they could end up with two accounts
216          * due to race condition. Remove this one.
217          */
218
219         $r = q("SELECT `uid` FROM `user`
220                 WHERE `nickname` = '%s' ",
221                 dbesc($nickname)
222         );
223         if ((dbm::is_result($r)) && (count($r) > 1) && $newuid) {
224                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
225                 dba::delete('user', array('uid' => $newuid));
226                 return $result;
227         }
228
229         if(x($newuid) !== false) {
230                 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
231                         VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
232                         intval($newuid),
233                         t('default'),
234                         1,
235                         dbesc($username),
236                         dbesc(System::baseUrl() . "/photo/profile/{$newuid}.jpg"),
237                         dbesc(System::baseUrl() . "/photo/avatar/{$newuid}.jpg"),
238                         intval($publish),
239                         intval($netpublish)
240
241                 );
242                 if ($r === false) {
243                         $result['message'] .=  t('An error occurred creating your default profile. Please try again.') . EOL;
244                         // Start fresh next time.
245                         dba::delete('user', array('uid' => $newuid));
246                         return $result;
247                 }
248
249                 // Create the self contact
250                 user_create_self_contact($newuid);
251
252                 // Create a group with no members. This allows somebody to use it
253                 // right away as a default group for new contacts.
254
255                 require_once('include/group.php');
256                 group_add($newuid, t('Friends'));
257
258                 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
259                         intval($newuid),
260                         dbesc(t('Friends'))
261                 );
262                 if (dbm::is_result($r)) {
263                         $def_gid = $r[0]['id'];
264
265                         q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
266                                 intval($r[0]['id']),
267                                 intval($newuid)
268                         );
269                 }
270
271                 if(Config::get('system', 'newuser_private') && $def_gid) {
272                         q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
273                                 dbesc("<" . $def_gid . ">"),
274                                 intval($newuid)
275                         );
276                 }
277
278         }
279
280         // if we have no OpenID photo try to look up an avatar
281         if(! strlen($photo))
282                 $photo = avatar_img($email);
283
284         // unless there is no avatar-plugin loaded
285         if(strlen($photo)) {
286                 require_once('include/Photo.php');
287                 $photo_failure = false;
288
289                 $filename = basename($photo);
290                 $img_str = fetch_url($photo,true);
291                 // guess mimetype from headers or filename
292                 $type = guess_image_type($photo,true);
293
294
295                 $img = new Photo($img_str, $type);
296                 if($img->is_valid()) {
297
298                         $img->scaleImageSquare(175);
299
300                         $hash = photo_new_resource();
301
302                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
303
304                         if ($r === false) {
305                                 $photo_failure = true;
306                         }
307
308                         $img->scaleImage(80);
309
310                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
311
312                         if ($r === false) {
313                                 $photo_failure = true;
314                         }
315
316                         $img->scaleImage(48);
317
318                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
319
320                         if ($r === false) {
321                                 $photo_failure = true;
322                         }
323
324                         if (! $photo_failure) {
325                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
326                                         dbesc($hash)
327                                 );
328                         }
329                 }
330         }
331
332         call_hooks('register_account', $newuid);
333
334         $result['success'] = true;
335         $result['user'] = $u;
336         return $result;
337
338 }
339
340 /**
341  * @brief create the "self" contact from data from the user table
342  *
343  * @param integer $uid
344  */
345 function user_create_self_contact($uid) {
346
347         // Only create the entry if it doesn't exist yet
348         $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
349         if (dbm::is_result($r)) {
350                 return;
351         }
352
353         $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
354         if (!dbm::is_result($r)) {
355                 return;
356         }
357
358         $user = $r[0];
359
360         q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
361                 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
362                 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
363                 intval($user['uid']),
364                 datetime_convert(),
365                 dbesc($user['username']),
366                 dbesc($user['nickname']),
367                 dbesc(System::baseUrl()."/photo/profile/".$user['uid'].".jpg"),
368                 dbesc(System::baseUrl()."/photo/avatar/".$user['uid'].".jpg"),
369                 dbesc(System::baseUrl()."/photo/micro/".$user['uid'].".jpg"),
370                 dbesc(System::baseUrl()."/profile/".$user['nickname']),
371                 dbesc(normalise_link(System::baseUrl()."/profile/".$user['nickname'])),
372                 dbesc($user['nickname'].'@'.substr(System::baseUrl(), strpos(System::baseUrl(),'://') + 3)),
373                 dbesc(System::baseUrl()."/dfrn_request/".$user['nickname']),
374                 dbesc(System::baseUrl()."/dfrn_notify/".$user['nickname']),
375                 dbesc(System::baseUrl()."/dfrn_poll/".$user['nickname']),
376                 dbesc(System::baseUrl()."/dfrn_confirm/".$user['nickname']),
377                 dbesc(System::baseUrl()."/poco/".$user['nickname']),
378                 dbesc(datetime_convert()),
379                 dbesc(datetime_convert()),
380                 dbesc(datetime_convert())
381         );
382 }
383
384 /**
385  * @brief send registration confiƕmation with the intormation that reg is pending
386  *
387  * @param string $email
388  * @param string $sitename
389  * @param string $username
390  * @return NULL|boolean from notification() and email() inherited 
391  */
392 function send_register_pending_eml($email, $sitename, $username) {
393         $body = deindent(t('
394                 Dear %1$s,
395                         Thank you for registering at %2$s. Your account is pending for approval by the administrator.
396         '));
397
398         $body = sprintf($body, $username, $sitename);
399
400         return notification(array(
401                 'type' => SYSTEM_EMAIL,
402                 'to_email' => $email,
403                 'subject'=> sprintf( t('Registration at %s'), $sitename),
404                 'body' => $body));
405 }
406
407 /*
408  * send registration confirmation.
409  * It's here as a function because the mail is sent
410  * from different parts
411  */
412 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
413         $preamble = deindent(t('
414                 Dear %1$s,
415                         Thank you for registering at %2$s. Your account has been created.
416         '));
417         $body = deindent(t('
418                 The login details are as follows:
419                         Site Location:  %3$s
420                         Login Name:     %1$s
421                         Password:       %5$s
422
423                 You may change your password from your account "Settings" page after logging
424                 in.
425
426                 Please take a few moments to review the other account settings on that page.
427
428                 You may also wish to add some basic information to your default profile
429                 (on the "Profiles" page) so that other people can easily find you.
430
431                 We recommend setting your full name, adding a profile photo,
432                 adding some profile "keywords" (very useful in making new friends) - and
433                 perhaps what country you live in; if you do not wish to be more specific
434                 than that.
435
436                 We fully respect your right to privacy, and none of these items are necessary.
437                 If you are new and do not know anybody here, they may help
438                 you to make some new and interesting friends.
439
440
441                 Thank you and welcome to %2$s.'));
442
443                 $preamble = sprintf($preamble, $username, $sitename);
444                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
445
446                 return notification(array(
447                         'type' => SYSTEM_EMAIL,
448                         'to_email' => $email,
449                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
450                         'preamble'=> $preamble,
451                         'body' => $body));
452 }