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