diff --git a/jappixmini/README b/jappixmini/README new file mode 100644 index 000000000..2ef7c2f1e --- /dev/null +++ b/jappixmini/README @@ -0,0 +1,23 @@ +Jappix Mini Plugin +================== + +This quick-and-dirty addon allows you to add a Jabber-based, Facebook-like chat +to Friendica. It uses Jappix Mini. + +It is necessary to use a BOSH proxy - so to use this plugin, you need to know the +address of a BOSH proxy that works with your account. + +The addon has an experimental autosubscribe and autosuggest functionality which tries +to add your Friendica contacts to your roster automatically. + +Installation +------------ + +Jappix Mini (AGPL license) is not distributed with this addon. You need to +install it manually: + +* Download latest zip file named friendica-addon-* from + https://github.com/Leberwurscht/jappix-friendica-addon/tags and place the zip file + in the addon folder. Make sure to name it 'jappix.zip' - the download link required + by the AGPL points there. +* Unpack the zip file, rename the folder to 'jappix'. Do not delete jappix.zip. diff --git a/jappixmini/jappixmini.php b/jappixmini/jappixmini.php new file mode 100644 index 000000000..889594486 --- /dev/null +++ b/jappixmini/jappixmini.php @@ -0,0 +1,382 @@ +You need to install the Jappix application, adapted for Friendica (see README).

'; + } + else if (!file_exists("addon/jappixmini/jappix.zip")) { + $o .= '

The source archive jappix.zip does not exist. This is probably a violation of the Jappix License (see README).

'; + } +} + +function jappixmini_plugin_admin_post(&$a) { +} + +function jappixmini_module() {} +function jappixmini_init(&$a) { + // Here, other friendica sites can fetch the jabber address of local users. + // Because we do not want to publish the addresses publicly, they are encrypted so + // that only contacts can read it. + $encrypt_for = $_REQUEST["encrypt_for"]; + if ($encrypt_for) { + $r = q("SELECT * FROM `contact` WHERE LENGTH(`pubkey`) AND `dfrn-id` = '%s' LIMIT 1", + dbesc($encrypt_for) + ); + if (!count($r)) killme(); + + // get public key to encrypt address + $pubkey = $r[0]['pubkey']; + + // get jabber address + $uid = $r[0]['uid']; + $username = get_pconfig($uid, 'jappixmini', 'username'); + if (!$username) killme(); + $server = get_pconfig($uid, 'jappixmini', 'server'); + if (!$server) killme(); + + $address = $username."@".$server; + + // encrypt address + $encrypted = ""; + openssl_public_encrypt($address,$encrypted,$pubkey); + + // calculate hex representation of encrypted address + $hex = bin2hex($encrypted); + + // construct answer + $answer = Array("status"=>"ok", "encrypted_address"=>$hex); + + // return answer as json + echo json_encode($answer); + killme(); + } + + // If we have only a private key, other site sends encrypted request, we answer unencrypted. + $encrypted_for = $_REQUEST["encrypted_for"]; + if (!$encrypted_for) killme(); + + $encrypted_request_hex = $_REQUEST["encrypted_request"]; + if (!$encrypted_request_hex) killme(); + $encrypted_request = hex2bin($encrypted_request_hex); + + $r = q("SELECT * FROM `contact` WHERE LENGTH(`prvkey`) AND `issued-id` = '%s' LIMIT 1", + dbesc($encrypted_for) + ); + if (!count($r)) killme(); + + // decrypt request, validate it + $prvkey = $r[0]['prvkey']; + $decrypted_request = ""; + openssl_private_decrypt($encrypted_request, $decrypted_request, $prvkey); + + if ($decrypted_request!=$encrypted_for) killme(); + + // get jabber address + $uid = $r[0]['uid']; + $username = get_pconfig($uid, 'jappixmini', 'username'); + if (!$username) killme(); + $server = get_pconfig($uid, 'jappixmini', 'server'); + if (!$server) killme(); + + $address = $username."@".$server; + + // construct answer + $answer = Array("status"=>"ok", "address"=>$address); + + // return answer as json + echo json_encode($answer); + killme(); +} + +function jappixmini_settings(&$a, &$s) { + $username = get_pconfig(local_user(),'jappixmini','username'); + $username = htmlentities($username); + $server = get_pconfig(local_user(),'jappixmini','server'); + $server = htmlentities($server); + $bosh = get_pconfig(local_user(),'jappixmini','bosh'); + $bosh = htmlentities($bosh); + $encrypted_password = get_pconfig(local_user(),'jappixmini','encrypted-password'); + $autosubscribe = get_pconfig(local_user(),'jappixmini','autosubscribe'); + $autosubscribe = intval($autosubscribe) ? ' checked="checked"' : ''; + $autoapprove = get_pconfig(local_user(),'jappixmini','autoapprove'); + $autoapprove = intval($autoapprove) ? ' checked="checked"' : ''; + $activate = get_pconfig(local_user(),'jappixmini','activate'); + $activate = intval($activate) ? ' checked="checked"' : ''; + + $s .= '
'; + $s .= '

Jappix Mini addon settings

'; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $onchange = "document.getElementById('jappixmini-encrypted-password').value = jappixmini_addon_encrypt_password(document.getElementById('jappixmini-password').value);"; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= ' '; + $s .= '
'; + $s .= ''; + $s .= '
'; + + $a->page['htmlhead'] .= ""; +} + +function jappixmini_settings_post(&$a,&$b) { + if(! local_user()) return; + + if($_POST['jappixmini-submit']) { + set_pconfig(local_user(),'jappixmini','username',trim($b['jappixmini-username'])); + set_pconfig(local_user(),'jappixmini','server',trim($b['jappixmini-server'])); + set_pconfig(local_user(),'jappixmini','bosh',trim($b['jappixmini-bosh'])); + set_pconfig(local_user(),'jappixmini','encrypted-password',trim($b['jappixmini-encrypted-password'])); + set_pconfig(local_user(),'jappixmini','autosubscribe',intval($b['jappixmini-autosubscribe'])); + set_pconfig(local_user(),'jappixmini','autoapprove',intval($b['jappixmini-autoapprove'])); + set_pconfig(local_user(),'jappixmini','activate',intval($b['jappixmini-activate'])); + info( 'Jappix Mini settings saved.' ); + + if (intval($b['jappixmini-purge'])) { + $uid = local_user(); + q("DELETE FROM `pconfig` WHERE `uid`=$uid AND `cat`='jappixmini' and `k` LIKE 'id%%'"); + info( 'List of addresses purged.' ); + } + } +} + +function jappixmini_script(&$a,&$s) { + if(! local_user()) return; + + $activate = get_pconfig(local_user(),'jappixmini','activate'); + if (!$activate) return; + + $a->page['htmlhead'] .= ''."\r\n"; + $a->page['htmlhead'] .= ''."\r\n"; + + $a->page['htmlhead'] .= ''."\r\n"; + $a->page['htmlhead'] .= ''."\r\n"; + + $a->page['htmlhead'] .= ''."\r\n"; + + $username = get_pconfig(local_user(),'jappixmini','username'); + $username = str_replace("'", "\\'", $username); + $server = get_pconfig(local_user(),'jappixmini','server'); + $server = str_replace("'", "\\'", $server); + $bosh = get_pconfig(local_user(),'jappixmini','bosh'); + $bosh = str_replace("'", "\\'", $bosh); + $encrypted_password = get_pconfig(local_user(),'jappixmini','encrypted-password'); + $encrypted_password = str_replace("'", "\\'", $encrypted_password); + + $autoapprove = get_pconfig(local_user(),'jappixmini','autoapprove'); + $autoapprove = intval($autoapprove); + $autosubscribe = get_pconfig(local_user(),'jappixmini','autosubscribe'); + $autosubscribe = intval($autosubscribe); + + // get a list of jabber accounts of the contacts + $contacts = Array(); + $uid = local_user(); + $rows = q("SELECT `v` FROM `pconfig` WHERE `uid`=$uid AND `cat`='jappixmini' and `k` LIKE 'id%%'"); + foreach ($rows as $row) { + $value = $row['v']; + $pos = strpos($value, ":"); + $address = substr($value, $pos+1); + $contacts[] = $address; + } + $contacts_json = json_encode($contacts); + + $a->page['htmlhead'] .= ""; + + return; +} + +function jappixmini_login(&$a, &$o) { + // save hash of password using setDB + $o = str_replace("
status != "ok") continue; + + $encrypted_address_hex = $answer->encrypted_address; + if (!$encrypted_address_hex) continue; + $encrypted_address = hex2bin($encrypted_address_hex); + + $decrypted_address = ""; + openssl_private_decrypt($encrypted_address, $decrypted_address, $prvkey); + if (!$decrypted_address) continue; + + $address = $decrypted_address; + } else if ($pubkey) { + $encrypted_request = ""; + openssl_public_encrypt($dfrn_id, $encrypted_request, $pubkey); + if (!$encrypted_request) continue; + $encrypted_request_hex = bin2hex($encrypted_request); + + $retrieval_address = $base."?encrypted_for=".urlencode($dfrn_id)."&encrypted_request=".urlencode($encrypted_request_hex); + + $answer_json = fetch_url($retrieval_address); + $answer = json_decode($answer_json); + if ($answer->status != "ok") continue; + + $address = $answer->address; + if (!$address) continue; + } + + // save address + set_pconfig($uid, "jappixmini", "id:$dfrn_id", "$now:$address"); + } + } +} + +function jappixmini_download_source(&$a,&$b) { + $b .= '

Jappix Mini

'; + $b .= '

This site uses Jappix Mini by the Jappix authors, which is distributed under the terms of the GNU Affero General Public License.

'; + $b .= '

You can download the source code.

'; +} diff --git a/jappixmini/lib.js b/jappixmini/lib.js new file mode 100644 index 000000000..dd95695f1 --- /dev/null +++ b/jappixmini/lib.js @@ -0,0 +1,120 @@ +function jappixmini_addon_xor(str1, str2) { + if (str1.length != str2.length) throw "not same length"; + + encoded = ""; + + for (i=0; iReintroduce your Friendica password for chatting:
'); + div.append($("
")); + input = $('') + div.append(input); + button = $(''); + button.click(function(){ + password = input.val(); + jappixmini_addon_set_client_secret(password); + div.remove(); + }); + div.append(button); + $("body").append(div); + } + + return client_secret; +} + +function jappixmini_addon_encrypt_password(password) { + client_secret = jappixmini_addon_get_client_secret(); + + // add \0 to password until it has the same length as secret + if (client_secret.length