]> git.mxchange.org Git - friendica.git/blob - include/user.php
Degrade priority step by step
[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                 dba::delete('user', array('uid' => $newuid));
230                 return $result;
231         }
232
233         if(x($newuid) !== false) {
234                 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
235                         VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
236                         intval($newuid),
237                         t('default'),
238                         1,
239                         dbesc($username),
240                         dbesc(z_root() . "/photo/profile/{$newuid}.jpg"),
241                         dbesc(z_root() . "/photo/avatar/{$newuid}.jpg"),
242                         intval($publish),
243                         intval($netpublish)
244
245                 );
246                 if ($r === false) {
247                         $result['message'] .=  t('An error occurred creating your default profile. Please try again.') . EOL;
248                         // Start fresh next time.
249                         dba::delete('user', array('uid' => $newuid));
250                         return $result;
251                 }
252
253                 // Create the self contact
254                 user_create_self_contact($newuid);
255
256                 // Create a group with no members. This allows somebody to use it
257                 // right away as a default group for new contacts.
258
259                 require_once('include/group.php');
260                 group_add($newuid, t('Friends'));
261
262                 $r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
263                         intval($newuid),
264                         dbesc(t('Friends'))
265                 );
266                 if (dbm::is_result($r)) {
267                         $def_gid = $r[0]['id'];
268
269                         q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
270                                 intval($r[0]['id']),
271                                 intval($newuid)
272                         );
273                 }
274
275                 if(get_config('system', 'newuser_private') && $def_gid) {
276                         q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
277                                 dbesc("<" . $def_gid . ">"),
278                                 intval($newuid)
279                         );
280                 }
281
282         }
283
284         // if we have no OpenID photo try to look up an avatar
285         if(! strlen($photo))
286                 $photo = avatar_img($email);
287
288         // unless there is no avatar-plugin loaded
289         if(strlen($photo)) {
290                 require_once('include/Photo.php');
291                 $photo_failure = false;
292
293                 $filename = basename($photo);
294                 $img_str = fetch_url($photo,true);
295                 // guess mimetype from headers or filename
296                 $type = guess_image_type($photo,true);
297
298
299                 $img = new Photo($img_str, $type);
300                 if($img->is_valid()) {
301
302                         $img->scaleImageSquare(175);
303
304                         $hash = photo_new_resource();
305
306                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
307
308                         if ($r === false) {
309                                 $photo_failure = true;
310                         }
311
312                         $img->scaleImage(80);
313
314                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
315
316                         if ($r === false) {
317                                 $photo_failure = true;
318                         }
319
320                         $img->scaleImage(48);
321
322                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
323
324                         if ($r === false) {
325                                 $photo_failure = true;
326                         }
327
328                         if (! $photo_failure) {
329                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
330                                         dbesc($hash)
331                                 );
332                         }
333                 }
334         }
335
336         call_hooks('register_account', $newuid);
337
338         $result['success'] = true;
339         $result['user'] = $u;
340         return $result;
341
342 }
343
344 /**
345  * @brief create the "self" contact from data from the user table
346  *
347  * @param integer $uid
348  */
349 function user_create_self_contact($uid) {
350
351         // Only create the entry if it doesn't exist yet
352         $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
353         if (dbm::is_result($r)) {
354                 return;
355         }
356
357         $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
358         if (!dbm::is_result($r)) {
359                 return;
360         }
361
362         $user = $r[0];
363
364         q("INSERT INTO `contact` (`uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
365                 `addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness`)
366                 VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0)",
367                 intval($user['uid']),
368                 datetime_convert(),
369                 dbesc($user['username']),
370                 dbesc($user['nickname']),
371                 dbesc(z_root()."/photo/profile/".$user['uid'].".jpg"),
372                 dbesc(z_root()."/photo/avatar/".$user['uid'].".jpg"),
373                 dbesc(z_root()."/photo/micro/".$user['uid'].".jpg"),
374                 dbesc(z_root()."/profile/".$user['nickname']),
375                 dbesc(normalise_link(z_root()."/profile/".$user['nickname'])),
376                 dbesc($user['nickname'].'@'.substr(z_root(), strpos(z_root(),'://') + 3)),
377                 dbesc(z_root()."/dfrn_request/".$user['nickname']),
378                 dbesc(z_root()."/dfrn_notify/".$user['nickname']),
379                 dbesc(z_root()."/dfrn_poll/".$user['nickname']),
380                 dbesc(z_root()."/dfrn_confirm/".$user['nickname']),
381                 dbesc(z_root()."/poco/".$user['nickname']),
382                 dbesc(datetime_convert()),
383                 dbesc(datetime_convert()),
384                 dbesc(datetime_convert())
385         );
386 }
387
388 /**
389  * @brief send registration confiƕmation with the intormation that reg is pending
390  *
391  * @param string $email
392  * @param string $sitename
393  * @param string $username
394  * @return NULL|boolean from notification() and email() inherited 
395  */
396 function send_register_pending_eml($email, $sitename, $username) {
397         $body = deindent(t('
398                 Dear %1$s,
399                         Thank you for registering at %2$s. Your account is pending for approval by the administrator.
400         '));
401
402         $body = sprintf($body, $username, $sitename);
403
404         return notification(array(
405                 'type' => "SYSTEM_EMAIL",
406                 'to_email' => $email,
407                 'subject'=> sprintf( t('Registration at %s'), $sitename),
408                 'body' => $body));
409 }
410
411 /*
412  * send registration confirmation.
413  * It's here as a function because the mail is sent
414  * from different parts
415  */
416 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
417         $preamble = deindent(t('
418                 Dear %1$s,
419                         Thank you for registering at %2$s. Your account has been created.
420         '));
421         $body = deindent(t('
422                 The login details are as follows:
423                         Site Location:  %3$s
424                         Login Name:     %1$s
425                         Password:       %5$s
426
427                 You may change your password from your account "Settings" page after logging
428                 in.
429
430                 Please take a few moments to review the other account settings on that page.
431
432                 You may also wish to add some basic information to your default profile
433                 (on the "Profiles" page) so that other people can easily find you.
434
435                 We recommend setting your full name, adding a profile photo,
436                 adding some profile "keywords" (very useful in making new friends) - and
437                 perhaps what country you live in; if you do not wish to be more specific
438                 than that.
439
440                 We fully respect your right to privacy, and none of these items are necessary.
441                 If you are new and do not know anybody here, they may help
442                 you to make some new and interesting friends.
443
444
445                 Thank you and welcome to %2$s.'));
446
447                 $preamble = sprintf($preamble, $username, $sitename);
448                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
449
450                 return notification(array(
451                         'type' => "SYSTEM_EMAIL",
452                         'to_email' => $email,
453                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
454                         'preamble'=> $preamble,
455                         'body' => $body));
456 }