]> git.mxchange.org Git - friendica.git/blob - include/user.php
Merge branch 'develop' of github.com:annando/friendica into 1409-shadow-items
[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         $blocked    = ((x($arr,'blocked'))    ? intval($arr['blocked'])  : 0);
31         $verified   = ((x($arr,'verified'))   ? intval($arr['verified']) : 0);
32
33         $publish    = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
34         $netpublish = ((strlen(get_config('system','directory_submit_url'))) ? $publish : 0);
35
36         $tmp_str = $openid_url;
37
38         if($using_invites) {
39                 if(! $invite_id) {
40                         $result['message'] .= t('An invitation is required.') . EOL;
41                         return $result;
42                 }
43                 $r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id));
44                 if(! results($r)) {
45                         $result['message'] .= t('Invitation could not be verified.') . EOL;
46                         return $result;
47                 }
48         }
49
50         if((! x($username)) || (! x($email)) || (! x($nickname))) {
51                 if($openid_url) {
52                         if(! validate_url($tmp_str)) {
53                                 $result['message'] .= t('Invalid OpenID url') . EOL;
54                                 return $result;
55                         }
56                         $_SESSION['register'] = 1;
57                         $_SESSION['openid'] = $openid_url;
58                         require_once('library/openid.php');
59                         $openid = new LightOpenID;
60                         $openid->identity = $openid_url;
61                         $openid->returnUrl = $a->get_baseurl() . '/openid';
62                         $openid->required = array('namePerson/friendly', 'contact/email', 'namePerson');
63                         $openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
64                         try {
65                                 $authurl = $openid->authUrl();
66                         } catch (Exception $e){
67                                 $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;
68                                 return $result;
69                         }
70                         goaway($authurl);
71                         // NOTREACHED
72                 }
73
74                 notice( t('Please enter the required information.') . EOL );
75                 return;
76         }
77
78         if(! validate_url($tmp_str))
79                 $openid_url = '';
80
81
82         $err = '';
83
84         // collapse multiple spaces in name
85         $username = preg_replace('/ +/',' ',$username);
86
87         if(mb_strlen($username) > 48)
88                 $result['message'] .= t('Please use a shorter name.') . EOL;
89         if(mb_strlen($username) < 3)
90                 $result['message'] .= t('Name too short.') . EOL;
91
92         // I don't really like having this rule, but it cuts down
93         // on the number of auto-registrations by Russian spammers
94
95         //  Using preg_match was completely unreliable, due to mixed UTF-8 regex support
96         //      $no_utf = get_config('system','no_utf');
97         //      $pat = (($no_utf) ? '/^[a-zA-Z]* [a-zA-Z]*$/' : '/^\p{L}* \p{L}*$/u' );
98
99         // So now we are just looking for a space in the full name.
100
101         $loose_reg = get_config('system','no_regfullname');
102         if(! $loose_reg) {
103                 $username = mb_convert_case($username,MB_CASE_TITLE,'UTF-8');
104                 if(! strpos($username,' '))
105                         $result['message'] .= t("That doesn't appear to be your full \x28First Last\x29 name.") . EOL;
106         }
107
108
109         if(! allowed_email($email))
110                 $result['message'] .= t('Your email domain is not among those allowed on this site.') . EOL;
111
112         if((! valid_email($email)) || (! validate_email($email)))
113                 $result['message'] .= t('Not a valid email address.') . EOL;
114
115         // Disallow somebody creating an account using openid that uses the admin email address,
116         // since openid bypasses email verification. We'll allow it if there is not yet an admin account.
117
118         $adminlist = explode(",", str_replace(" ", "", strtolower($a->config['admin_email'])));
119
120         //if((x($a->config,'admin_email')) && (strcasecmp($email,$a->config['admin_email']) == 0) && strlen($openid_url)) {
121         if((x($a->config,'admin_email')) && in_array(strtolower($email), $adminlist) && strlen($openid_url)) {
122                 $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
123                         dbesc($email)
124                 );
125                 if(count($r))
126                         $result['message'] .= t('Cannot use that email.') . EOL;
127         }
128
129         $nickname = $arr['nickname'] = strtolower($nickname);
130
131         if(! preg_match("/^[a-z][a-z0-9\-\_]*$/",$nickname))
132                 $result['message'] .= t('Your "nickname" can only contain "a-z", "0-9", "-", and "_", and must also begin with a letter.') . EOL;
133         $r = q("SELECT `uid` FROM `user`
134                 WHERE `nickname` = '%s' LIMIT 1",
135                 dbesc($nickname)
136         );
137         if(count($r))
138                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
139
140         // Check deleted accounts that had this nickname. Doesn't matter to us,
141         // but could be a security issue for federated platforms.
142
143         $r = q("SELECT * FROM `userd`
144                 WHERE `username` = '%s' LIMIT 1",
145                 dbesc($nickname)
146         );
147         if(count($r))
148                 $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
149
150         if(strlen($result['message'])) {
151                 return $result;
152         }
153
154         $new_password = ((strlen($password)) ? $password : autoname(6) . mt_rand(100,9999));
155         $new_password_encoded = hash('whirlpool',$new_password);
156
157         $result['password'] = $new_password;
158
159         require_once('include/crypto.php');
160
161         $keys = new_keypair(4096);
162
163         if($keys === false) {
164                 $result['message'] .= t('SERIOUS ERROR: Generation of security keys failed.') . EOL;
165                 return $result;
166         }
167
168         $default_service_class = get_config('system','default_service_class');
169         if(! $default_service_class)
170                 $default_service_class = '';
171
172
173         $prvkey = $keys['prvkey'];
174         $pubkey = $keys['pubkey'];
175
176         /**
177          *
178          * Create another keypair for signing/verifying
179          * salmon protocol messages. We have to use a slightly
180          * less robust key because this won't be using openssl
181          * but the phpseclib. Since it is PHP interpreted code
182          * it is not nearly as efficient, and the larger keys
183          * will take several minutes each to process.
184          *
185          */
186
187         $sres    = new_keypair(512);
188         $sprvkey = $sres['prvkey'];
189         $spubkey = $sres['pubkey'];
190
191         $r = q("INSERT INTO `user` ( `guid`, `username`, `password`, `email`, `openid`, `nickname`,
192                 `pubkey`, `prvkey`, `spubkey`, `sprvkey`, `register_date`, `verified`, `blocked`, `timezone`, `service_class`, `default-location` )
193                 VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, 'UTC', '%s', '' )",
194                 dbesc(generate_user_guid()),
195                 dbesc($username),
196                 dbesc($new_password_encoded),
197                 dbesc($email),
198                 dbesc($openid_url),
199                 dbesc($nickname),
200                 dbesc($pubkey),
201                 dbesc($prvkey),
202                 dbesc($spubkey),
203                 dbesc($sprvkey),
204                 dbesc(datetime_convert()),
205                 intval($verified),
206                 intval($blocked),
207                 dbesc($default_service_class)
208         );
209
210         if($r) {
211                 $r = q("SELECT * FROM `user`
212                         WHERE `username` = '%s' AND `password` = '%s' LIMIT 1",
213                         dbesc($username),
214                         dbesc($new_password_encoded)
215                 );
216                 if($r !== false && count($r)) {
217                         $u = $r[0];
218                         $newuid = intval($r[0]['uid']);
219                 }
220         }
221         else {
222                 $result['message'] .=  t('An error occurred during registration. Please try again.') . EOL ;
223                 return $result;
224         }
225
226         /**
227          * if somebody clicked submit twice very quickly, they could end up with two accounts
228          * due to race condition. Remove this one.
229          */
230
231         $r = q("SELECT `uid` FROM `user`
232                 WHERE `nickname` = '%s' ",
233                 dbesc($nickname)
234         );
235         if((count($r) > 1) && $newuid) {
236                 $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
237                 q("DELETE FROM `user` WHERE `uid` = %d",
238                         intval($newuid)
239                 );
240                 return $result;
241         }
242
243         if(x($newuid) !== false) {
244                 $r = q("INSERT INTO `profile` ( `uid`, `profile-name`, `is-default`, `name`, `photo`, `thumb`, `publish`, `net-publish` )
245                         VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, %d ) ",
246                         intval($newuid),
247                         t('default'),
248                         1,
249                         dbesc($username),
250                         dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"),
251                         dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"),
252                         intval($publish),
253                         intval($netpublish)
254
255                 );
256                 if($r === false) {
257                         $result['message'] .=  t('An error occurred creating your default profile. Please try again.') . EOL;
258                         // Start fresh next time.
259                         $r = q("DELETE FROM `user` WHERE `uid` = %d",
260                                 intval($newuid));
261                         return $result;
262                 }
263                 $r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
264                         `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness` )
265                         VALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0 ) ",
266                         intval($newuid),
267                         datetime_convert(),
268                         dbesc($username),
269                         dbesc($nickname),
270                         dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"),
271                         dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"),
272                         dbesc($a->get_baseurl() . "/photo/micro/{$newuid}.jpg"),
273                         dbesc($a->get_baseurl() . "/profile/$nickname"),
274                         dbesc(normalise_link($a->get_baseurl() . "/profile/$nickname")),
275                         dbesc($a->get_baseurl() . "/dfrn_request/$nickname"),
276                         dbesc($a->get_baseurl() . "/dfrn_notify/$nickname"),
277                         dbesc($a->get_baseurl() . "/dfrn_poll/$nickname"),
278                         dbesc($a->get_baseurl() . "/dfrn_confirm/$nickname"),
279                         dbesc($a->get_baseurl() . "/poco/$nickname"),
280                         dbesc(datetime_convert()),
281                         dbesc(datetime_convert()),
282                         dbesc(datetime_convert())
283                 );
284
285                 // Create a group with no members. This allows somebody to use it
286                 // right away as a default group for new contacts.
287
288                 require_once('include/group.php');
289                 group_add($newuid, t('Friends'));
290
291                 $r = q("SELECT id FROM `group` WHERE uid = %d AND name = '%s'",
292                         intval($newuid),
293                         dbesc(t('Friends'))
294                 );
295                 if($r && count($r)) {
296                         $def_gid = $r[0]['id'];
297
298                         q("UPDATE user SET def_gid = %d WHERE uid = %d",
299                                 intval($r[0]['id']),
300                                 intval($newuid)
301                         );
302                 }
303
304                 if(get_config('system', 'newuser_private') && $def_gid) {
305                         q("UPDATE user SET allow_gid = '%s' WHERE uid = %d",
306                            dbesc("<" . $def_gid . ">"),
307                            intval($newuid)
308                         );
309                 }
310
311         }
312
313         // if we have no OpenID photo try to look up an avatar
314         if(! strlen($photo))
315                 $photo = avatar_img($email);
316
317         // unless there is no avatar-plugin loaded
318         if(strlen($photo)) {
319                 require_once('include/Photo.php');
320                 $photo_failure = false;
321
322                 $filename = basename($photo);
323                 $img_str = fetch_url($photo,true);
324                 // guess mimetype from headers or filename
325                 $type = guess_image_type($photo,true);
326
327
328                 $img = new Photo($img_str, $type);
329                 if($img->is_valid()) {
330
331                         $img->scaleImageSquare(175);
332
333                         $hash = photo_new_resource();
334
335                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 4 );
336
337                         if($r === false)
338                                 $photo_failure = true;
339
340                         $img->scaleImage(80);
341
342                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 5 );
343
344                         if($r === false)
345                                 $photo_failure = true;
346
347                         $img->scaleImage(48);
348
349                         $r = $img->store($newuid, 0, $hash, $filename, t('Profile Photos'), 6 );
350
351                         if($r === false)
352                                 $photo_failure = true;
353
354                         if(! $photo_failure) {
355                                 q("UPDATE `photo` SET `profile` = 1 WHERE `resource-id` = '%s' ",
356                                         dbesc($hash)
357                                 );
358                         }
359                 }
360         }
361
362         call_hooks('register_account', $newuid);
363
364         $result['success'] = true;
365         $result['user'] = $u;
366         return $result;
367
368 }
369
370
371 /*
372  * send registration confirmation.
373  * It's here as a function because the mail is sent
374  * from different parts
375  */
376 function send_register_open_eml($email, $sitename, $siteurl, $username, $password){
377         $preamble = deindent(t('
378                 Dear %1$s,
379                         Thank you for registering at %2$s. Your account has been created.
380         '));
381         $body = deindent(t('
382                 The login details are as follows:
383                         Site Location:  %3$s
384                         Login Name:     %1$s
385                         Password:       %5$s
386
387                 You may change your password from your account "Settings" page after logging
388                 in.
389
390                 Please take a few moments to review the other account settings on that page.
391
392                 You may also wish to add some basic information to your default profile
393                 (on the "Profiles" page) so that other people can easily find you.
394
395                 We recommend setting your full name, adding a profile photo,
396                 adding some profile "keywords" (very useful in making new friends) - and
397                 perhaps what country you live in; if you do not wish to be more specific
398                 than that.
399
400                 We fully respect your right to privacy, and none of these items are necessary.
401                 If you are new and do not know anybody here, they may help
402                 you to make some new and interesting friends.
403
404
405                 Thank you and welcome to %2$s.'));
406
407                 $preamble = sprintf($preamble, $username, $sitename);
408                 $body = sprintf($body, $email, $sitename, $siteurl, $username, $password);
409
410                 return notification(array(
411                         'type' => "SYSTEM_EMAIL",
412                         'to_email' => $email,
413                         'subject'=> sprintf( t('Registration details for %s'), $sitename),
414                         'preamble'=> $preamble,
415                         'body' => $body));
416 }