]> git.mxchange.org Git - friendica.git/blob - include/user.php
Merge pull request #3284 from annando/issue-3278
[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         // Create another keypair for signing/verifying salmon protocol messages.
179         $sres    = new_keypair(512);
180         $sprvkey = $sres['prvkey'];
181         $spubkey = $sres['pubkey'];
182
183         $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,
184                 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `service_class`, `default-location` )
185                 VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '%s', '' )",
186                 dbesc(generate_user_guid()),
187                 dbesc($username),
188                 dbesc($new_password_encoded),
189                 dbesc($email),
190                 dbesc($openid_url),
191                 dbesc($nickname),
192                 dbesc($pubkey),
193                 dbesc($prvkey),
194                 dbesc($spubkey),
195                 dbesc($sprvkey),
196                 dbesc(datetime_convert()),
197                 intval($verified),
198                 intval($blocked),
199                 dbesc($default_service_class)
200         );
201
202         if ($r) {
203                 $r = q("SELECT * FROM `user`
204                         WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
205                         dbesc($username),
206                         dbesc($new_password_encoded)
207                 );
208                 if (dbm::is_result($r)) {
209                         $u = $r[0];
210                         $newuid = intval($r[0]['uid']);
211                 }
212         }
213         else {
214                 $result['message'] .=  t('An error occurred during registration. Please try again.') . EOL ;
215                 return $result;
216         }
217
218         /**
219          * if somebody clicked submit twice very quickly, they could end up with two accounts
220          * due to race condition. Remove this one.
221          */
222
223         $r = q("SELECT `uid` FROM `user`
224                 WHERE `nickname` = '%s' ",
225                 dbesc($nickname)
226         );
227         if ((dbm::is_result($r)) && (count($r) > 1) && $newuid) {
228                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
229                 q("DELETE FROM `user` WHERE `uid` = %d",
230                         intval($newuid)
231                 );
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(z_root() . "/photo/profile/{$newuid}.jpg"),
243                         dbesc(z_root() . "/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                         $r = q("DELETE FROM `user` WHERE `uid` = %d",
252                                 intval($newuid));
253                         return $result;
254                 }
255
256                 // Create the self contact
257                 user_create_self_contact($newuid);
258
259                 // Create a group with no members. This allows somebody to use it
260                 // right away as a default group for new contacts.
261
262                 require_once('include/group.php');
263                 group_add($newuid, t('Friends'));
264
265                 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
266                         intval($newuid),
267                         dbesc(t('Friends'))
268                 );
269                 if (dbm::is_result($r)) {
270                         $def_gid = $r[0]['id'];
271
272                         q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
273                                 intval($r[0]['id']),
274                                 intval($newuid)
275                         );
276                 }
277
278                 if(get_config('system', 'newuser_private') && $def_gid) {
279                         q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
280                                 dbesc("<" . $def_gid . ">"),
281                                 intval($newuid)
282                         );
283                 }
284
285         }
286
287         // if we have no OpenID photo try to look up an avatar
288         if(! strlen($photo))
289                 $photo = avatar_img($email);
290
291         // unless there is no avatar-plugin loaded
292         if(strlen($photo)) {
293                 require_once('include/Photo.php');
294                 $photo_failure = false;
295
296                 $filename = basename($photo);
297                 $img_str = fetch_url($photo,true);
298                 // guess mimetype from headers or filename
299                 $type = guess_image_type($photo,true);
300
301
302                 $img = new Photo($img_str, $type);
303                 if($img->is_valid()) {
304
305                         $img->scaleImageSquare(175);
306
307                         $hash = photo_new_resource();
308
309                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
310
311                         if ($r === false) {
312                                 $photo_failure = true;
313                         }
314
315                         $img->scaleImage(80);
316
317                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
318
319                         if ($r === false) {
320                                 $photo_failure = true;
321                         }
322
323                         $img->scaleImage(48);
324
325                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
326
327                         if ($r === false) {
328                                 $photo_failure = true;
329                         }
330
331                         if (! $photo_failure) {
332                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
333                                         dbesc($hash)
334                                 );
335                         }
336                 }
337         }
338
339         call_hooks('register_account', $newuid);
340
341         $result['success'] = true;
342         $result['user'] = $u;
343         return $result;
344
345 }
346
347 /**
348  * @brief create the "self" contact from data from the user table
349  *
350  * @param integer $uid
351  */
352 function user_create_self_contact($uid) {
353
354         // Only create the entry if it doesn't exist yet
355         $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
356         if (dbm::is_result($r)) {
357                 return;
358         }
359
360         $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
361         if (!dbm::is_result($r)) {
362                 return;
363         }
364
365         $user = $r[0];
366
367         q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
368                 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
369                 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
370                 intval($user['uid']),
371                 datetime_convert(),
372                 dbesc($user['username']),
373                 dbesc($user['nickname']),
374                 dbesc(z_root()."/photo/profile/".$user['uid'].".jpg"),
375                 dbesc(z_root()."/photo/avatar/".$user['uid'].".jpg"),
376                 dbesc(z_root()."/photo/micro/".$user['uid'].".jpg"),
377                 dbesc(z_root()."/profile/".$user['nickname']),
378                 dbesc(normalise_link(z_root()."/profile/".$user['nickname'])),
379                 dbesc($user['nickname'].'@'.substr(z_root(), strpos(z_root(),'://') + 3)),
380                 dbesc(z_root()."/dfrn_request/".$user['nickname']),
381                 dbesc(z_root()."/dfrn_notify/".$user['nickname']),
382                 dbesc(z_root()."/dfrn_poll/".$user['nickname']),
383                 dbesc(z_root()."/dfrn_confirm/".$user['nickname']),
384                 dbesc(z_root()."/poco/".$user['nickname']),
385                 dbesc(datetime_convert()),
386                 dbesc(datetime_convert()),
387                 dbesc(datetime_convert())
388         );
389 }
390
391 /**
392  * @brief send registration confiƕmation with the intormation that reg is pending
393  *
394  * @param string $email
395  * @param string $sitename
396  * @param string $username
397  * @return NULL|boolean from notification() and email() inherited 
398  */
399 function send_register_pending_eml($email, $sitename, $username) {
400         $body = deindent(t('
401                 Dear %1$s,
402                         Thank you for registering at %2$s. Your account is pending for approval by the administrator.
403         '));
404
405         $body = sprintf($body, $username, $sitename);
406
407         return notification(array(
408                 'type' => "SYSTEM_EMAIL",
409                 'to_email' => $email,
410                 'subject'=> sprintf( t('Registration at %s'), $sitename),
411                 'body' => $body));
412 }
413
414 /*
415  * send registration confirmation.
416  * It's here as a function because the mail is sent
417  * from different parts
418  */
419 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
420         $preamble = deindent(t('
421                 Dear %1$s,
422                         Thank you for registering at %2$s. Your account has been created.
423         '));
424         $body = deindent(t('
425                 The login details are as follows:
426                         Site Location:  %3$s
427                         Login Name:     %1$s
428                         Password:       %5$s
429
430                 You may change your password from your account "Settings" page after logging
431                 in.
432
433                 Please take a few moments to review the other account settings on that page.
434
435                 You may also wish to add some basic information to your default profile
436                 (on the "Profiles" page) so that other people can easily find you.
437
438                 We recommend setting your full name, adding a profile photo,
439                 adding some profile "keywords" (very useful in making new friends) - and
440                 perhaps what country you live in; if you do not wish to be more specific
441                 than that.
442
443                 We fully respect your right to privacy, and none of these items are necessary.
444                 If you are new and do not know anybody here, they may help
445                 you to make some new and interesting friends.
446
447
448                 Thank you and welcome to %2$s.'));
449
450                 $preamble = sprintf($preamble, $username, $sitename);
451                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
452
453                 return notification(array(
454                         'type' => "SYSTEM_EMAIL",
455                         'to_email' => $email,
456                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
457                         'preamble'=> $preamble,
458                         'body' => $body));
459 }