Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
8.4 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
  1. <?php
  2. require_once('library/simplepie/simplepie.inc');
  3. require_once('include/items.php');
  4. require_once('include/event.php');
  5. function dfrn_notify_post(&$a) {
  6. $dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : '');
  7. $dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 2.0);
  8. $challenge = ((x($_POST,'challenge')) ? notags(trim($_POST['challenge'])) : '');
  9. $data = ((x($_POST,'data')) ? $_POST['data'] : '');
  10. $key = ((x($_POST,'key')) ? $_POST['key'] : '');
  11. $dissolve = ((x($_POST,'dissolve')) ? intval($_POST['dissolve']) : 0);
  12. $perm = ((x($_POST,'perm')) ? notags(trim($_POST['perm'])) : 'r');
  13. $ssl_policy = ((x($_POST,'ssl_policy')) ? notags(trim($_POST['ssl_policy'])): 'none');
  14. $page = ((x($_POST,'page')) ? intval($_POST['page']) : 0);
  15. $forum = (($page == 1) ? 1 : 0);
  16. $prv = (($page == 2) ? 1 : 0);
  17. $writable = (-1);
  18. if($dfrn_version >= 2.21) {
  19. $writable = (($perm === 'rw') ? 1 : 0);
  20. }
  21. $direction = (-1);
  22. if(strpos($dfrn_id,':') == 1) {
  23. $direction = intval(substr($dfrn_id,0,1));
  24. $dfrn_id = substr($dfrn_id,2);
  25. }
  26. $r = q("SELECT * FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
  27. dbesc($dfrn_id),
  28. dbesc($challenge)
  29. );
  30. if(! count($r)) {
  31. logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge);
  32. xml_status(3);
  33. }
  34. $r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s' LIMIT 1",
  35. dbesc($dfrn_id),
  36. dbesc($challenge)
  37. );
  38. // find the local user who owns this relationship.
  39. $sql_extra = '';
  40. switch($direction) {
  41. case (-1):
  42. $sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
  43. break;
  44. case 0:
  45. $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  46. break;
  47. case 1:
  48. $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  49. break;
  50. default:
  51. xml_status(3);
  52. break; // NOTREACHED
  53. }
  54. // be careful - $importer will contain both the contact information for the contact
  55. // sending us the post, and also the user information for the person receiving it.
  56. // since they are mixed together, it is easy to get them confused.
  57. $r = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`,
  58. `contact`.`pubkey` AS `cpubkey`,
  59. `contact`.`prvkey` AS `cprvkey`,
  60. `contact`.`thumb` AS `thumb`,
  61. `contact`.`url` as `url`,
  62. `contact`.`name` as `senderName`,
  63. `user`.*
  64. FROM `contact`
  65. LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
  66. WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  67. AND `user`.`nickname` = '%s' AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 $sql_extra LIMIT 1",
  68. dbesc($a->argv[1])
  69. );
  70. if(! count($r)) {
  71. logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id);
  72. xml_status(3);
  73. //NOTREACHED
  74. }
  75. // $importer in this case contains the contact record for the remote contact joined with the user record of our user.
  76. $importer = $r[0];
  77. if((($writable != (-1)) && ($writable != $importer['writable'])) || ($importer['forum'] != $forum) || ($importer['prv'] != $prv)) {
  78. q("UPDATE `contact` SET `writable` = %d, forum = %d, prv = %d WHERE `id` = %d LIMIT 1",
  79. intval(($writable == (-1)) ? $importer['writable'] : $writable),
  80. intval($forum),
  81. intval($prv),
  82. intval($importer['id'])
  83. );
  84. if($writable != (-1))
  85. $importer['writable'] = $writable;
  86. $importer['forum'] = $page;
  87. }
  88. // if contact's ssl policy changed, update our links
  89. fix_contact_ssl_policy($importer,$ssl_policy);
  90. logger('dfrn_notify: received notify from ' . $importer['name'] . ' for ' . $importer['username']);
  91. logger('dfrn_notify: data: ' . $data, LOGGER_DATA);
  92. if($dissolve == 1) {
  93. /**
  94. * Relationship is dissolved permanently
  95. */
  96. require_once('include/Contact.php');
  97. contact_remove($importer['id']);
  98. logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']);
  99. xml_status(0);
  100. }
  101. // If we are setup as a soapbox we aren't accepting input from this person
  102. if($importer['page-flags'] == PAGE_SOAPBOX)
  103. xml_status(0);
  104. if(strlen($key)) {
  105. $rawkey = hex2bin(trim($key));
  106. logger('rino: md5 raw key: ' . md5($rawkey));
  107. $final_key = '';
  108. if($dfrn_version >= 2.1) {
  109. if((($importer['duplex']) && strlen($importer['cprvkey'])) || (! strlen($importer['cpubkey']))) {
  110. openssl_private_decrypt($rawkey,$final_key,$importer['cprvkey']);
  111. }
  112. else {
  113. openssl_public_decrypt($rawkey,$final_key,$importer['cpubkey']);
  114. }
  115. }
  116. else {
  117. if((($importer['duplex']) && strlen($importer['cpubkey'])) || (! strlen($importer['cprvkey']))) {
  118. openssl_public_decrypt($rawkey,$final_key,$importer['cpubkey']);
  119. }
  120. else {
  121. openssl_private_decrypt($rawkey,$final_key,$importer['cprvkey']);
  122. }
  123. }
  124. logger('rino: received key : ' . $final_key);
  125. $data = aes_decrypt(hex2bin($data),$final_key);
  126. logger('rino: decrypted data: ' . $data, LOGGER_DATA);
  127. }
  128. $ret = local_delivery($importer,$data);
  129. xml_status($ret);
  130. // NOTREACHED
  131. }
  132. function dfrn_notify_content(&$a) {
  133. if(x($_GET,'dfrn_id')) {
  134. // initial communication from external contact, $direction is their direction.
  135. // If this is a duplex communication, ours will be the opposite.
  136. $dfrn_id = notags(trim($_GET['dfrn_id']));
  137. $dfrn_version = (float) $_GET['dfrn_version'];
  138. logger('dfrn_notify: new notification dfrn_id=' . $dfrn_id);
  139. $direction = (-1);
  140. if(strpos($dfrn_id,':') == 1) {
  141. $direction = intval(substr($dfrn_id,0,1));
  142. $dfrn_id = substr($dfrn_id,2);
  143. }
  144. $hash = random_string();
  145. $status = 0;
  146. $r = q("DELETE FROM `challenge` WHERE `expire` < " . intval(time()));
  147. $r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` )
  148. VALUES( '%s', '%s', %d ) ",
  149. dbesc($hash),
  150. dbesc($dfrn_id),
  151. intval(time() + 90 )
  152. );
  153. logger('dfrn_notify: challenge=' . $hash, LOGGER_DEBUG );
  154. $sql_extra = '';
  155. switch($direction) {
  156. case (-1):
  157. $sql_extra = sprintf(" AND ( `issued-id` = '%s' OR `dfrn-id` = '%s' ) ", dbesc($dfrn_id), dbesc($dfrn_id));
  158. $my_id = $dfrn_id;
  159. break;
  160. case 0:
  161. $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  162. $my_id = '1:' . $dfrn_id;
  163. break;
  164. case 1:
  165. $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  166. $my_id = '0:' . $dfrn_id;
  167. break;
  168. default:
  169. $status = 1;
  170. break; // NOTREACHED
  171. }
  172. $r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`page-flags` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  173. WHERE `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `user`.`nickname` = '%s'
  174. AND `user`.`account_expired` = 0 AND `user`.`account_removed` = 0 $sql_extra LIMIT 1",
  175. dbesc($a->argv[1])
  176. );
  177. if(! count($r))
  178. $status = 1;
  179. $challenge = '';
  180. $encrypted_id = '';
  181. $id_str = $my_id . '.' . mt_rand(1000,9999);
  182. $prv_key = trim($r[0]['prvkey']);
  183. $pub_key = trim($r[0]['pubkey']);
  184. $dplx = intval($r[0]['duplex']);
  185. if((($dplx) && (strlen($prv_key))) || ((strlen($prv_key)) && (!(strlen($pub_key))))) {
  186. openssl_private_encrypt($hash,$challenge,$prv_key);
  187. openssl_private_encrypt($id_str,$encrypted_id,$prv_key);
  188. }
  189. elseif(strlen($pub_key)) {
  190. openssl_public_encrypt($hash,$challenge,$pub_key);
  191. openssl_public_encrypt($id_str,$encrypted_id,$pub_key);
  192. }
  193. else
  194. $status = 1;
  195. $challenge = bin2hex($challenge);
  196. $encrypted_id = bin2hex($encrypted_id);
  197. $rino = ((function_exists('mcrypt_encrypt')) ? 1 : 0);
  198. $rino_enable = get_config('system','rino_encrypt');
  199. if(! $rino_enable)
  200. $rino = 0;
  201. if((($r[0]['rel']) && ($r[0]['rel'] != CONTACT_IS_SHARING)) || ($r[0]['page-flags'] == PAGE_COMMUNITY)) {
  202. $perm = 'rw';
  203. }
  204. else {
  205. $perm = 'r';
  206. }
  207. header("Content-type: text/xml");
  208. echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"
  209. . '<dfrn_notify>' . "\r\n"
  210. . "\t" . '<status>' . $status . '</status>' . "\r\n"
  211. . "\t" . '<dfrn_version>' . DFRN_PROTOCOL_VERSION . '</dfrn_version>' . "\r\n"
  212. . "\t" . '<rino>' . $rino . '</rino>' . "\r\n"
  213. . "\t" . '<perm>' . $perm . '</perm>' . "\r\n"
  214. . "\t" . '<dfrn_id>' . $encrypted_id . '</dfrn_id>' . "\r\n"
  215. . "\t" . '<challenge>' . $challenge . '</challenge>' . "\r\n"
  216. . '</dfrn_notify>' . "\r\n" ;
  217. killme();
  218. }
  219. }