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