<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>images/pic.png</filename>
    </added>
    <added>
      <filename>scripts/README.txt</filename>
    </added>
    <added>
      <filename>scripts/create_cert.js</filename>
    </added>
    <added>
      <filename>scripts/setup.cmd</filename>
    </added>
    <added>
      <filename>scripts/socialvpn</filename>
    </added>
    <added>
      <filename>scripts/stop_svpn.cmd</filename>
    </added>
    <added>
      <filename>src/SVPNTool.cs</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,28 +2,18 @@ SocialVPN
 
 Building SocialVPN
 ==================
-NAnt build tool is required
+NAnt build tool is required.
 
-For debian-based systems:
-apt-get install nant uml-utilities
+For Debian-based systems:
+apt-get install nant uml-utilities resolvconf curl
 
 For RedHat-based systems:
-yum install nant uml-utilities
-
-cd src/
+yum install nant uml-utilities curl
 
 To compile, run:
 
 nant
 
-To run NUnit test, run:
-
-nant test
-
-To clean, run
-
-nant clean
-
 Running SocialVPN
 =================
 After compiling, all files to run SocialVPN are saved in bin directory.
@@ -36,32 +26,22 @@ For Windows XP, run the start_win.cmd file
 
 For Windows Vista, right-click on start_win.cmd and &quot;Run as administrator&quot;
 
-For Linux, see instructions below to run as normal user (much safer)
-
-To run SocialVPN as non-root on Linux
--------------------------------------
+For Linux, run the following commands:
 
-Run following commands as root:
+whoami &gt; user.txt
 
-chmod 666 /dev/net/tun/
+su root
 
-tunctl -u &quot;your username&quot; -t tapipop
-
-To find your username run the whoami command
-
-Then run:
-
-./start_linux.sh email pcid &quot;name&quot;
+./start_linux.sh
 
 Accessing SocialVPN Web Interface
 =================================
-SocialVPN can be managed through a Web browser or the wget command line
-utility. The start_win.cmd and the start_win.sh files contains the port
-number used to access the interface. The default port number is 58888.
+SocialVPN can be managed through a Web browser or the SVPNTool.exe command 
+line utility. The start_win.cmd and the start_win.sh files contains the 
+port number used to access the interface. The default port number is 58888.
 
 Point your browser to http://127.0.0.1:58888/
 
-
 Dependencies:
 =============
 SocialVPN is built on top of two other projects:
@@ -74,14 +54,6 @@ SocialVPN is built on top of two other projects:
 All packaged binaries found under lib and bin directories are compiled from
 these two projects.
 
-Troubleshooting:
-================
-The libtuntap.so and libtuntap.dll files are platform-dependent, they have to
-be compiled for your platform. Under the bin directory there are two other
-libtuntap.so files on for 32-bit systems (libtuntap.so_32) and another for
-64-bit systems (libtuntap.so_64). Rename one of these files to libtuntap.so
-depending on your architecture. Windows 64-bit will be available soon.
-
 Questions/Comments:
 ===================
 Contact Pierre St Juste &lt;ptony82@ufl.edu&gt; for any questions.</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.Coordinate.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.Dht.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.IPAddresses.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.Security.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.XmlRpc.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/Brunet.dll</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>lib/ManagedIpopNode.dll</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,6 @@
     &lt;copy todir=&quot;./lib&quot; failonerror=&quot;false&quot;&gt;
       &lt;fileset basedir=&quot;${ipop.dir}/lib/&quot;&gt;
         &lt;include name=&quot;*.dll&quot; /&gt;
