]> git.mxchange.org Git - friendica.git/blob - include/user.php
a05bd831a8e7d81aa19344d3853846acc363ee36
[friendica.git] / include / user.php
1 <?php
2
3 use Friendica\Core\System;
4
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');
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 = get_config('system','invitation_only');
22         $num_invites   = get_config('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(get_config('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 = get_config('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         $default_service_class = get_config('system','default_service_class');
173         if(! $default_service_class)
174                 $default_service_class = '';
175
176
177         $prvkey = $keys['prvkey'];
178         $pubkey = $keys['pubkey'];
179
180         // Create another keypair for signing/verifying salmon protocol messages.
181         $sres    = new_keypair(512);
182         $sprvkey = $sres['prvkey'];
183         $spubkey = $sres['pubkey'];
184
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()),
189                 dbesc($username),
190                 dbesc($new_password_encoded),
191                 dbesc($email),
192                 dbesc($openid_url),
193                 dbesc($nickname),
194                 dbesc($pubkey),
195                 dbesc($prvkey),
196                 dbesc($spubkey),
197                 dbesc($sprvkey),
198                 dbesc(datetime_convert()),
199                 intval($verified),
200                 intval($blocked),
201                 dbesc($default_service_class)
202         );
203
204         if ($r) {
205                 $r = q("SELECT * FROM `user`
206                         WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
207                         dbesc($username),
208                         dbesc($new_password_encoded)
209                 );
210                 if (dbm::is_result($r)) {
211                         $u = $r[0];
212                         $newuid = intval($r[0]['uid']);
213                 }
214         }
215         else {
216                 $result['message'] .=  t('An error occurred during registration. Please try again.') . EOL ;
217                 return $result;
218         }
219
220         /**
221          * if somebody clicked submit twice very quickly, they could end up with two accounts
222          * due to race condition. Remove this one.
223          */
224
225         $r = q("SELECT `uid` FROM `user`
226                 WHERE `nickname` = '%s' ",
227                 dbesc($nickname)
228         );
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));
232                 return $result;
233         }
234
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 ) ",
238                         intval($newuid),
239                         t('default'),
240                         1,
241                         dbesc($username),
242                         dbesc(System::baseUrl() . "/photo/profile/{$newuid}.jpg"),
243                         dbesc(System::baseUrl() . "/photo/avatar/{$newuid}.jpg"),
244                         intval($publish),
245                         intval($netpublish)
246
247                 );
248                 if ($r === false) {
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));
252                         return $result;
253                 }
254
255                 // Create the self contact
256                 user_create_self_contact($newuid);
257
258                 // Create a group with no members. This allows somebody to use it
259                 // right away as a default group for new contacts.
260
261                 require_once('include/group.php');
262                 group_add($newuid, t('Friends'));
263
264                 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
265                         intval($newuid),
266                         dbesc(t('Friends'))
267                 );
268                 if (dbm::is_result($r)) {
269                         $def_gid = $r[0]['id'];
270
271                         q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
272                                 intval($r[0]['id']),
273                                 intval($newuid)
274                         );
275                 }
276
277                 if(get_config('system', 'newuser_private') && $def_gid) {
278                         q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
279                                 dbesc("<" . $def_gid . ">"),
280                                 intval($newuid)
281                         );
282                 }
283
284         }
285
286         // if we have no OpenID photo try to look up an avatar
287         if(! strlen($photo))
288                 $photo = avatar_img($email);
289
290         // unless there is no avatar-plugin loaded
291         if(strlen($photo)) {
292                 require_once('include/Photo.php');
293                 $photo_failure = false;
294
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);
299
300
301                 $img = new Photo($img_str, $type);
302                 if($img->is_valid()) {
303
304                         $img->scaleImageSquare(175);
305
306                         $hash = photo_new_resource();
307
308                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
309
310                         if ($r === false) {
311                                 $photo_failure = true;
312                         }
313
314                         $img->scaleImage(80);
315
316                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
317
318                         if ($r === false) {
319                                 $photo_failure = true;
320                         }
321
322                         $img->scaleImage(48);
323
324                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
325
326                         if ($r === false) {
327                                 $photo_failure = true;
328                         }
329
330                         if (! $photo_failure) {
331                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
332                                         dbesc($hash)
333                                 );
334                         }
335                 }
336         }
337
338         call_hooks('register_account', $newuid);
339
340         $result['success'] = true;
341         $result['user'] = $u;
342         return $result;
343
344 }
345
346 /**
347  * @brief create the "self" contact from data from the user table
348  *
349  * @param integer $uid
350  */
351 function user_create_self_contact($uid) {
352
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)) {
356                 return;
357         }
358
359         $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
360         if (!dbm::is_result($r)) {
361                 return;
362         }
363
364         $user = $r[0];
365
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']),
370                 datetime_convert(),
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())
387         );
388 }
389
390 /**
391  * @brief send registration confiƕmation with the intormation that reg is pending
392  *
393  * @param string $email
394  * @param string $sitename
395  * @param string $username
396  * @return NULL|boolean from notification() and email() inherited 
397  */
398 function send_register_pending_eml($email, $sitename, $username) {
399         $body = deindent(t('
400                 Dear %1$s,
401                         Thank you for registering at %2$s. Your account is pending for approval by the administrator.
402         '));
403
404         $body = sprintf($body, $username, $sitename);
405
406         return notification(array(
407                 'type' => SYSTEM_EMAIL,
408                 'to_email' => $email,
409                 'subject'=> sprintf( t('Registration at %s'), $sitename),
410                 'body' => $body));
411 }
412
413 /*
414  * send registration confirmation.
415  * It's here as a function because the mail is sent
416  * from different parts
417  */
418 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
419         $preamble = deindent(t('
420                 Dear %1$s,
421                         Thank you for registering at %2$s. Your account has been created.
422         '));
423         $body = deindent(t('
424                 The login details are as follows:
425                         Site Location:  %3$s
426                         Login Name:     %1$s
427                         Password:       %5$s
428
429                 You may change your password from your account "Settings" page after logging
430                 in.
431
432                 Please take a few moments to review the other account settings on that page.
433
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.
436
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
440                 than that.
441
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.
445
446
447                 Thank you and welcome to %2$s.'));
448
449                 $preamble = sprintf($preamble, $username, $sitename);
450                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
451
452                 return notification(array(
453                         'type' => SYSTEM_EMAIL,
454                         'to_email' => $email,
455                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
456                         'preamble'=> $preamble,
457                         'body' => $body));
458 }