]> git.mxchange.org Git - friendica.git/blob - mod/dfrn_confirm.php
7daa7f94436b83f3bc564704d7d3b8d421aa89ca
[friendica.git] / mod / dfrn_confirm.php
1 <?php
2
3
4
5 function dfrn_confirm_post(&$a) {
6
7         if($a->argc > 1)
8                 $node = $a->argv[1];
9
10         if(x($_POST,'source_url')) {
11
12                 // We are processing an external confirmation to an introduction created by our user.
13
14                 $public_key = $_POST['public_key'];
15                 $dfrn_id    = $_POST['dfrn_id'];
16                 $source_url = $_POST['source_url'];
17                 $aes_key    = $_POST['aes_key'];
18                 $duplex     = $_POST['duplex'];
19                 $version_id = $_POST['dfrn_version'];
20
21                 // Find our user's account
22
23                 $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1",
24                         dbesc($node));
25
26                 if(! count($r)) {
27                         $message = t('No user record found for ') . '\'' . $node . '\'';
28                         xml_status(3,$message); // failure
29                         // NOTREACHED
30                 }
31
32                 $my_prvkey = $r[0]['prvkey'];
33                 $local_uid = $r[0]['uid'];
34
35
36                 if(! strstr($my_prvkey,'BEGIN RSA PRIVATE KEY')) {
37                         $message = t('Our site encryption key is apparently messed up.');
38                         xml_status(3,$message);
39                 }
40
41                 // verify everything
42
43                 $decrypted_source_url = "";
44                 openssl_private_decrypt($source_url,$decrypted_source_url,$my_prvkey);
45
46
47                 if(! strlen($decrypted_source_url)) {
48                         $message = t('Empty site URL was provided or URL could not be decrypted by us.');
49                         xml_status(3,$message);
50                         // NOTREACHED
51                 }
52
53                 $ret = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
54                         dbesc($decrypted_source_url),
55                         intval($local_uid)
56                 );
57
58                 if(! count($ret)) {
59                         // this is either a bogus confirmation (?) or we deleted the original introduction.
60                         $message = t('Contact record was not found for you on our site.');
61                         xml_status(3,$message);
62                         return; // NOTREACHED 
63                 }
64
65                 $relation = $ret[0]['rel'];
66
67                 // Decrypt all this stuff we just received
68
69                 $foreign_pubkey = $ret[0]['site-pubkey'];
70                 $dfrn_record    = $ret[0]['id'];
71
72                 $decrypted_dfrn_id = "";
73                 openssl_public_decrypt($dfrn_id,$decrypted_dfrn_id,$foreign_pubkey);
74
75                 if(strlen($aes_key)) {
76                         $decrypted_aes_key = "";
77                         openssl_private_decrypt($aes_key,$decrypted_aes_key,$my_prvkey);
78                         $dfrn_pubkey = openssl_decrypt($public_key,'AES-256-CBC',$decrypted_aes_key);
79                 }
80                 else {
81                         $dfrn_pubkey = $public_key;
82                 }
83
84                 $r = q("SELECT * FROM `contact` WHERE `dfrn-id` = '%s' LIMIT 1",
85                         dbesc($decrypted_dfrn_id),
86                         intval($local_uid)
87                 );
88                 if(count($r)) {
89                         $message = t('The ID provided by your system is a duplicate on our system. It should work if you try again.');
90                         xml_status(1,$message); // Birthday paradox - duplicate dfrn-id
91                         // NOTREACHED
92                 }
93
94                 $r = q("UPDATE `contact` SET `dfrn-id` = '%s', `pubkey` = '%s' WHERE `id` = %d LIMIT 1",
95                         dbesc($decrypted_dfrn_id),
96                         dbesc($dfrn_pubkey),
97                         intval($dfrn_record)
98                 );
99                 if(! count($r)) {
100                         $message = t('Unable to set your contact credentials on our system.');
101                         xml_status(3,$message);
102                 }
103
104                 // We're good but now we have to scrape the profile photo and send notifications.
105
106                 require_once("Photo.php");
107
108                 $photo_failure = false;
109
110                 $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1",
111                         intval($dfrn_record));
112                 if(count($r)) {
113
114                         $filename = basename($r[0]['photo']);
115                         $img_str = fetch_url($r[0]['photo'],true);
116                         $img = new Photo($img_str);
117                         if($img->is_valid()) {
118
119                                 $img->scaleImageSquare(175);
120                                         
121                                 $hash = photo_new_resource();
122
123                                 $r = $img->store($local_uid, $dfrn_record, $hash, $filename, t('Contact Photos') , 4);
124
125                                 if($r === false)
126                                         $photo_failure = true;
127                                         
128                                 $img->scaleImage(80);
129                                 $r = $img->store($local_uid, $dfrn_record, $hash, $filename, t('Contact Photos') , 5);
130
131                                 if($r === false)
132                                         $photo_failure = true;
133
134                                 $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
135                                 $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';      
136                         }
137                         else
138                                 $photo_failure = true;
139                 }
140                 else
141                         $photo_failure = true;
142
143                 if($photo_failure) {
144                         $photo = $a->get_baseurl() . '/images/default-profile.jpg';
145                         $thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
146                 }
147
148                 $new_relation = REL_FAN;
149                 if(($relation == REL_VIP) || ($duplex))
150                         $new_relation = REL_BUD;
151
152                 $r = q("UPDATE `contact` SET 
153                         `photo` = '%s', 
154                         `thumb` = '%s', 
155                         `rel` = %d, 
156                         `name-date` = '%s', 
157                         `uri-date` = '%s', 
158                         `avatar-date` = '%s', 
159                         `blocked` = 0, 
160                         `pending` = 0,
161                         `duplex` = %d, 
162                         `network` = 'dfrn' WHERE `id` = %d LIMIT 1
163                 ",
164                         dbesc($photo),
165                         dbesc($thumb),
166                         intval($new_relation),
167                         dbesc(datetime_convert()),
168                         dbesc(datetime_convert()),
169                         dbesc(datetime_convert()),
170                         intval($duplex),
171                         intval($dfrn_record)
172                 );
173                 if($r === false) { // should not happen unless schema is messed up
174                         $message = t('Unable to update your contact profile details on our system');
175                         xml_status(3,$message);
176                 }
177
178                 // Otherwise everything seems to have worked and we are almost done. Yay!
179                 // Send an email notification
180
181                 $r = q("SELECT * FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
182                         WHERE `contact`.`id` = %d LIMIT 1",
183                         intval($dfrn_record)
184                 );
185                 if((count($r)) && ($r[0]['notify-flags'] & NOTIFY_CONFIRM)) {
186
187                         $tpl = (($new_relation == REL_BUD) 
188                                 ? load_view_file('view/friend_complete_eml.tpl')
189                                 : load_view_file('view/intro_complete_eml.tpl'));
190                 
191                         $email_tpl = replace_macros($tpl, array(
192                                 '$sitename' => $a->config['sitename'],
193                                 '$siteurl' =>  $a->get_baseurl(),
194                                 '$username' => $r[0]['username'],
195                                 '$email' => $r[0]['email'],
196                                 '$fn' => $r[0]['name'],
197                                 '$dfrn_url' => $r[0]['url'],
198                                 '$uid' => $newuid )
199                         );
200         
201                         $res = mail($r[0]['email'], t("Connection accepted at ") . $a->config['sitename'],
202                                 $email_tpl, 'From: ' . t('Administrator') . '@' . $_SERVER[SERVER_NAME] );
203                         if(!$res) {
204                                 notice( t("Email notification failed.") . EOL );
205                         }
206                 }
207                 xml_status(0); // Success
208                 return; // NOTREACHED
209
210         ////////////////////// End of this scenario ///////////////////////////////////////////////
211         }
212         else {
213
214                 // We are processing a local confirmation initiated on this system by our user to an external introduction.
215
216                 $uid = get_uid();
217
218                 if(! $uid) {
219                         notice( t('Permission denied.') . EOL );
220                         return;
221                 }       
222         
223                 $dfrn_id  = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : "");
224                 $intro_id = intval($_POST['intro_id']);
225                 $duplex   = intval($_POST['duplex']);
226
227                 $r = q("SELECT * FROM `contact` WHERE `issued-id` = '%s' AND `uid` = %d LIMIT 1",
228                                 dbesc($dfrn_id),
229                                 intval($uid)
230                 );
231
232                 if(! count($r)) {
233                         notice( t('Node does not exist.') . EOL );
234                         return;
235                 }
236
237                 $contact_id   = $r[0]['id'];
238                 $relation     = $r[0]['rel'];
239                 $site_pubkey  = $r[0]['site-pubkey'];
240                 $dfrn_confirm = $r[0]['confirm'];
241                 $aes_allow    = $r[0]['aes_allow'];
242
243                 $res = openssl_pkey_new(array(
244                         'digest_alg' => 'whirlpool',
245                         'private_key_bits' => 4096,
246                         'encrypt_key' => false )
247                 );
248
249
250                 $private_key = '';
251
252                 openssl_pkey_export($res, $private_key);
253
254                 $pubkey = openssl_pkey_get_details($res);
255                 $public_key = $pubkey["key"];
256
257                 $r = q("UPDATE `contact` SET `prvkey` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
258                         dbesc($private_key),
259                         intval($contact_id),
260                         intval($uid) 
261                 );
262
263
264                 $params = array();
265
266                 $src_aes_key = random_string();
267
268                 $result = '';
269                 openssl_private_encrypt($dfrn_id,$result,$a->user['prvkey']);
270
271                 $params['dfrn_id'] = $result;
272                 $params['public_key'] = $public_key;
273
274
275                 $my_url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
276
277                 openssl_public_encrypt($my_url, $params['source_url'], $site_pubkey);
278
279                 if($aes_allow && function_exists('openssl_encrypt')) {
280                         openssl_public_encrypt($src_aes_key, $params['aes_key'], $site_pubkey);
281                         $params['public_key'] = openssl_encrypt($public_key,'AES-256-CBC',$src_aes_key);
282                 }
283
284                 $params['dfrn_version'] = '2.0';
285                 if($duplex == 1)
286                         $params['duplex'] = 1;
287
288                 $res = post_url($dfrn_confirm,$params);
289
290                 // Try to be robust if the remote site is having difficulty and throwing up
291                 // errors of some kind. 
292
293                 $leading_junk = substr($res,0,strpos($res,'<?xml'));
294
295                 $res = substr($res,strpos($res,'<?xml'));
296                 if(! strlen($res)) {
297
298                                 // No XML at all, this exchange is messed up really bad.
299                                 // We shouldn't proceed, because the xml parser might choke,
300                                 // and $status is going to be zero, which indicates success.
301                                 // We can hardly call this a success.  
302
303                         notice( t('Response from remote site was not understood.') . EOL);
304                         return;
305                 }
306
307                 if(strlen($leading_junk) && get_config('system','debugging')) {
308
309                                 // This might be more common. Mixed error text and some XML.
310                                 // If we're configured for debugging, show the text. Proceed in either case.
311
312                         notice( t('Unexpected response from remote site: ') . EOL . $leading_junk . EOL );
313                 }
314
315                 $xml = simplexml_load_string($res);
316                 $status = (int) $xml->status;
317                 $message = unxmlify($xml->message);
318                 switch($status) {
319                         case 0:
320                                 notice( t("Confirmation completed successfully.") . EOL);
321                                 if(strlen($message))
322                                         notice( t('Remote site reported: ') . $message . EOL);
323                                 break;
324                         case 1:
325                                 // birthday paradox - generate new dfrn-id and fall through.
326                                 $new_dfrn_id = random_string();
327                                 $r = q("UPDATE contact SET `issued-id` = '%s' WHERE `id` = %d AND `uid` = %d LIMIT 1",
328                                         dbesc($new_dfrn_id),
329                                         intval($contact_id),
330                                         intval($uid) 
331                                 );
332
333                         case 2:
334                                 notice( t("Temporary failure. Please wait and try again.") . EOL);
335                                 if(strlen($message))
336                                         notice( t('Remote site reported: ') . $message . EOL);
337                                 break;
338
339
340                         case 3:
341                                 notice( t("Introduction failed or was revoked.") . EOL);
342                                 if(strlen($message))
343                                         notice( t('Remote site reported: ') . $message . EOL);
344                                 break;
345                         }
346
347                 if(($status == 0) && ($intro_id)) {
348
349                         //delete the notification
350
351                         $r = q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d LIMIT 1",
352                                 intval($intro_id),
353                                 intval($uid)
354                         );
355                         
356                 }
357
358                 if($status != 0) 
359                         return;
360                 
361                 require_once("Photo.php");
362
363                 $photo_failure = false;
364
365                 $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1",
366                         intval($contact_id));
367                 if(count($r)) {
368
369                         $filename = basename($r[0]['photo']);
370                         $img_str = fetch_url($r[0]['photo'],true);
371                         $img = new Photo($img_str);
372                         if($img->is_valid()) {
373
374                                 $img->scaleImageSquare(175);
375                                         
376                                 $hash = photo_new_resource();
377
378                                 $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 4 );
379
380                                 if($r === false)
381                                         $photo_failure = true;
382
383                                 $img->scaleImage(80);
384
385                                 $r = $img->store($uid, $contact_id, $hash, $filename, t('Contact Photos'), 5 );
386
387                                 if($r === false)
388                                         $photo_failure = true;
389
390                                 $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg';
391                                 $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg';
392                         }
393                         else
394                                 $photo_failure = true;
395                 }
396                 else
397                         $photo_failure = true;
398
399                 if($photo_failure) {
400                         $photo = $a->get_baseurl() . '/images/default-profile.jpg';
401                         $thumb = $a->get_baseurl() . '/images/default-profile-sm.jpg';
402                 }
403
404                 $new_relation = REL_VIP;
405                 if(($relation == REL_FAN) || ($duplex))
406                         $new_relation = REL_BUD;
407
408                 $r = q("UPDATE `contact` SET `photo` = '%s', 
409                         `thumb` = '%s', 
410                         `rel` = %d, 
411                         `name-date` = '%s', 
412                         `uri-date` = '%s', 
413                         `avatar-date` = '%s', 
414                         `blocked` = 0, 
415                         `pending` = 0,
416                         `duplex` = %d,
417                         `network` = 'dfrn' WHERE `id` = %d LIMIT 1
418                 ",
419                         dbesc($photo),
420                         dbesc($thumb),
421                         intval($new_relation),
422                         dbesc(datetime_convert()),
423                         dbesc(datetime_convert()),
424                         dbesc(datetime_convert()),
425                         intval($duplex),
426                         intval($contact_id)
427                 );
428                 if($r === false)
429                         notice( t('Unable to set contact photo.') . EOL);
430
431                 goaway($a->get_baseurl() . '/contacts/' . intval($contact_id));
432                 return;  //NOTREACHED
433         }
434         return;
435 }