]> git.mxchange.org Git - friendica.git/blob - mod/dfrn_poll.php
facebook connector - initial checkin (untested)
[friendica.git] / mod / dfrn_poll.php
1 <?php
2
3 require_once('include/items.php');
4 require_once('include/auth.php');
5
6
7 function dfrn_poll_init(&$a) {
8
9         $dfrn_id         = ((x($_GET,'dfrn_id'))         ? $_GET['dfrn_id']              : '');
10         $type            = ((x($_GET,'type'))            ? $_GET['type']                 : 'data');
11         $last_update     = ((x($_GET,'last_update'))     ? $_GET['last_update']          : '');
12         $destination_url = ((x($_GET,'destination_url')) ? $_GET['destination_url']      : '');
13         $challenge       = ((x($_GET,'challenge'))       ? $_GET['challenge']            : '');
14         $sec             = ((x($_GET,'sec'))             ? $_GET['sec']                  : '');
15         $dfrn_version    = ((x($_GET,'dfrn_version'))    ? (float) $_GET['dfrn_version'] : 2.0);
16
17         $direction = (-1);
18
19
20         if(strpos($dfrn_id,':') == 1) {
21                 $direction = intval(substr($dfrn_id,0,1));
22                 $dfrn_id   = substr($dfrn_id,2);
23         }
24
25         if(($dfrn_id === '') && (! x($_POST,'dfrn_id')) && ($a->argc > 1)) {
26                 header("Content-type: application/atom+xml");
27                 $o = get_feed_for($a, '*', $a->argv[1],$last_update);
28                 echo $o;
29                 killme();
30         }
31
32         if(($type === 'profile') && (! strlen($sec))) {
33
34                 $sql_extra = '';
35                 switch($direction) {
36                         case (-1):
37                                 $sql_extra = sprintf(" AND ( `dfrn-id` = '%s' OR `issued-id` = '%s' ) ", dbesc($dfrn_id),dbesc($dfrn_id));
38                                 $my_id = $dfrn_id;
39                                 break;
40                         case 0:
41                                 $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
42                                 $my_id = '1:' . $dfrn_id;
43                                 break;
44                         case 1:
45                                 $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
46                                 $my_id = '0:' . $dfrn_id;
47                                 break;
48                         default:
49                                 goaway($a->get_baseurl());
50                                 break; // NOTREACHED
51                 }
52
53                 $r = q("SELECT `contact`.*, `user`.`username`, `user`.`nickname` 
54                         FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
55                         WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 
56                         AND `user`.`nickname` = '%s' $sql_extra LIMIT 1",
57                         dbesc($a->argv[1])
58                 );
59                 
60                 if(count($r)) {
61
62                         $s = fetch_url($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check');
63
64                         logger("dfrn_poll: old profile returns " . $s, LOGGER_DATA);
65
66                         if(strlen($s)) {
67
68                                 $xml = simplexml_load_string($s);
69
70                                 if((int) $xml->status == 1) {
71                                         $_SESSION['authenticated'] = 1;
72                                         $_SESSION['visitor_id'] = $r[0]['id'];
73                                         notice( $r[0]['username'] . t(' welcomes ') . $r[0]['name'] . EOL);
74                                         // Visitors get 1 day session.
75                                         $session_id = session_id();
76                                         $expire = time() + 86400;
77                                         q("UPDATE `session` SET `expire` = '%s' WHERE `sid` = '%s' LIMIT 1",
78                                                 dbesc($expire),
79                                                 dbesc($session_id)
80                                         ); 
81                                 }
82                         }
83                         $profile = $r[0]['nickname'];
84                         goaway((strlen($destination_url)) ? $destination_url : $a->get_baseurl() . '/profile/' . $profile);
85                 }
86                 goaway($a->get_baseurl());
87
88         }
89
90         if($type === 'profile-check') {
91
92                 if((strlen($challenge)) && (strlen($sec))) {
93
94                         q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time()));
95                         $r = q("SELECT * FROM `profile_check` WHERE `sec` = '%s' ORDER BY `expire` DESC LIMIT 1",
96                                 dbesc($sec)
97                         );
98                         if(! count($r)) {
99                                 xml_status(3);
100                                 // NOTREACHED
101                         }
102                         $orig_id = $r[0]['dfrn_id'];
103                         if(strpos(':',$orig_id))
104                                 $orig_id = substr($orig_id,2);
105
106                         $c = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
107                                 intval($r[0]['cid'])
108                         );
109                         if(! count($c)) {
110                                 xml_status(3);
111                         }
112                         $contact = $c[0];
113
114                         $sent_dfrn_id = hex2bin($dfrn_id);
115                         $challenge    = hex2bin($challenge);
116
117                         $final_dfrn_id = '';
118
119                         if(($contact['duplex']) && strlen($contact['prvkey'])) {
120                                 openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']);
121                                 openssl_private_decrypt($challenge,$decoded_challenge,$contact['prvkey']);
122                         }
123                         else {
124                                 openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']);
125                                 openssl_public_decrypt($challenge,$decoded_challenge,$contact['pubkey']);
126                         }
127
128                         $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
129
130                         if(strpos($final_dfrn_id,':') == 1)
131                                 $final_dfrn_id = substr($final_dfrn_id,2);
132
133                         if($final_dfrn_id != $orig_id) {
134
135                                 // did not decode properly - cannot trust this site 
136                                 xml_status(3);
137                         }
138
139                         header("Content-type: text/xml");
140                         echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><dfrn_poll><status>0</status><challenge>$decoded_challenge</challenge><sec>$sec</sec></dfrn_poll>";
141                         killme();
142                         // NOTREACHED
143                 }
144                 else {
145                                 // old protocol
146
147                         switch($direction) {
148                                 case 1:
149                                         $dfrn_id = '0:' . $dfrn_id;
150                                         break;
151                                 case 0:
152                                         $dfrn_id = '1:' . $dfrn_id;
153                                         break;
154                                 default:
155                                         break;
156                         }
157
158
159                         q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time()));
160                         $r = q("SELECT * FROM `profile_check` WHERE `dfrn_id` = '%s' ORDER BY `expire` DESC",
161                                 dbesc($dfrn_id));
162                         if(count($r)) {
163                                 xml_status(1);
164                                 return; // NOTREACHED
165                         }
166                         xml_status(0);
167                         return; // NOTREACHED
168                 }
169         }
170
171 }
172
173
174
175 function dfrn_poll_post(&$a) {
176
177         $dfrn_id      = ((x($_POST,'dfrn_id'))      ? $_POST['dfrn_id']              : '');
178         $challenge    = ((x($_POST,'challenge'))    ? $_POST['challenge']            : '');
179         $url          = ((x($_POST,'url'))          ? $_POST['url']                  : '');
180         $dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 2.0);
181
182         $direction    = (-1);
183         if(strpos($dfrn_id,':') == 1) {
184                 $direction = intval(substr($dfrn_id,0,1));
185                 $dfrn_id   = substr($dfrn_id,2);
186         }
187
188
189         $r = q("SELECT * FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
190                 dbesc($dfrn_id),
191                 dbesc($challenge)
192         );
193
194         if(! count($r))
195                 killme();
196
197         $type = $r[0]['type'];
198         $last_update = $r[0]['last_update'];
199
200         $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
201                 dbesc($dfrn_id),
202                 dbesc($challenge)
203         );
204
205
206         $sql_extra = '';
207         switch($direction) {
208                 case (-1):
209                         $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
210                         $my_id = $dfrn_id;
211                         break;
212                 case 0:
213                         $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
214                         $my_id = '1:' . $dfrn_id;
215                         break;
216                 case 1:
217                         $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
218                         $my_id = '0:' . $dfrn_id;
219                         break;
220                 default:
221                         goaway($a->get_baseurl());
222                         break; // NOTREACHED
223         }
224
225
226         $r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1");
227
228
229         if(! count($r))
230                 killme();
231
232         $owner_uid = $r[0]['uid'];
233         $contact_id = $r[0]['id']; 
234
235
236         if($type === 'reputation' && strlen($url)) {
237                 $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
238                         dbesc($url),
239                         intval($owner_uid)
240                 );
241                 $reputation = 0;
242                 $text = '';
243
244                 if(count($r)) {
245                         $reputation = $r[0]['rating'];
246                         $text = $r[0]['reason'];
247
248                         if($r[0]['id'] == $contact_id) {        // inquiring about own reputation not allowed
249                                 $reputation = 0;
250                                 $text = '';
251                         }
252                 }
253
254                 echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
255                 <reputation>
256                         <url>$url</url>
257                         <rating>$reputation</rating>
258                         <description>$text</description>
259                 </reputation>
260                 ";
261                 killme();
262                 // NOTREACHED
263         }
264         else {
265                 header("Content-type: application/atom+xml");
266                 $o = get_feed_for($a,$dfrn_id, $a->argv[1], $last_update, $direction);
267                 echo $o;
268                 killme();
269
270         }
271 }
272
273 function dfrn_poll_content(&$a) {
274
275         $dfrn_id         = ((x($_GET,'dfrn_id'))         ? $_GET['dfrn_id']              : '');
276         $type            = ((x($_GET,'type'))            ? $_GET['type']                 : 'data');
277         $last_update     = ((x($_GET,'last_update'))     ? $_GET['last_update']          : '');
278         $destination_url = ((x($_GET,'destination_url')) ? $_GET['destination_url']      : '');
279         $sec             = ((x($_GET,'sec'))             ? $_GET['sec']                  : '');
280         $dfrn_version    = ((x($_GET,'dfrn_version'))    ? (float) $_GET['dfrn_version'] : 2.0);
281
282         $direction = (-1);
283         if(strpos($dfrn_id,':') == 1) {
284                 $direction = intval(substr($dfrn_id,0,1));
285                 $dfrn_id = substr($dfrn_id,2);
286         }
287
288
289         if($dfrn_id != '') {
290                 // initial communication from external contact
291                 $hash = random_string();
292
293                 $status = 0;
294
295                 $r = q("DELETE FROM `challenge` WHERE `expire` < " . intval(time()));
296
297                 if($type !== 'profile') {
298                         $r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` , `type`, `last_update` )
299                                 VALUES( '%s', '%s', '%s', '%s', '%s' ) ",
300                                 dbesc($hash),
301                                 dbesc($dfrn_id),
302                                 intval(time() + 60 ),
303                                 dbesc($type),
304                                 dbesc($last_update)
305                         );
306                 }
307                 $sql_extra = '';
308                 switch($direction) {
309                         case (-1):
310                                 if($type === 'profile')
311                                         $sql_extra = sprintf(" AND ( `dfrn-id` = '%s' OR `issued-id` = '%s' ) ", dbesc($dfrn_id),dbesc($dfrn_id));
312                                 else
313                                         $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
314                                 $my_id = $dfrn_id;
315                                 break;
316                         case 0:
317                                 $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
318                                 $my_id = '1:' . $dfrn_id;
319                                 break;
320                         case 1:
321                                 $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
322                                 $my_id = '0:' . $dfrn_id;
323                                 break;
324                         default:
325                                 goaway($a->get_baseurl());
326                                 break; // NOTREACHED
327                 }
328
329                 $r = q("SELECT `contact`.*, `user`.`username`, `user`.`nickname` 
330                         FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
331                         WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 
332                         AND `user`.`nickname` = '%s' $sql_extra LIMIT 1",
333                         dbesc($a->argv[1])
334                 );
335
336                 if(count($r)) {
337
338                         $challenge = '';
339                         $encrypted_id = '';
340                         $id_str = $my_id . '.' . mt_rand(1000,9999);
341
342                         if($r[0]['duplex'] && strlen($r[0]['pubkey'])) {
343                                 openssl_public_encrypt($hash,$challenge,$r[0]['pubkey']);
344                                 openssl_public_encrypt($id_str,$encrypted_id,$r[0]['pubkey']);
345                         }
346                         else {
347                                 openssl_private_encrypt($hash,$challenge,$r[0]['prvkey']);
348                                 openssl_private_encrypt($id_str,$encrypted_id,$r[0]['prvkey']);
349                         }
350
351                         $challenge = bin2hex($challenge);
352                         $encrypted_id = bin2hex($encrypted_id);
353                 }
354                 else {
355                         $status = 1;
356                         $challenge = '';
357                         $encrypted_id = '';
358                 }
359
360                 if(($type === 'profile') && (strlen($sec))) {
361                         // URL reply
362
363                         $s = fetch_url($r[0]['poll'] 
364                                 . '?dfrn_id=' . $encrypted_id 
365                                 . '&type=profile-check'
366                                 . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
367                                 . '&challenge=' . $challenge
368                                 . '&sec=' . $sec
369                         );
370
371                         logger("dfrn_poll: sec profile: " . $s, LOGGER_DATA);
372
373                         if(strlen($s) && strstr($s,'<?xml')) {
374
375                                 $xml = simplexml_load_string($s);
376
377                                 logger('dfrn_poll: profile: parsed xml: ' . print_r($xml,true), LOGGER_DATA);
378
379                                 logger('dfrn_poll: secure profile: challenge: ' . $xml->challenge . ' expecting ' . $hash);
380                                 logger('dfrn_poll: secure profile: sec: ' . $xml->sec . ' expecting ' . $sec);
381  
382                                 
383                                 if(((int) $xml->status == 0) && ($xml->challenge == $hash)  && ($xml->sec == $sec)) {
384                                         $_SESSION['authenticated'] = 1;
385                                         $_SESSION['visitor_id'] = $r[0]['id'];
386                                         notice( $r[0]['username'] . t(' welcomes ') . $r[0]['name'] . EOL);
387                                         // Visitors get 1 day session.
388                                         $session_id = session_id();
389                                         $expire = time() + 86400;
390                                         q("UPDATE `session` SET `expire` = '%s' WHERE `sid` = '%s' LIMIT 1",
391                                                 dbesc($expire),
392                                                 dbesc($session_id)
393                                         ); 
394                                 }
395                                 $profile = $r[0]['nickname'];
396                                 goaway((strlen($destination_url)) ? $destination_url : $a->get_baseurl() . '/profile/' . $profile);
397                         }
398                         goaway($a->get_baseurl());
399                         // NOTREACHED
400
401                 }
402                 else {
403                         // XML reply
404                         header("Content-type: text/xml");
405                         echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"
406                                 . '<dfrn_poll>' . "\r\n"
407                                 . "\t" . '<status>' . $status . '</status>' . "\r\n"
408                                 . "\t" . '<dfrn_version>' . DFRN_PROTOCOL_VERSION . '</dfrn_version>' . "\r\n"
409                                 . "\t" . '<dfrn_id>' . $encrypted_id . '</dfrn_id>' . "\r\n"
410                                 . "\t" . '<challenge>' . $challenge . '</challenge>' . "\r\n"
411                                 . '</dfrn_poll>' . "\r\n" ;
412                         killme();
413                         // NOTREACHED
414                 }
415         }
416 }
417
418