]> git.mxchange.org Git - friendica-addons.git/blobdiff - jappixmini/lib.js
Preparation to make the automatic authentication work (hopefully) reliable
[friendica-addons.git] / jappixmini / lib.js
index 610a831230538acc966d516b86e2c5e691d8fc98..31302732874ea9c6bf186c4e981442f34ec2cd57 100644 (file)
@@ -1,9 +1,15 @@
+//
+// Copyright 2012 "Leberwurscht" <leberwurscht@hoegners.de>
+//
+// This file is dual-licensed under the MIT license (see MIT.txt) and the AGPL license (see jappix/COPYING).
+//
+
 function jappixmini_addon_xor(str1, str2) {
     if (str1.length != str2.length) throw "not same length";
 
-    encoded = "";
+    var encoded = "";
 
-    for (i=0; i<str1.length;i++) {
+    for (var i=0; i<str1.length;i++) {
         var a = str1.charCodeAt(i);
         var b = str2.charCodeAt(i);
         var c = a ^ b;
@@ -17,69 +23,81 @@ function jappixmini_addon_xor(str1, str2) {
 function jappixmini_addon_set_client_secret(password) {
        if (!password) return;
 
-       salt1 = "h8doCRekWto0njyQohKpdx6BN0UTyC6N";
-       salt2 = "jdX8OwFC1kWAq3s9uOyAcE8g3UNNO5t3";
+       var salt1 = "h8doCRekWto0njyQohKpdx6BN0UTyC6N";
+       var salt2 = "jdX8OwFC1kWAq3s9uOyAcE8g3UNNO5t3";
 
-       client_secret1 = str_sha1(salt1+password);
-       client_secret2 = str_sha1(salt2+password);
-       client_secret = client_secret1 + client_secret2;
+       var client_secret1 = str_sha1(salt1+password);
+       var client_secret2 = str_sha1(salt2+password);
+       var client_secret = client_secret1 + client_secret2;
 
-       setDB('jappix-mini', 'client_secret', client_secret);
+       setPersistent('jappix-mini', 'client-secret', client_secret);
        console.log("client secret set");
 }
 
-function jappixmini_addon_get_client_secret() {
-       client_secret = getDB('jappix-mini', 'client_secret');
+function jappixmini_addon_get_client_secret(callback) {
+       var client_secret = getPersistent('jappix-mini', 'client-secret');
        if (client_secret===null) {
-               div = $('<div style="position:fixed;padding:1em;background-color:#F00;color:#fff;top:50px;left:50px;">Retype your Friendica password for chatting:</div>');
-               div.append($("<br>"));
-               input = $('<input type="password">')
-               div.append(input);
-               button = $('<input type="button" value="OK">');
+               var div = document.getElementById("#jappixmini-password-query-div");
+
+               if (!div) {
+                       div = $('<div id="jappixmini-password-query-div" style="position:fixed;padding:1em;background-color:#F00;color:#fff;top:50px;left:650px;">Retype your Friendica password for chatting:<br></div>');
+
+                       var input = $('<input type="password" id="jappixmini-password-query-input">')
+                       div.append(input);
+
+                       var button = $('<input type="button" value="OK" id="jappixmini-password-query-button">');
+                       div.append(button);
+
+                       $("body").append(div);
+               }
+
                button.click(function(){
-                       password = input.val();
+                       var password = $("#jappixmini-password-query-input").val();
                        jappixmini_addon_set_client_secret(password);
                        div.remove();
+
+                       var client_secret = getPersistent('jappix-mini', 'client-secret');
+                       callback(client_secret);
                });
-               div.append(button);
-               $("body").append(div);
        }
-
-       return client_secret;
+       else {
+               callback(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 (password.length>client_secret.length-1) throw "password too long";
-       while (password.length<client_secret.length) {
-               password += "\0";
-       }
+function jappixmini_addon_encrypt_password(password, callback) {
+       jappixmini_addon_get_client_secret(function(client_secret){
+               // add \0 to password until it has the same length as secret
+               if (password.length>client_secret.length-1) throw "password too long";
+               while (password.length<client_secret.length) {
+                       password += "\0";
+               }
 
-       // xor password with secret
-       encrypted_password = jappixmini_addon_xor(client_secret, password);
+               // xor password with secret
+               var encrypted_password = jappixmini_addon_xor(client_secret, password);
 
-       encrypted_password = encodeURI(encrypted_password)
-       return encrypted_password;
+               encrypted_password = encodeURI(encrypted_password)
+               callback(encrypted_password);
+       });
 }
 
-function jappixmini_addon_decrypt_password(encrypted_password) {
+function jappixmini_addon_decrypt_password(encrypted_password, callback) {
        encrypted_password = decodeURI(encrypted_password);
 
-       client_secret = jappixmini_addon_get_client_secret();
-
-       // xor password with secret
-       password = jappixmini_addon_xor(client_secret, encrypted_password);
+       jappixmini_addon_get_client_secret(function(client_secret){
+               // xor password with secret
+               var password = jappixmini_addon_xor(client_secret, encrypted_password);
 
-        // remove \0
-       first_null = password.indexOf("\0")
-       password = password.substr(0, first_null);
+               // remove \0
+               var first_null = password.indexOf("\0")
+               if (first_null==-1) throw "Decrypted password does not contain \\0";
+               password = password.substr(0, first_null);
 
-       return password;
+               callback(password);
+       });
 }
 
-function jappixmini_manage_roster(contacts, autoapprove, autosubscribe) {
+function jappixmini_manage_roster(contacts, contacts_hash, autoapprove, autosubscribe) {
        // listen for subscriptions
        con.registerHandler('presence',function(presence){
                var type = presence.getType();
@@ -87,25 +105,125 @@ function jappixmini_manage_roster(contacts, autoapprove, autosubscribe) {
 
                var from = fullXID(getStanzaFrom(presence));
                var xid = bareXID(from);
+               var pstatus = presence.getStatus();
+
+               var approve;
+
+               if (autoapprove && contacts[xid]!==undefined) {
+                       // approve known address
+                       approve = true;
+                       console.log("Approve known Friendica contact "+xid+".");
+               }
+               else if (autoapprove && pstatus && pstatus.indexOf("Friendica")!=-1) {
+                       // Unknown address claims to be a Friendica contact.
+                       // This is probably because the other side knows our
+                       // address, but we do not know the other side yet.
+                       // But it's only a matter of time, so wait - do not
+                       // approve yet and do not annoy the user by asking.
+                       approve = false;
+                       console.log("Do not approve unknown Friendica contact "+xid+" - wait instead.");
+               }
+               else {
+                       // In all other cases, ask the user.
+                       var message = "Accept "+xid+" for chat?";
+                       if (pstatus) message += "\n\nStatus:\n"+pstatus;
+                       approve = confirm(message);
 
-               approve = true;
-               if ((!autoapprove) || contacts[xid]===undefined)
-                       approve = confirm("Accept "+xid+" for chat?");
+                       // do not ask any more
+                       if (!approve) sendSubscribe(xid, "unsubscribed");
+               }
 
                if (approve) {
-                       acceptSubscribe(xid, contacts[xid]);
-                       console.log("Accepted "+xid+" for chat.");
+                       var name = contacts[xid];
+                       if (!name) name = xid;
+
+                       acceptSubscribe(xid, name);
+                       console.log("Accepted "+xid+" ("+name+") for chat.");
                }
        });
 
        // autosubscribe
-       if (autosubscribe) {
-               for (i=0; i<contacts.length; i++) {
-                       xid = contacts[i];
-                       sendSubscribe(xid, "subscribe");
-                       console.log("Subscribed to "+xid);
+       if (!autosubscribe) return;
+
+       var stored_hash = getPersistent("jappix-mini", "contacts-hash");
+       var contacts_changed = (stored_hash != contacts_hash); // stored_hash gets updated later if everything was successful
+       if (!contacts_changed) return;
+
+       console.log("Start autosubscribe.");
+
+       var get_roster = new JSJaCIQ();
+       get_roster.setType('get');
+       get_roster.setQuery(NS_ROSTER);
+
+       con.send(get_roster, function(iq){
+               var handleXML = iq.getQuery();
+
+               // filter out contacts that are already in the roster
+               $(handleXML).find('item').each(function() {
+                        var node = $(this);
+                       var xid = node.attr("jid");
+                       var name = node.attr("name");
+                       var subscription = node.attr("subscription");
+
+                       // ignore accounts that are not in the list
+                       if (contacts[xid]===undefined) return;
+
+                       // add to Friendica group or change name if necessary
+                       var groups = [];
+                       var group_missing = false;
+                       node.find('group').each(function() {
+                               var group_text = $(this).text();
+                               if (group_text) groups.push(group_text);
+                       });
+                       if ($.inArray("Friendica", groups)==-1) {
+                               group_missing = true;
+                               groups.push("Friendica");
+                       }
+
+                       if (group_missing || name!=contacts[xid]) {
+                               sendRoster(xid, null, contacts[xid], groups);
+                               console.log("Added "+xid+" to Friendica group and set name to "+contacts[xid]+".");
+                       }
+
+                       // authorize if necessary
+                       if (subscription=="to") {
+                               sendSubscribe(xid, 'subscribed');
+                               console.log("Authorized "+xid+" automatically.");
+                       }
+
+                       // remove from list
+                       delete contacts[xid];
+               });
+
+               // go through remaining contacts
+               for (var xid in contacts) {if(!contacts.hasOwnProperty(xid)) continue;
+                       // subscribe
+                       var presence = new JSJaCPresence();
+                       presence.setTo(xid);
+                       presence.setType("subscribe");
+
+                       // must contain the word "~Friendica" so the other side knows
+                       // how to handle this
+                       presence.setStatus("I'm "+MINI_NICKNAME+" from ~Friendica.\n[machine-generated message]");
+
+                       con.send(presence);
+                       console.log("Subscribed to "+xid+" automatically.");
+
+                       // add to roster
+                       var iq = new JSJaCIQ();
+                       iq.setType('set');
+                       var iqQuery = iq.setQuery(NS_ROSTER);
+                       var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid}));
+                       item.setAttribute('name', contacts[xid]);
+                       item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, "Friendica"));
+                       con.send(iq);
+                       console.log("Added "+xid+" ("+contacts[xid]+") to roster.");
                }
-       }
+
+               setPersistent("jappix-mini", "contacts-hash", contacts_hash);
+               console.log("Autosubscribe done.");
+       });
+
 }
 
 function jappixmini_addon_subscribe() {
@@ -114,31 +232,50 @@ function jappixmini_addon_subscribe() {
                return;
         }
 
-       xid = prompt("Jabber address");
+       var xid = prompt("Jabber address");
        sendSubscribe(xid, "subscribe");
 }
 
-function jappixmini_addon_start(server, username, bosh, encrypted, password, nickname) {
-    // decrypt password
+function jappixmini_addon_start(server, username, proxy, bosh, encrypted, password, nickname, contacts, contacts_hash, autoapprove, autosubscribe, groupchats) {
+    var handler = function(password){
+        // check if settings have changed, reinitialize jappix mini if this is the case
+        var settings_identifier = str_sha1(server);
+        settings_identifier += str_sha1(username);
+        settings_identifier += str_sha1(proxy);
+        settings_identifier += str_sha1(bosh);
+        settings_identifier += str_sha1(password);
+        settings_identifier += str_sha1(nickname);
+
+        var saved_identifier = getDB("jappix-mini", "settings-identifier");
+        if (saved_identifier != settings_identifier) {
+            disconnectMini();
+            removeDB('jappix-mini', 'dom');
+            removePersistent("jappix-mini", "contacts-hash");
+        }
+        setDB("jappix-mini", "settings-identifier", settings_identifier);
+
+        // set HOST_BOSH
+        if (proxy)
+            HOST_BOSH = proxy+"?host_bosh="+encodeURI(bosh);
+        else
+            HOST_BOSH = bosh;
+
+        // start jappix mini
+       MINI_GROUPCHATS = groupchats;
+        MINI_NICKNAME = nickname;
+        LOCK_HOST = "off";
+        launchMini(true, false, server, username, password);
+
+        // increase priority over other Jabber clients - does not seem to work?
+        var priority = 101;
+        presenceMini(null,null,priority);
+
+        jappixmini_manage_roster(contacts, contacts_hash, autoapprove, autosubscribe)
+    }
+
+    // decrypt password if necessary
     if (encrypted)
-        password = jappixmini_addon_decrypt_password(password);
-
-    // check if settings have changed, reinitialize jappix mini if this is the case
-    settings_identifier = str_sha1(server);
-    settings_identifier += str_sha1(username);
-    settings_identifier += str_sha1(bosh);
-    settings_identifier += str_sha1(password);
-    settings_identifier += str_sha1(nickname);
-
-    saved_identifier = getDB("jappix-mini", "settings_identifier");
-    if (saved_identifier != settings_identifier) removeDB('jappix-mini', 'dom');
-    setDB("jappix-mini", "settings_identifier", settings_identifier);
-
-    // set bosh host
-    if (bosh)
-        HOST_BOSH = HOST_BOSH+"?host_bosh="+encodeURI(bosh);
-
-    // start jappix mini
-    MINI_NICKNAME = nickname;
-    launchMini(true, false, server, username, password);
+        jappixmini_addon_decrypt_password(password, handler);
+    else
+        handler(password);
 }