-        &lt;include name=&quot;libtuntap.so&quot; /&gt;
       &lt;/fileset&gt;
     &lt;/copy&gt;
 </diff>
      <filename>socialvpn.build</filename>
    </modified>
    <modified>
      <diff>@@ -129,7 +129,7 @@ namespace SocialVPN {
     public void Stop() {
       _running = false;
       _listener.Stop();
-      _runner.Join();
+      _runner.Abort();
     }
 
     /**
@@ -147,15 +147,14 @@ namespace SocialVPN {
           }
           Console.WriteLine(e);
         }
-
         HttpListenerRequest request = context.Request;
         HttpListenerResponse response = context.Response;
         string responseString = String.Empty;
+        byte[] buffer = null;
         response.ContentType = &quot;text/xml&quot;;
 
         // Process api post request from the Javascript interface
-        if (request.RawUrl == &quot;/api&quot;)
-        {
+        if (request.RawUrl == &quot;/api&quot;) {
           StreamReader reader = new StreamReader(request.InputStream,
                                                  request.ContentEncoding);
 
@@ -167,37 +166,33 @@ namespace SocialVPN {
                               DateTime.Now.TimeOfDay, postData));
           responseString = Process(SocialUtils.DecodeUrl(postData));
         }
-        else if (request.RawUrl.StartsWith(&quot;/getapi&quot;))
-        {
-          if(request.RawUrl.Length &gt; 9) {
-            string getData = request.RawUrl.Substring(8);
-            ProtocolLog.WriteIf(SocialLog.SVPNLog, String.Format(
-                                &quot;HTTP API: {0} {1}&quot;,
-                                DateTime.Now.TimeOfDay, getData));
-            responseString = Process(SocialUtils.DecodeUrl(getData));
-          }
-        }
         // Cross-domain request made by Flash clients
-        else if (request.RawUrl == &quot;/crossdomain.xml&quot;)
-        {
+        else if (request.RawUrl == &quot;/crossdomain.xml&quot;) {
           responseString = CrossDomainXML;
         }
-        else if (request.RawUrl == &quot;/socialvpn.js&quot;)
-        {
-          using (StreamReader text = new StreamReader(&quot;socialvpn.js&quot;))
-          {
+        else if (request.RawUrl == &quot;/socialvpn.js&quot;) {
+          using (StreamReader text = new StreamReader(&quot;socialvpn.js&quot;)) {
             responseString = text.ReadToEnd();
           }
           response.ContentType = &quot;text/javascript&quot;;
         }
-        else if (request.RawUrl == &quot;/socialvpn.css&quot;)
-        {
-          using (StreamReader text = new StreamReader(&quot;socialvpn.css&quot;))
-          {
+        else if (request.RawUrl == &quot;/socialvpn.css&quot;) {
+          using (StreamReader text = new StreamReader(&quot;socialvpn.css&quot;)) {
             responseString = text.ReadToEnd();
           }
           response.ContentType = &quot;text/css&quot;;
         }
+        else if (request.RawUrl == &quot;/pic.svg&quot;) {
+          using (StreamReader text = new StreamReader(&quot;pic.svg&quot;)) {
+            responseString = text.ReadToEnd();
+          }
+          response.ContentType = &quot;image/svg+xml&quot;;
+        }
+        else if (request.RawUrl == &quot;/pic.png&quot;) {
+          responseString = null;
+          buffer = SocialUtils.ReadFileBytes(&quot;pic.png&quot;);
+          response.ContentType = &quot;image/png&quot;;
+        }
         // Return html content for page display
         else
         {
@@ -205,7 +200,9 @@ namespace SocialVPN {
           response.ContentType = &quot;text/html&quot;;
         }
 
-        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
+        if ( buffer == null &amp;&amp; responseString != null) {
+          buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
+        }
         response.ContentLength64 = buffer.Length;
         response.AddHeader(&quot;Cache-Control&quot;, &quot;No-cache&quot;);
         System.IO.Stream output = response.OutputStream;</diff>
      <filename>src/HttpInterface.cs</filename>
    </modified>
    <modified>
      <diff>@@ -30,13 +30,19 @@ using NUnit.Framework;
 
 namespace SocialVPN {
 
+  /**
+   * Definition of QueueItem for Blocking Queue.
+   */ 
   public class QueueItem {
 
     public enum Actions {
-      AddCert,
+      AddCertTrue,
+      AddCertFalse,
+      DhtAdd,
       Sync,
       Process,
-      HeartBeat
+      HeartBeat,
+      Publish
     }
 
     public Actions Action;
@@ -56,6 +62,11 @@ namespace SocialVPN {
   public class SocialConnectionManager {
 
     /**
+     * The common delimiter for user input
+     */
+    public const char DELIM = ',';
+
+    /**
      * The node which accepts peers based on certificates.
      */
     protected readonly SocialNode _snode;
@@ -91,9 +102,14 @@ namespace SocialVPN {
     protected DateTime _last_update, _last_publish, _last_store, _last_ping;
 
     /**
-     * Interval for periodic operations
+     * Global Dht Access.
      */
-    protected readonly TimeSpan _interval;
+    protected bool _global_access;
+
+    /**
+     * The counter for heartbeat event.
+     */
+    protected int _heartbeat_counter;
 
     /**
      * Constructor.
@@ -115,11 +131,15 @@ namespace SocialVPN {
       _queue = queue;
       _main_thread = new Thread(Start);
       _main_thread.Start();
-      _interval = new TimeSpan(0,5,0);
-      _last_update = DateTime.Now - _interval;
+      _last_update = DateTime.MinValue;
       _last_store = _last_update;
       _last_publish = _last_update;
       _last_ping = _last_update;
+      _heartbeat_counter = 0;
+    }
+
+    public void SetGlobalAccess(string global_access) {
+      _global_access = (global_access == &quot;on&quot;);
     }
 
     public void Start() {
@@ -128,11 +148,19 @@ namespace SocialVPN {
       }
 
       while(true) {
-        QueueItem item = (QueueItem)_queue.Dequeue();
         try {
+          QueueItem item = (QueueItem)_queue.Dequeue();
           switch(item.Action) {
-            case QueueItem.Actions.AddCert:
-              _snode.AddCertificate((byte[]) item.Obj);      
+            case QueueItem.Actions.AddCertTrue:
+              _snode.AddCertificate((byte[]) item.Obj, true);      
+              break;
+
+            case QueueItem.Actions.AddCertFalse:
+              _snode.AddCertificate((byte[]) item.Obj, false);      
+              break;
+
+            case QueueItem.Actions.DhtAdd:
+              _snode.AddDhtFriend((string) item.Obj, _global_access);      
               break;
 
             case QueueItem.Actions.Sync:
@@ -147,25 +175,43 @@ namespace SocialVPN {
               HeartBeatAction();
               break;
 
+            case QueueItem.Actions.Publish:
+              _snode.PublishCertificate();
+              break;
+
             default:
               break;
           }
         } catch (Exception e) {
           ProtocolLog.WriteIf(SocialLog.SVPNLog, e.Message);
           ProtocolLog.WriteIf(SocialLog.SVPNLog, 
-                              String.Format(&quot;HEARTBEAT ACTION FAILURE: {0}&quot;,
+                              String.Format(&quot;QUEUE ACTION FAILURE: {0}&quot;,
                               DateTime.Now.TimeOfDay));
         }
       }
     }
 
+    public void Stop() {
+      _http.Stop();
+      _main_thread.Abort();
+      Environment.Exit(1);
+    }
+
     /**
      * Heartbeat event handler.
      * @param obj the default object.
      * @param eargs the event arguments.
      */
     public void HeartBeatHandler(Object obj, EventArgs eargs) {
-      _queue.Enqueue(new QueueItem(QueueItem.Actions.HeartBeat, obj));
+      if( _heartbeat_counter % 60 == 0) {
+        if(!_snode.CertPublished) {
+          _queue.Enqueue(new QueueItem(QueueItem.Actions.Publish, null));
+        }
+        else {
+          _queue.Enqueue(new QueueItem(QueueItem.Actions.HeartBeat, obj));
+        }
+      }
+      _heartbeat_counter++;
     }
 
     /**
@@ -173,23 +219,21 @@ namespace SocialVPN {
      * @param obj the default object.
      */
     public void HeartBeatAction(){
-      if(!_snode.Dht.Online) {
-        return;
-      }
       DateTime now = DateTime.Now;
-      if((now - _last_update).Minutes &gt;= 5 ) {
+      DateTime min = DateTime.MinValue;
+      if(_last_update == min || (now - _last_update).Minutes &gt;= 5 ) {
         UpdateFriends(null);
         _last_update = now;
       }
-      if((now - _last_store).Minutes &gt;= 5 ) {
+      if(_last_store == min || (now - _last_store).Minutes &gt;= 30 ) {
         _snp.StoreFingerprint();
         _last_store = now;
       }
-      if((now - _last_publish).Minutes &gt;= 5 ) {
+      if(_last_publish == min || (now - _last_publish).Minutes &gt;= 30 ) {
         _snode.PublishCertificate();
         _last_publish = now;
       }
-      if((now - _last_ping).Minutes &gt;= 5 ) {
+      if(_last_ping == min || (now - _last_ping).Minutes &gt;= 1 ) {
         _srh.PingFriends();
         _last_ping = now;
       }
@@ -201,7 +245,7 @@ namespace SocialVPN {
      * @param eargs the event arguments.
      */
     public void ProcessHandler(Object obj, EventArgs eargs) {
-      ((Dictionary&lt;string, string&gt;)obj)[&quot;response&quot;] = _snode.GetState();
+      ((Dictionary&lt;string, string&gt;)obj)[&quot;response&quot;] = _snode.GetState(false);
       // Allows main thread to run request, main thread does all the work
       _queue.Enqueue(new QueueItem(QueueItem.Actions.Process, obj));
     }
@@ -215,11 +259,11 @@ namespace SocialVPN {
       if(request.ContainsKey(&quot;m&quot;)) {
         switch(request[&quot;m&quot;]) {
           case &quot;add&quot;:
-            _snp.AddFriends(request[&quot;uids&quot;]);
+            _snp.AddFriends(request[&quot;uids&quot;].Split(DELIM));
             break;
 
           case &quot;addfpr&quot;:
-            _snp.AddFingerprints(request[&quot;fprs&quot;]);
+            _snp.AddFingerprints(request[&quot;fprs&quot;].Split(DELIM));
             break;
 
           case &quot;addcert&quot;:
@@ -238,12 +282,22 @@ namespace SocialVPN {
             BlockFriends(request[&quot;fprs&quot;]);
             break;
 
+          case &quot;delete&quot;:
+            DeleteFriends(request[&quot;fprs&quot;]);
+            break;
+
+          case &quot;global&quot;:
+            SetGlobalAccess(request[&quot;access&quot;]);
+            break;
+
           default:
             break;
         }
         if(request[&quot;m&quot;] == &quot;add&quot; || request[&quot;m&quot;] == &quot;addfpr&quot; || 
             request[&quot;m&quot;] == &quot;addcert&quot;) {
-          UpdateFriends(null);
+          if(_snode.CertPublished) {
+            UpdateFriends(null);
+          }
         }
       }
     }
@@ -266,7 +320,7 @@ namespace SocialVPN {
      * @param fprlist a list of fingerprints.
      */
     protected void AllowFriends(string fprlist) {
-      string[] fprs = fprlist.Split('\n');
+      string[] fprs = fprlist.Split(DELIM);
       foreach(string fpr in fprs) {
         _snode.AddFriend(fpr);
       }
@@ -277,7 +331,7 @@ namespace SocialVPN {
      * @param fprlist a list of fingerprints.
      */
     protected void BlockFriends(string fprlist) {
-      string[] fprs = fprlist.Split('\n');
+      string[] fprs = fprlist.Split(DELIM);
       foreach(string fpr in fprs) {
         _snode.RemoveFriend(fpr);
       }
@@ -290,11 +344,22 @@ namespace SocialVPN {
     protected void AddFriends(string[] uids) {
       List&lt;byte[]&gt; certificates = _snp.GetCertificates(uids);
       foreach(byte[] cert in certificates) {
-        _snode.AddCertificate(cert);
+        _snode.AddCertificate(cert, true);
       }
       List&lt;string&gt; fingerprints = _snp.GetFingerprints(uids);
       foreach(string fpr in fingerprints) {
-        _snode.AddDhtFriend(fpr);
+        _snode.AddDhtFriend(fpr, true);
+      }
+    }
+
+    /**
+     * Delete a list of fingerprints seperated by newline.
+     * @param fprlist a list of fingerprints.
+     */
+    protected void DeleteFriends(string fprlist) {
+      string[] fprs = fprlist.Split(DELIM);
+      foreach(string fpr in fprs) {
+        _snode.DeleteFriend(fpr);
       }
     }
   }</diff>
      <filename>src/SocialConnectionManager.cs</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 using System;
+using System.Collections;
 using System.Collections.Generic;
+using System.Text;
 
 using Brunet;
 using Brunet.DistributedServices;
@@ -60,11 +62,6 @@ namespace SocialVPN {
     protected readonly Dictionary&lt;string, ISocialNetwork&gt; _networks;
 
     /**
-     * Location of the certificates directory.
-     */
-    protected readonly string _cert_dir;
-
-    /**
      * List of friends manually added.
      */
     protected readonly List&lt;string&gt; _friends;
@@ -85,19 +82,17 @@ namespace SocialVPN {
      * @param user the local user object.
      * @param certData the local certificate data.
      */
-    public SocialNetworkProvider(IDht dht, SocialUser user, byte[] certData,
-                                 string certDir) {
+    public SocialNetworkProvider(IDht dht, SocialUser user, byte[] certData) {
       _local_user = user;
       _dht = dht;
       _providers = new Dictionary&lt;string, IProvider&gt;();
       _networks = new Dictionary&lt;string,ISocialNetwork&gt;();
       _local_cert_data = certData;
-      _cert_dir = certDir;
       _friends = new List&lt;string&gt;();
+      _friends.Add(_local_user.Uid);
       _fingerprints = new List&lt;string&gt;();
       _certificates = new List&lt;byte[]&gt;();
       RegisterBackends();
-      LoadCertificates();
     }
 
     /**
@@ -181,7 +176,7 @@ namespace SocialVPN {
           continue;
         }
         foreach(string fpr in tmp_fprs) {
-          if(fpr.Length &gt; 45 || !fingerprints.Contains(fpr)) {
+          if(fpr.Length &gt;= 45 || !fingerprints.Contains(fpr)) {
             fingerprints.Add(fpr);
           }
         }
@@ -192,6 +187,21 @@ namespace SocialVPN {
           fingerprints.Add(fpr);
         }
       }
+
+      // Get friends from DHT
+      foreach(string friend in _friends) {
+        byte[] key_bytes = Encoding.UTF8.GetBytes(friend);
+        MemBlock keyb = MemBlock.Reference(key_bytes);
+        Hashtable[] results = _dht.Get(keyb);
+        foreach(Hashtable result in results) {
+          byte[] fpr_data = (byte[]) result[&quot;value&quot;];
+          string fpr = Encoding.UTF8.GetString(fpr_data);
+          if(!fingerprints.Contains(fpr)) {
+            fingerprints.Add(fpr);
+          }
+        }
+        
+      }
       return fingerprints;
     }
 
@@ -240,6 +250,25 @@ namespace SocialVPN {
       foreach(IProvider provider in _providers.Values) {
         success = (success || provider.StoreFingerprint());
       }
+      // Store in the DHT by default
+      byte[] key_bytes = Encoding.UTF8.GetBytes(_local_user.Uid);
+      MemBlock keyb = MemBlock.Reference(key_bytes);
+      byte[] value_bytes = Encoding.UTF8.GetBytes(_local_user.DhtKey);
+      MemBlock valueb = MemBlock.Reference(value_bytes);
+      if(_dht.Put(keyb, valueb, SocialNode.DHTTTL)) {
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, 
+                          String.Format(&quot;STORE UID SUCCESS: {0} {1} {2}&quot;,
+                          DateTime.Now.TimeOfDay,_local_user.DhtKey,
+                          _local_user.Uid));
+
+      }
+      else {
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, 
+                          String.Format(&quot;STORE UID FAILURE: {0} {1} {2}&quot;,
+                          DateTime.Now.TimeOfDay,_local_user.DhtKey,
+                          _local_user.Uid));
+      }
+      
       return success;
     }
 
@@ -259,35 +288,13 @@ namespace SocialVPN {
     }
 
     /**
-     * Loads certificates from the file system.
+     * Adds a list of fingerprints.
+     * @param fprs a list of fingerprints.
      */
-    protected void LoadCertificates() {
-      string[] cert_files = null;
-      try {
-        cert_files = System.IO.Directory.GetFiles(_cert_dir);
-      } catch (Exception e) {
-        ProtocolLog.WriteIf(SocialLog.SVPNLog, e.Message);
-        ProtocolLog.WriteIf(SocialLog.SVPNLog, &quot;LOAD CERTIFICATES FAILURE&quot;);
-      }
-      foreach(string cert_file in cert_files) {
-        byte[] cert_data = SocialUtils.ReadFileBytes(cert_file);
-        _certificates.Add(cert_data);
-      }
-    }
-
-    /**
-     * Adds a list of fingerprints seperated by newline.
-     * @param fprlist a list of fingerprints.
-     */
-    public void AddFingerprints(string fprlist) {
-      string[] fprs = fprlist.Split('\n');
+    public void AddFingerprints(string[] fprs) {
       foreach(string fpr in fprs) {
-        string tmp_fpr = null;
-        if(!fpr.Contains(&quot;=&quot;)) {
-          tmp_fpr = fpr + &quot;=&quot;;
-        }
-        if(!_fingerprints.Contains(tmp_fpr)) {
-          _fingerprints.Add(tmp_fpr);
+        if(!_fingerprints.Contains(fpr)) {
+          _fingerprints.Add(fpr);
         }
       }
     }
@@ -305,11 +312,10 @@ namespace SocialVPN {
     }
 
     /**
-     * Adds a list of friends seperated by newline.
-     * @param friendlist a list of friends unique identifiers.
+     * Adds a list of friends.
+     * @param friends a list of friends unique identifiers.
      */
-    public void AddFriends(string friendlist) {
-      string[] friends = friendlist.Split('\n');
+    public void AddFriends(string[] friends) {
       foreach(string friend in friends) {
         if(!_friends.Contains(friend)) {
           _friends.Add(friend);
@@ -317,6 +323,18 @@ namespace SocialVPN {
       }
     }
 
+    /**
+     * Remove a list of friends.
+     * @param fprs a list of friends unique identifiers.
+     */
+    public void DeleteFingerprints(string[] fprs) {
+      foreach(string fpr in fprs) {
+        if(_fingerprints.Contains(fpr)) {
+          _fingerprints.Remove(fpr);
+        }
+      }
+    }
+
   }
 #if SVPN_NUNIT
   [TestFixture]</diff>
      <filename>src/SocialNetworkProvider.cs</filename>
    </modified>
    <modified>
      <diff>@@ -58,9 +58,14 @@ namespace SocialVPN {
     public const string CERTFILENAME = &quot;local.cert&quot;;
 
     /**
+     * The path for the state file.
+     */
+    public const string STATEPATH = &quot;state.xml&quot;;
+
+    /**
      * The DHT TTL.
      */
-    public const int DHTTTL = 600;
+    public const int DHTTTL = 3600;
 
     /**
      * Dictionary of friends indexed by alias.
@@ -118,17 +123,33 @@ namespace SocialVPN {
     protected readonly BlockingQueue _queue;
 
     /**
+     * The http port.
+     */
+    protected readonly string _http_port;
+
+    /**
+     * Keeps track of published certificate.
+     */
+    protected bool _cert_published;
+
+    /**
+     * Access for published certificate status.
+     */
+    public bool CertPublished { get { return _cert_published; } }
+
+    /**
      * Constructor.
      * @param brunetConfig configuration file for Brunet P2P library.
      * @param ipopConfig configuration file for IP over P2P app.
      */
     public SocialNode(NodeConfig brunetConfig, IpopConfig ipopConfig, 
-                      string certDir, string port) : 
+                      string certDir, string port, string global_access) : 
                       base(brunetConfig, ipopConfig) {
       _friends = new Dictionary&lt;string, SocialUser&gt;();
       _aliases = new Dictionary&lt;string, string&gt;();
       _addr_to_key = new Dictionary&lt;string, string&gt;();
       _cert_dir = certDir;
+      _http_port = port;
       string cert_path = Path.Combine(certDir, CERTFILENAME);
       _local_cert = new Certificate(SocialUtils.ReadFileBytes(cert_path));
       _local_user = new SocialUser(_local_cert);
@@ -136,39 +157,36 @@ namespace SocialVPN {
       _bso.CertificateHandler.AddCACertificate(_local_cert.X509);
       _bso.CertificateHandler.AddSignedCertificate(_local_cert.X509);
       _snp = new SocialNetworkProvider(this.Dht, _local_user, 
-                                       _local_cert.X509.RawData, certDir);
+                                       _local_cert.X509.RawData);
       _queue = new BlockingQueue();
       _srh = new SocialRpcHandler(_node, _local_user, _friends, _queue);
       _scm = new SocialConnectionManager(this, _snp, _srh, port, _queue);
+      _cert_published = false;
       _node.ConnectionTable.ConnectionEvent += ConnectHandler;
       _node.HeartBeatEvent += _scm.HeartBeatHandler;
+      Shutdown.OnExit += _scm.Stop;
       _local_user.IP = _marad.LocalIP;
-      _local_user.Alias = CreateAlias(_local_user.Uid, _local_user.PCID,
-                                     _local_user.DhtKey);
+      CreateAlias(_local_user);
       _marad.MapLocalDNS(_local_user.Alias);
+      _scm.SetGlobalAccess(global_access);
+      LoadCertificates();
     }
 
     /**
      * Create a unique alias for a user resource.
-     * @param uid the user unique identifier (email).
-     * @param pcid the pc identifier.
-     * @param dhtKey the friend's dht key.
-     * @return a unique user alias used for DNS naming.
+     * @param user the object representing the user.
      */
-    protected virtual string CreateAlias(string uid, string pcid, 
-                                         string dhtKey) {
-      uid = uid.Replace('@', '.');
-      string alias = (pcid + &quot;.&quot; + uid + DNSSUFFIX).ToLower();
-
+    protected virtual void CreateAlias(SocialUser friend) {
+      string user = friend.Uid.Split('@')[0];
+      string alias = (friend.PCID + &quot;.&quot; + user + DNSSUFFIX).ToLower();
+      int counter = 1;
       // If alias already exists, remove old friend with alias
-      if(_aliases.ContainsKey(alias)) {
-        string dht_key = _aliases[alias];
-        DeleteFriend(_friends[dht_key]);
+      while(_aliases.ContainsKey(alias)) {
+        alias = (friend.PCID + counter + &quot;.&quot; + user + DNSSUFFIX).ToLower();
+        counter++;
       }
-      else {
-        _aliases[alias] = dhtKey;
-      }
-      return alias;
+      _aliases[alias] = friend.DhtKey;
+      friend.Alias = alias;
     }
 
     /**
@@ -194,7 +212,7 @@ namespace SocialVPN {
     public void PublishCertificate() {
       byte[] key_bytes = Encoding.UTF8.GetBytes(_local_user.DhtKey);
       MemBlock keyb = MemBlock.Reference(key_bytes);
-      MemBlock value = MemBlock.Reference(_local_cert.X509.RawData);
+      MemBlock valueb = MemBlock.Reference(_local_cert.X509.RawData);
 
       Channel q = new Channel();
       q.CloseAfterEnqueue();
@@ -202,6 +220,7 @@ namespace SocialVPN {
         try {
           bool success = (bool) (q.Dequeue());
           if(success) {
+            _cert_published = true;
             ProtocolLog.WriteIf(SocialLog.SVPNLog,
                                 String.Format(&quot;PUBLISH CERT SUCCESS: {0} {1}&quot;,
                                 DateTime.Now.TimeOfDay, _local_user.DhtKey));
@@ -213,14 +232,15 @@ namespace SocialVPN {
                               DateTime.Now.TimeOfDay, _local_user.DhtKey));
         }
       };
-      this.Dht.AsyncPut(keyb, value, DHTTTL, q);
+      this.Dht.AsyncPut(keyb, valueb, DHTTTL, q);
     }
 
     /**
      * Add a friend to socialvpn from an X509 certificate.
      * @param certData the X509 certificate as a byte array.
+     * @param access determines to give user network access.
      */
-    public void AddCertificate(byte[] certData) {
+    public void AddCertificate(byte[] certData, bool access) {
       Certificate cert = new Certificate(certData);
       SocialUser friend = new SocialUser(cert);
 
@@ -232,7 +252,7 @@ namespace SocialVPN {
                             DateTime.Now.TimeOfDay, friend.DhtKey));
       }
       else if(_snp.ValidateCertificate(certData)) {
-        friend.Alias = CreateAlias(friend.Uid, friend.PCID, friend.DhtKey);
+        CreateAlias(friend);
         SocialUtils.SaveCertificate(cert, _cert_dir);
         _bso.CertificateHandler.AddCACertificate(cert.X509);
         _friends.Add(friend.DhtKey, friend);
@@ -240,6 +260,11 @@ namespace SocialVPN {
         AddFriend(friend);
         _srh.PingFriend(friend);
 
+        // Block access
+        if(!access) {
+          RemoveFriend(friend);
+        }
+
         ProtocolLog.WriteIf(SocialLog.SVPNLog,
                             String.Format(&quot;ADD CERT KEY SUCCESS: {0} {1} {2}&quot;,
                             DateTime.Now.TimeOfDay, friend.DhtKey,
@@ -256,10 +281,11 @@ namespace SocialVPN {
     /**
      * Add friend by retreiving certificate from DHT.
      * @param key the DHT key for friend's certificate.
+     * @param access determines to give user network access.
      */
-    public void AddDhtFriend(string key) {
+    public void AddDhtFriend(string key, bool access) {
       if(key != _local_user.DhtKey &amp;&amp; !_friends.ContainsKey(key) &amp;&amp;
-         key.Length &gt;= 45) {
+         key.Length &gt;= 45 ) {
         ProtocolLog.WriteIf(SocialLog.SVPNLog, 
                             String.Format(&quot;ADD DHT FETCH: {0} {1}&quot;, 
                             DateTime.Now.TimeOfDay, key));
@@ -269,11 +295,21 @@ namespace SocialVPN {
           try {
             Hashtable result = (Hashtable) q.Dequeue();
             byte[] certData = (byte[]) result[&quot;value&quot;];
-            ProtocolLog.WriteIf(SocialLog.SVPNLog, 
-                                String.Format(&quot;ADD DHT SUCCESS: {0} {1}&quot;,
-                                DateTime.Now.TimeOfDay, key));
-            _queue.Enqueue(new QueueItem(
-              QueueItem.Actions.AddCert, certData));
+            string tmp_key = SocialUser.DHTPREFIX + 
+                             SocialUtils.GetSHA256(certData);
+            if(tmp_key == key) {
+              ProtocolLog.WriteIf(SocialLog.SVPNLog, 
+                                  String.Format(&quot;ADD DHT SUCCESS: {0} {1}&quot;,
+                                  DateTime.Now.TimeOfDay, key));
+              if(access) {
+                _queue.Enqueue(new QueueItem(
+                               QueueItem.Actions.AddCertTrue, certData));
+              }
+              else {
+                _queue.Enqueue(new QueueItem(
+                               QueueItem.Actions.AddCertFalse, certData));
+              }
+            }
           } catch (Exception e) {
             ProtocolLog.WriteIf(SocialLog.SVPNLog,e.Message);
             ProtocolLog.WriteIf(SocialLog.SVPNLog,
@@ -307,49 +343,104 @@ namespace SocialVPN {
       }
     }
 
+    /*
+     * Deletes a friend from socialvpn.
+     * @param fpr the friend's fingerprint to be removed.
+     */
+    public void DeleteFriend(string fpr) {
+      if(_friends.ContainsKey(fpr)) {
+        DeleteFriend(_friends[fpr]);
+      }
+    }
 
     /*
      * Add a friend from socialvpn.
      * @param friend the friend to be added.
      */
-    public void AddFriend(SocialUser friend) {
+    protected void AddFriend(SocialUser friend) {
       Address addr = AddressParser.Parse(friend.Address);
       friend.IP = _marad.RegisterMapping(friend.Alias, addr);
       _node.ManagedCO.AddAddress(addr);
       friend.Access = SocialUser.AccessTypes.Allow.ToString();
+      _srh.PingFriend(friend);
+      GetState(true);
     }
 
     /**
      * Removes (block access) a friend from socialvpn.
      * @param friend the friend to be removed.
      */
-    public void RemoveFriend(SocialUser friend) {
+    protected void RemoveFriend(SocialUser friend) {
       Address addr = AddressParser.Parse(friend.Address);
       _node.ManagedCO.RemoveAddress(addr);
       _marad.UnregisterMapping(friend.Alias);
       friend.Access = SocialUser.AccessTypes.Block.ToString();
+      GetState(true);
     }
 
     /**
      * Delete (erase) a friend from socialvpn.
      * @param friend the friend to be deleted.
      */
-    public void DeleteFriend(SocialUser friend) {
+    protected void DeleteFriend(SocialUser friend) {
       RemoveFriend(friend);
-      SocialUtils.DeleteCertificate(friend.Address, _cert_dir);
       _friends.Remove(friend.DhtKey);
+      _addr_to_key.Remove(friend.Address);
+      _aliases.Remove(friend.Alias);
+      SocialUtils.DeleteCertificate(friend.Address, _cert_dir);
+      GetState(true);
+    }
+
+    /**
+     * Loads certificates from the file system.
+     */
+    protected void LoadCertificates() {
+      string[] cert_files = null;
+      try {
+        cert_files = System.IO.Directory.GetFiles(_cert_dir);
+        SocialState state = Utils.ReadConfig&lt;SocialState&gt;(STATEPATH);
+        foreach(string cert_file in cert_files) {
+          byte[] cert_data = SocialUtils.ReadFileBytes(cert_file);
+          AddCertificate(cert_data, true);
+        }
+        SetState(state);
+      } catch (Exception e) {
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, e.Message);
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, &quot;LOAD CERTIFICATES FAILURE&quot;);
+      }
+    }
+
+    /**
+     * Restores the previous state from the file system.
+     * @param state the social state to set.
+     */
+    public void SetState(SocialState state) {
+      try {
+        foreach(SocialUser friend in state.Friends) {
+          if(friend.Access == SocialUser.AccessTypes.Block.ToString()) {
+            DeleteFriend(friend.DhtKey);
+          }
+        }
+      } catch(Exception e) { 
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, e.Message);
+        ProtocolLog.WriteIf(SocialLog.SVPNLog, &quot;SET STATE FAILURE&quot;);
+      }
     }
 
     /**
      * Generates an XML string representing state of the system.
      * @return a string represential the state.
      */
-    public string GetState() {
+    public string GetState(bool write_to_file) {
       SocialState state = new SocialState();
       state.Certificate = _local_cert_b64;
       state.LocalUser = _local_user;
+      //state.Deletes = _deletes;
       state.Friends = new SocialUser[_friends.Count];
       _friends.Values.CopyTo(state.Friends, 0);
+      if(write_to_file) {
+        Utils.WriteConfig(STATEPATH, state);
+      }
       return SocialUtils.ObjectToXml&lt;SocialState&gt;(state);
     }
 
@@ -358,33 +449,43 @@ namespace SocialVPN {
      */
     public static new void Main(string[] args) {
 
-      if(args.Length &lt; 3) {
-        Console.WriteLine(&quot;usage: SocialVPN.exe &lt;brunet.config path&gt; &quot; + 
-                           &quot;&lt;ipop.config path&gt; &lt;http port&gt; [email] [pcid] &quot; + 
-                           &quot;[\&quot;name\&quot;]&quot;);
-        return;
-      }
+      NodeConfig node_config = null;
+      IpopConfig ipop_config = null;
+      string port, global_access;
 
-      NodeConfig node_config = Utils.ReadConfig&lt;NodeConfig&gt;(args[0]);
-      IpopConfig ipop_config = Utils.ReadConfig&lt;IpopConfig&gt;(args[1]);
+      if(args.Length &lt; 4) {
+        try {
+          node_config = Utils.ReadConfig&lt;NodeConfig&gt;(&quot;brunet.config&quot;);
+          ipop_config = Utils.ReadConfig&lt;IpopConfig&gt;(&quot;ipop.config&quot;);
+          port = &quot;58888&quot;;
+          global_access = &quot;on&quot;;
+        } catch {
+          Console.WriteLine(&quot;usage: SocialVPN.exe &lt;brunet.config path&gt; &quot; + 
+                             &quot;&lt;ipop.config path&gt; &lt;http port&gt; &quot; +
+                             &quot;&lt;global_access(on/off)&gt;&quot; + 
+                             &quot;[email] [pcid] [\&quot;name\&quot;]&quot;);
+          return;
+        }
+      }
+      else {
+        node_config = Utils.ReadConfig&lt;NodeConfig&gt;(args[0]);
+        ipop_config = Utils.ReadConfig&lt;IpopConfig&gt;(args[1]);
+        port = args[2];
+        global_access = args[3];
+      }
 
       if(!System.IO.Directory.Exists(node_config.Security.CertificatePath)) {
         string name, uid, pcid, version, country;
-        if(args.Length &gt;= 6) {
-          uid = args[3];
-          pcid = args[4];
-          name = args[5];
+        if(args.Length &gt;= 7) {
+          uid = args[4];
+          pcid = args[5];
+          name = args[6];
         }
         else {
-          Console.Write(&quot;Enter Name (First Last): &quot;);
-          name = Console.ReadLine();
-          Console.Write(&quot;Enter Email Address: &quot;);
-          uid = Console.ReadLine();
-          Console.Write(&quot;Enter a unique name for this machine: &quot;);
-          pcid = Console.ReadLine();
-        }
-
-        if(uid.Length &lt; 1 || pcid.Length &lt; 1 || name.Length &lt; 1) {
+          Console.WriteLine(&quot;usage (on first run): SocialVPN.exe &quot; +
+                            &quot;&lt;brunet.config path&gt; &lt;ipop.config path&gt;&quot; +
+                            &quot;&lt;http port&gt; &lt;global_access(on/off)&gt; &quot; +
+                            &quot;&lt;email&gt; &lt;pcid&gt; &lt;\&quot;name\&quot;&gt;&quot;);
           return;
         }
 
@@ -400,7 +501,7 @@ namespace SocialVPN {
 
       SocialNode node = new SocialNode(node_config, ipop_config, 
                                        node_config.Security.CertificatePath,
-                                       args[2]);
+                                       port, global_access);
       node.Run();
     }
   }</diff>
      <filename>src/SocialNode.cs</filename>
    </modified>
    <modified>
      <diff>@@ -171,6 +171,7 @@ namespace SocialVPN {
                             String.Format(&quot;FIRE SYNC: {0} {1} {2}&quot;,
                             DateTime.Now.TimeOfDay, dhtKey, uid));
 
+        _queue.Enqueue(new QueueItem(QueueItem.Actions.DhtAdd, dhtKey));
         _queue.Enqueue(new QueueItem(QueueItem.Actions.Sync, uid));
       }
       return _local_user.DhtKey + DELIM + response;
@@ -215,7 +216,7 @@ namespace SocialVPN {
 
       ISender sender = new AHExactSender(_node, addr);
       _rpc.Invoke(sender, q, &quot;SocialVPN.FriendPing&quot;, _local_user.DhtKey,
-        _local_user.Uid);
+                  _local_user.Uid);
     }
   }
 #if SVPN_NUNIT</diff>
      <filename>src/SocialRpcHandler.cs</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 using System;
+using System.Collections.Generic;
 
 namespace SocialVPN {
 
@@ -37,5 +38,9 @@ namespace SocialVPN {
      * The list of friends.
      */
     public SocialUser[] Friends;
+
+    public List&lt;string&gt; Deletes;
+
+    public List&lt;string&gt; Messages;
   }
 }</diff>
      <filename>src/SocialState.cs</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,7 @@ namespace SocialVPN {
 
     public const string ALIASDEFAULT = &quot;unknown&quot;;
 
-    public const string PICDEFAULT = &quot;nopic&quot;;
+    public const string PICDEFAULT = &quot;pic.png&quot;;
 
     public const string DHTPREFIX = &quot;svpn:&quot;;
 </diff>
      <filename>src/SocialUser.cs</filename>
    </modified>
    <modified>
      <diff>@@ -114,7 +114,7 @@ namespace SocialVPN {
     public static void DeleteCertificate(string address, string certDir) {
       address = address.Substring(12);
       string cert_path = Path.Combine(certDir, address + CERTSUFFIX);
-      if(!File.Exists(cert_path)) {
+      if(File.Exists(cert_path)) {
         File.Delete(cert_path);
       }
     }
@@ -213,11 +213,11 @@ namespace SocialVPN {
       
       for (int x = 0; x &lt; pairs.Length; x++) {
         string[] item = pairs[x].Split('=');
-        /*
+        
         result.Add(HttpUtility.UrlDecode(item[0]), 
                    HttpUtility.UrlDecode(item[1]));
-        */
-        result.Add(item[0], item[1]);
+        
+        //result.Add(item[0], item[1]);
       }
       return result;
     }</diff>
      <filename>src/SocialUtils.cs</filename>
    </modified>
    <modified>
      <diff>@@ -5,18 +5,12 @@
   &lt;property name=&quot;build.dir&quot; value=&quot;build&quot; /&gt;
   &lt;property name=&quot;bin.dir&quot; value=&quot;../bin&quot;/&gt;
   &lt;property name=&quot;config.dir&quot; value=&quot;../config&quot;/&gt;
+  &lt;property name=&quot;scripts.dir&quot; value=&quot;../scripts&quot;/&gt;
+  &lt;property name=&quot;images.dir&quot; value=&quot;../images&quot;/&gt;
 
   &lt;target name=&quot;clean&quot; description=&quot;Remove build directory&quot;&gt;
     &lt;delete dir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;/&gt;
-    &lt;delete failonerror=&quot;true&quot;&gt;
-      &lt;fileset basedir=&quot;${bin.dir}&quot;&gt;
-        &lt;include name=&quot;SocialVPN.exe&quot; /&gt;
-        &lt;include name=&quot;*.dll&quot; /&gt;
-        &lt;include name=&quot;libtuntap.*&quot;/&gt;
-        &lt;include name=&quot;socialvpn.*&quot; /&gt;
-        &lt;include name=&quot;*.config&quot; /&gt;
-      &lt;/fileset&gt;
-    &lt;/delete&gt;
+    &lt;delete dir=&quot;${bin.dir}&quot; failonerror=&quot;true&quot; /&gt;
   &lt;/target&gt;
 
   &lt;target name=&quot;build&quot; description=&quot;Build SocialVPN.exe&quot;&gt;
@@ -24,10 +18,10 @@
     &lt;copy todir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;&gt;
       &lt;fileset basedir=&quot;${lib.dir}&quot;&gt;
         &lt;include name=&quot;*.dll&quot; /&gt;
-        &lt;include name=&quot;libtuntap.*&quot; /&gt;
       &lt;/fileset&gt;
     &lt;/copy&gt;
 
+    &lt;mkdir dir=&quot;${bin.dir}&quot; failonerror=&quot;true&quot;/&gt;
     &lt;copy todir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;&gt;
       &lt;fileset basedir=&quot;.&quot;&gt;
         &lt;include name=&quot;socialvpn.js&quot; /&gt;
@@ -37,11 +31,23 @@
 
     &lt;copy todir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;&gt;
       &lt;fileset basedir=&quot;${config.dir}&quot;&gt;
-        &lt;include name=&quot;*.config&quot; /&gt;
+        &lt;include name=&quot;*&quot; /&gt;
+      &lt;/fileset&gt;
+    &lt;/copy&gt;
+
+    &lt;copy todir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;&gt;
+      &lt;fileset basedir=&quot;${scripts.dir}&quot;&gt;
+        &lt;include name=&quot;*&quot; /&gt;
       &lt;/fileset&gt;
     &lt;/copy&gt;
 
-    &lt;csc target=&quot;exe&quot; output=&quot;${build.dir}/SocialVPN.exe&quot;&gt;
+    &lt;copy todir=&quot;${build.dir}&quot; failonerror=&quot;true&quot;&gt;
+      &lt;fileset basedir=&quot;${images.dir}&quot;&gt;
+        &lt;include name=&quot;*&quot; /&gt;
+      &lt;/fileset&gt;
+    &lt;/copy&gt;
+
+    &lt;csc target=&quot;winexe&quot; main=&quot;SocialVPN.SocialNode&quot; output=&quot;${build.dir}/SocialVPN.exe&quot;&gt;
       &lt;sources failonempty=&quot;true&quot;&gt;
         &lt;include name=&quot;*.cs&quot;/&gt;
       &lt;/sources&gt;
@@ -61,10 +67,11 @@
       &lt;/references&gt;
     &lt;/csc&gt;
 
-    &lt;mkdir dir=&quot;${bin.dir}&quot; failonerror=&quot;true&quot;/&gt;
-    &lt;copy todir=&quot;${bin.dir}&quot; failonerror=&quot;true&quot;&gt;
-      &lt;fileset basedir=&quot;${build.dir}&quot;&gt;
-        &lt;include name=&quot;SocialVPN.exe&quot; /&gt;
+    &lt;csc target=&quot;exe&quot; main=&quot;SocialVPN.SVPNTool&quot; output=&quot;${build.dir}/SVPNTool.exe&quot;&gt;
+      &lt;sources failonempty=&quot;true&quot;&gt;
+        &lt;include name=&quot;*.cs&quot;/&gt;
+      &lt;/sources&gt;
+      &lt;references basedir=&quot;${build.dir}&quot;&gt;
         &lt;include name=&quot;Brunet.dll&quot; /&gt;
         &lt;include name=&quot;Brunet.Dht.dll&quot; /&gt;
         &lt;include name=&quot;Brunet.DhtService.dll&quot; /&gt;
@@ -73,16 +80,18 @@
         &lt;include name=&quot;Brunet.Coordinate.dll&quot; /&gt;
         &lt;include name=&quot;Brunet.XmlRpc.dll&quot; /&gt;
         &lt;include name=&quot;CookComputing.XmlRpcV2.dll&quot; /&gt;
-        &lt;include name=&quot;System.Runtime.Remoting.dll&quot; /&gt;
-        &lt;include name=&quot;System.Web.dll&quot; /&gt;
         &lt;include name=&quot;Mono.Posix.dll&quot;/&gt;
         &lt;include name=&quot;Mono.Security.dll&quot;/&gt;
-        &lt;include name=&quot;libtuntap.*&quot;/&gt;
+        &lt;include name=&quot;System.Runtime.Remoting.dll&quot;/&gt;
+        &lt;include name=&quot;System.Web.dll&quot; /&gt;
         &lt;include name=&quot;ManagedIpopNode.dll&quot; /&gt;
-        &lt;include name=&quot;socialvpn.js&quot; /&gt;
-        &lt;include name=&quot;socialvpn.css&quot; /&gt;
-        &lt;include name=&quot;brunet.config&quot; /&gt;
-        &lt;include name=&quot;ipop.config&quot; /&gt;
+        &lt;include name=&quot;nunit.framework.dll&quot;/&gt;
+      &lt;/references&gt;
+    &lt;/csc&gt;
+
+    &lt;copy todir=&quot;${bin.dir}&quot; failonerror=&quot;true&quot;&gt;
+      &lt;fileset basedir=&quot;${build.dir}&quot;&gt;
+        &lt;include name=&quot;*&quot; /&gt;
       &lt;/fileset&gt;
     &lt;/copy&gt;
   &lt;/target&gt;</diff>
      <filename>src/default.build</filename>
    </modified>
    <modified>
      <diff>@@ -55,6 +55,15 @@ body {
   padding: 0px;
 }
 
+#local_nav h5 {
+  font-size: 12px;
+  margin: 5px;
+  padding: 0px;
+  color: #999999;
+  font-weight: bold;
+}
+
+
 #local_nav ul {
   margin: 10px 0px 10px 0px;
   padding: 0px 5px 5px 5px;
@@ -179,6 +188,12 @@ body {
   float: right;
 }
 
+.div_fpr {
+  font-size: 12px;
+  color: #999999;
+  font-weight: bold;
+}
+
 .loginlink {
   font-size: 20px;
   font-weight: bold;</diff>
      <filename>src/socialvpn.css</filename>
    </modified>
    <modified>
      <diff>@@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 var stateXML = &quot;&quot;;
 var pageID = &quot;friends&quot;;
 var option = &quot;All&quot;;
+var refresh_time = 0;
+var show_fpr = &quot;no&quot;;
 
 init();
 
@@ -95,129 +97,56 @@ function loadHeader() {
   div_subheader.appendChild(main_title);
   div_subheader.appendChild(menu);
 
-  createElem(&quot;li&quot;, &quot;Login&quot;, &quot;&quot;, &quot;&quot;, menu.id, loadLogin); 
-  createElem(&quot;li&quot;, &quot;Profile&quot;, &quot;&quot;, &quot;&quot;, menu.id, loadProfile); 
-  createElem(&quot;li&quot;, &quot;Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, loadFriends); 
+  //createElem(&quot;li&quot;, &quot;Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, loadFriends); 
 }
 
-function loadLogin() {
-  var div_tmp_content = document.getElementById('tmp_content');
-  div_tmp_content.innerHTML = &quot;&quot;;
-  
-  createElem(&quot;span&quot;, &quot;Please enter username and password&quot;, &quot;&quot;, &quot;f_name&quot;, 
-             &quot;tmp_content&quot;, &quot;&quot;);
-  
-  var user_text = createElem(&quot;input&quot;, &quot;&quot;, &quot;user_input&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                             &quot;&quot;);
-  user_text.setAttribute(&quot;type&quot;, &quot;text&quot;);
-  
-  var pass_text = createElem(&quot;input&quot;, &quot;&quot;, &quot;pass_input&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                             &quot;&quot;);
-  pass_text.setAttribute(&quot;type&quot;, &quot;password&quot;);
-  
-  var input_button = createElem(&quot;button&quot;, &quot;Submit&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                                submitLogin);
-  input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
-  
-  var input_button = createElem(&quot;button&quot;, &quot;Cancel&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                                cancelSubmit);
-  input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
-}
-
-function loadProfile() {
-  pageID = &quot;profile&quot;;
+function loadFriends() {
+  pageID = &quot;friends&quot;;
   
   clearDiv(&quot;local_nav&quot;);
   clearDiv(&quot;main_content&quot;);
 
-  var title = document.createElement('h4');
-  title.innerHTML = &quot;Profile&quot;;
-  
-  var menu = document.createElement('ul');
-  menu.id = &quot;profile_menu&quot;;
-    
-  var div_local_nav = document.getElementById('local_nav');
-  div_local_nav.innerHTML = &quot;&quot;;
-  div_local_nav.appendChild(title);
-  div_local_nav.appendChild(menu);
-  
-  createElem(&quot;li&quot;, &quot;Information&quot;, &quot;&quot;, &quot;&quot;, menu.id, showProfileInfo);
-  createElem(&quot;li&quot;, &quot;Update Profile&quot;, &quot;&quot;, &quot;&quot;, menu.id, &quot;&quot;);
-
-  showProfileInfo();
-}
-
-function showProfileInfo() {
-  clearDiv(&quot;main_content&quot;);
-  createTable(&quot;Information&quot;);
-
-  var dtTable = document.getElementById('data_table');
-  
-  var new_tr = document.createElement('tr');
-  var new_td = document.createElement('td');
-  var div_info = document.createElement('div');
-  div_info.className = &quot;div_info&quot;;  
-  dtTable.appendChild(new_tr);
-  new_tr.appendChild(new_td);  
-  new_td.appendChild(div_info);
-  
   var local_user = stateXML.getElementsByTagName('LocalUser')[0];
-  
   var name = local_user.getElementsByTagName('Name')[0].textContent;
-  var openid = local_user.getElementsByTagName('Uid')[0].textContent;
-  var pcid = local_user.getElementsByTagName('PCID')[0].textContent;
-  var p2paddress = local_user.getElementsByTagName('Address')[0].textContent;
-  var key_fpr = local_user.getElementsByTagName('Fingerprint')[0].textContent;
-  var pic = &quot;http://static.ak.fbcdn.net/pics/d_silhouette.gif&quot;;
-  
-  var img_usr = document.createElement('img');
-  img_usr.className = &quot;f_img&quot;;
-  img_usr.setAttribute(&quot;src&quot;, pic);
-  img_usr.setAttribute(&quot;width&quot;, &quot;200&quot;);
-  img_usr.setAttribute(&quot;height&quot;, &quot;126&quot;);
-  div_info.appendChild(img_usr);
+  var alias = local_user.getElementsByTagName('Alias')[0].textContent;
+  var ip = local_user.getElementsByTagName('IP')[0].textContent;
+  var fingerprint = local_user.getElementsByTagName('DhtKey')[0].textContent;
   
-  createElem(&quot;span&quot;, name, &quot;&quot;, &quot;fp_name&quot;, div_info, &quot;&quot;);
-  div_info.appendChild(document.createElement('br'));
-  div_info.appendChild(document.createElement('br'));
-  
-  createElem(&quot;span&quot;, openid, &quot;&quot;, &quot;fp_info&quot;, div_info, &quot;&quot;);
-  div_info.appendChild(document.createElement('br'));
-  
-  createElem(&quot;span&quot;, pcid, &quot;&quot;, &quot;fp_info&quot;, div_info, &quot;&quot;);
-  div_info.appendChild(document.createElement('br'));
-  
-  createElem(&quot;span&quot;, key_fpr, &quot;&quot;, &quot;fp_info&quot;, div_info, &quot;&quot;);
-  div_info.appendChild(document.createElement('br')); 
-}
-
-function loadFriends() {
-  pageID = &quot;friends&quot;;
-  
-  clearDiv(&quot;local_nav&quot;);
-  clearDiv(&quot;main_content&quot;);
-
   var title = document.createElement('h4');
-  title.innerHTML = &quot;Friends&quot;;
-  
+  title.innerHTML = name + &quot; - &quot; + alias + &quot; - &quot; + ip;
+
   var menu = document.createElement('ul');
   menu.id = &quot;friends_menu&quot;;
     
   var div_local_nav = document.getElementById('local_nav');
   div_local_nav.innerHTML = &quot;&quot;;
   div_local_nav.appendChild(title);
+  var subtitle = document.createElement('h5');
+  subtitle.innerHTML = &quot;Your fingerprint - &quot; + fingerprint;  
+  div_local_nav.appendChild(subtitle);
   div_local_nav.appendChild(menu);
   
   createElem(&quot;li&quot;, &quot;All Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, showAllFriends);
   createElem(&quot;li&quot;, &quot;Online Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, showOnlineFriends);
   createElem(&quot;li&quot;, &quot;Offline Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, showOfflineFriends);
   createElem(&quot;li&quot;, &quot;Blocked Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, showBlockedFriends);
-  createElem(&quot;li&quot;, &quot;Add Friend Uid&quot;, &quot;&quot;, &quot;&quot;, menu.id, addFriendID);
-  createElem(&quot;li&quot;, &quot;Add Certificate&quot;, &quot;&quot;, &quot;&quot;, menu.id, addCertificate);
+  createElem(&quot;li&quot;, &quot;Show/Hide Fingerprints&quot;, &quot;&quot;, &quot;&quot;, menu.id, toggleFprs);
+  createElem(&quot;li&quot;, &quot;Add Friends&quot;, &quot;&quot;, &quot;&quot;, menu.id, addEmails);
+  //createElem(&quot;li&quot;, &quot;Add Fingerprints&quot;, &quot;&quot;, &quot;&quot;, menu.id, addFingerprints);
   
   showFriends();
 }
 
+function toggleFprs() {
+  if(show_fpr == &quot;yes&quot;) {
+    show_fpr = &quot;no&quot;;
+  }
+  else {
+    show_fpr = &quot;yes&quot;;
+  }
+  loadFriends();
+}
+
 function showAllFriends() {
   option = &quot;All&quot;;
   showFriends();
@@ -258,7 +187,7 @@ function showFriends() {
       friends[i].status = &quot;Status: Online (&quot; + friend_time + &quot;)&quot;;
       addFriend(friends[i]);
     }
-    else if(friend_access == &quot;Block&quot; &amp;&amp; option == &quot;Blocked&quot;) {
+    else if(friend_access == &quot;Block&quot; &amp;&amp; option == &quot;Blocked&quot; || option == &quot;All&quot;) {
       friends[i].status = &quot;Status: Blocked&quot;;
       addFriend(friends[i]);
     }
@@ -266,12 +195,12 @@ function showFriends() {
 }
 
 function addFriend(friend) {
-  var address = friend.getElementsByTagName('Address')[0].textContent;
+  var dhtkey = friend.getElementsByTagName('DhtKey')[0].textContent;
   var dtTable = document.getElementById('data_table');
   
   var new_tr = document.createElement('tr');
   var new_td = document.createElement('td');
-  new_td.id = address;
+  new_td.id = dhtkey;
   var div_opts = document.createElement('div');
   div_opts.className = &quot;div_options&quot;;
   var div_info = document.createElement('div');
@@ -282,14 +211,19 @@ function addFriend(friend) {
   new_td.appendChild(div_opts);
   new_td.appendChild(div_info);
 
+  var opt_item = createElem(&quot;span&quot;, &quot;Block&quot;, &quot;&quot;, &quot;opts_menu&quot;, div_opts, 
+                            removeFriendPost);
+  opt_item.dhtkey = dhtkey;
+  div_opts.appendChild(document.createElement('br'));
+
   var opt_item = createElem(&quot;span&quot;, &quot;Unblock&quot;, &quot;&quot;, &quot;opts_menu&quot;, div_opts, 
                             addFriendPost);
-  opt_item.address = address;
+  opt_item.dhtkey = dhtkey;
   div_opts.appendChild(document.createElement('br'));
   
-  var opt_item = createElem(&quot;span&quot;, &quot;Block&quot;, &quot;&quot;, &quot;opts_menu&quot;, div_opts, 
-                            removeFriendPost);
-  opt_item.address = address;
+  var opt_item = createElem(&quot;span&quot;, &quot;Delete&quot;, &quot;&quot;, &quot;opts_menu&quot;, div_opts, 
+                            deleteFriendPost);
+  opt_item.dhtkey = dhtkey;
   div_opts.appendChild(document.createElement('br'));
 
   var img_usr = document.createElement('img');
@@ -300,7 +234,8 @@ function addFriend(friend) {
   img_usr.setAttribute(&quot;height&quot;, &quot;50&quot;);
   div_info.appendChild(img_usr);
   
-  var innerHTML = friend.getElementsByTagName('Name')[0].textContent;
+  var name = friend.getElementsByTagName('Name')[0].textContent;
+  var innerHTML = name;
   var info_item = createElem(&quot;span&quot;, innerHTML, &quot;&quot;, &quot;f_name&quot;, div_info, &quot;&quot;);
   div_info.appendChild(document.createElement('br'));
   
@@ -312,6 +247,20 @@ function addFriend(friend) {
   var innerHTML = friend.status;
   var info_item = createElem(&quot;span&quot;, innerHTML, &quot;&quot;, &quot;f_online&quot;, div_info, &quot;&quot;);
   div_info.appendChild(document.createElement('br'));
+
+  if(show_fpr == &quot;yes&quot; ) {  
+	var new_tr = document.createElement('tr');
+	var new_td = document.createElement('td');
+	new_td.id = dhtkey;
+	var div_info = document.createElement('div');
+	div_info.className = &quot;div_fpr&quot;;
+	div_info.innerHTML = name + &quot;'s fingerprint - &quot; +
+		friend.getElementsByTagName('DhtKey')[0].textContent;
+  
+	dtTable.appendChild(new_tr);
+	new_tr.appendChild(new_td);  
+	new_td.appendChild(div_info);
+  }
 }
 
 function cancelSubmit() {
@@ -319,20 +268,20 @@ function cancelSubmit() {
   div_tmp_content.innerHTML = &quot;&quot;;
 }
 
-function addFriendID() {  
+function addEmails() {  
   var div_tmp_content = document.getElementById('tmp_content');
   div_tmp_content.innerHTML = &quot;&quot;;
   
-  createElem(&quot;span&quot;, &quot;Please enter a list of OpenIDs seperated by new line&quot;, 
+  createElem(&quot;span&quot;, &quot;Enter friend's email addresses (comma seperated)&quot;, 
              &quot;&quot;, &quot;f_name&quot;, &quot;tmp_content&quot;, &quot;&quot;);
   
   var input_text = createElem(&quot;textarea&quot;, &quot;&quot;, &quot;data_input&quot;, &quot;&quot;, &quot;tmp_content&quot;,
                               &quot;&quot;);
-  input_text.setAttribute(&quot;rows&quot;, &quot;10&quot;);
+  input_text.setAttribute(&quot;rows&quot;, &quot;5&quot;);
   input_text.setAttribute(&quot;cols&quot;, &quot;50&quot;);
   
   var input_button = createElem(&quot;button&quot;, &quot;Submit&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                                submitFriendID);
+                                submitEmails);
   input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
   
   var input_button = createElem(&quot;button&quot;, &quot;Cancel&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
@@ -340,28 +289,20 @@ function addFriendID() {
   input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
 }
 
-function submitFriendID() {
-  var input_data =&quot;m=add&amp;uids=&quot; + 
-    encodeURIComponent(document.getElementById('data_input').value);    
-  makeCall(input_data);
-  var div_tmp_content = document.getElementById('tmp_content');
-  div_tmp_content.innerHTML = &quot;&quot;;
-}
-
-function addCertificate() {  
+function addFingerprints() {  
   var div_tmp_content = document.getElementById('tmp_content');
   div_tmp_content.innerHTML = &quot;&quot;;
   
-  createElem(&quot;span&quot;, &quot;Paste a friend's certificate&quot;, 
+  createElem(&quot;span&quot;, &quot;Paste fingerprints (comma seperated)&quot;, 
              &quot;&quot;, &quot;f_name&quot;, &quot;tmp_content&quot;, &quot;&quot;);
   
   var input_text = createElem(&quot;textarea&quot;, &quot;&quot;, &quot;data_input&quot;, &quot;&quot;, &quot;tmp_content&quot;,
                               &quot;&quot;);
-  input_text.setAttribute(&quot;rows&quot;, &quot;10&quot;);
+  input_text.setAttribute(&quot;rows&quot;, &quot;5&quot;);
   input_text.setAttribute(&quot;cols&quot;, &quot;50&quot;);
   
   var input_button = createElem(&quot;button&quot;, &quot;Submit&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
-                                submitCertificate);
+                                submitFingerprints);
   input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
   
   var input_button = createElem(&quot;button&quot;, &quot;Cancel&quot;, &quot;&quot;, &quot;&quot;, &quot;tmp_content&quot;, 
@@ -369,50 +310,55 @@ function addCertificate() {
   input_button.setAttribute(&quot;type&quot;, &quot;text&quot;);
 }
 
-function submitCertificate() {
-  var input_data =&quot;m=addcert&amp;cert=&quot; + 
+function submitEmails() {
+  var input_data =&quot;m=add&amp;uids=&quot; + 
     encodeURIComponent(document.getElementById('data_input').value);    
-  makeCall(input_data);
+  makeCall(input_data, 2000);
   var div_tmp_content = document.getElementById('tmp_content');
   div_tmp_content.innerHTML = &quot;&quot;;
 }
 
-function submitLogin() {
-  var input_data =&quot;m=login&amp;id=drupalbackend&amp;user=&quot; + 
-    document.getElementById('user_input').value + &quot;&amp;pass=&quot; +
-    document.getElementById('pass_input').value;
-  makeCall(input_data);
+function submitFingerprints() {
+  var input_data =&quot;m=addfpr&amp;fprs=&quot; + 
+    encodeURIComponent(document.getElementById('data_input').value);    
+  makeCall(input_data, 2000);
   var div_tmp_content = document.getElementById('tmp_content');
   div_tmp_content.innerHTML = &quot;&quot;;
 }
 
-function getConnect() {
-  makeCall('m=connect');
-}
-
 function getState() {
-  makeCall('m=getstate');
+  makeCall('m=getstate', 0);
 }
 
 function removeFriendPost() {
-  var postData = &quot;m=update&amp;address=&quot; + 
-    this.address + &quot;&amp;access=off&quot;;
-  makeCall(postData);
+  var postData = &quot;m=block&amp;fprs=&quot; + 
+    encodeURIComponent(this.dhtkey);
+  makeCall(postData, 1000);
 }
 
 function addFriendPost() {
-  var postData = &quot;m=update&amp;address=&quot; + 
-    this.address + &quot;&amp;access=on&quot;;
-  makeCall(postData);
+  var postData = &quot;m=allow&amp;fprs=&quot; + 
+    encodeURIComponent(this.dhtkey);
+  makeCall(postData, 1000);
 }
 
-function makeCall(postData) {
+function deleteFriendPost() {
+  var postData = &quot;m=delete&amp;fprs=&quot; + 
+    encodeURIComponent(this.dhtkey);
+  makeCall(postData, 1000);
+}
+
+function makeCall(postData, ref_time) {
+  refresh_time = ref_time
   var httpRequest = new XMLHttpRequest();
   httpRequest.overrideMimeType('text/xml');
   httpRequest.onreadystatechange = function() { 
     if(httpRequest.readyState == 4) {
       stateXML = httpRequest.responseXML;
-      if(pageID == &quot;friends&quot;) {
+      if(refresh_time != 0) {
+        window.setTimeout(getState, refresh_time);
+      }
+      else if(pageID == &quot;friends&quot;) {
         loadFriends();
       }
     }</diff>
      <filename>src/socialvpn.js</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>bin/start_linux.sh</filename>
    </removed>
    <removed>
      <filename>bin/start_win.cmd</filename>
    </removed>
    <removed>
      <filename>lib/libtuntap.so</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>ac91efd6fc201d814bec34f9aae1d8ce9800e8f3</id>
    </parent>
  </parents>
  <author>
    <name>Pierre St Juste</name>
    <email>ptony82@gmail.com</email>
  </author>
  <url>http://github.com/ptony82/socialvpn/commit/996b1a929d649e67b4b1d1af23da93e29e776173</url>
  <id>996b1a929d649e67b4b1d1af23da93e29e776173</id>
  <committed-date>2009-07-27T10:16:55-07:00</committed-date>
  <authored-date>2009-07-27T10:16:55-07:00</authored-date>
  <message>This is a commit for the beta release version, I need to find tag option in git</message>
  <tree>b6fec2dc746df4a91bad7f4623af82b0c9f216ab</tree>
  <committer>
    <name>Pierre St Juste</name>
    <email>ptony82@gmail.com</email>
  </committer>
</commit>
