From 9be1a94043ce1518d70ebe8b1d0c44b54ec6652f Mon Sep 17 00:00:00 2001
From: David-Sarah Hopwood <david-sarah@jacaranda.org>
Date: Thu, 21 Mar 2013 00:25:49 +0000
Subject: [PATCH] Censor the introducer and helper furls' swissnums from the
 web welcome page. refs #1802

Signed-off-by: David-Sarah Hopwood <david-sarah@jacaranda.org>
---
 src/allmydata/test/test_web.py  | 56 +++++++++++++++++++++++++++++++--
 src/allmydata/web/root.py       | 20 +++++++++---
 src/allmydata/web/welcome.xhtml |  4 +--
 3 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 13750b85..1ffab54b 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -617,6 +617,54 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(_check)
         return d
 
+    def test_introducer_status(self):
+        class MockIntroducerClient(object):
+            def __init__(self, connected):
+                self.connected = connected
+            def connected_to_introducer(self):
+                return self.connected
+
+        d = defer.succeed(None)
+
+        # introducer not connected, unguessable furl
+        def _set_introducer_not_connected_unguessable(ign):
+            self.s.introducer_furl = "pb://someIntroducer/secret"
+            self.s.introducer_client = MockIntroducerClient(False)
+            return self.GET("/")
+        d.addCallback(_set_introducer_not_connected_unguessable)
+        def _check_introducer_not_connected_unguessable(res):
+            html = res.replace('\n', ' ')
+            self.failUnlessIn('<div class="furl">pb://someIntroducer/[censored]</div>', html)
+            self.failIfIn('pb://someIntroducer/secret', html)
+            self.failUnless(re.search('<div class="status-indicator connected-no"></div>[ ]*<div>Introducer not connected</div>', html), res)
+        d.addCallback(_check_introducer_not_connected_unguessable)
+
+        # introducer connected, unguessable furl
+        def _set_introducer_connected_unguessable(ign):
+            self.s.introducer_furl = "pb://someIntroducer/secret"
+            self.s.introducer_client = MockIntroducerClient(True)
+            return self.GET("/")
+        d.addCallback(_set_introducer_connected_unguessable)
+        def _check_introducer_connected_unguessable(res):
+            html = res.replace('\n', ' ')
+            self.failUnlessIn('<div class="furl">pb://someIntroducer/[censored]</div>', html)
+            self.failIfIn('pb://someIntroducer/secret', html)
+            self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Introducer</div>', html), res)
+        d.addCallback(_check_introducer_connected_unguessable)
+
+        # introducer connected, guessable furl
+        def _set_introducer_connected_guessable(ign):
+            self.s.introducer_furl = "pb://someIntroducer/introducer"
+            self.s.introducer_client = MockIntroducerClient(True)
+            return self.GET("/")
+        d.addCallback(_set_introducer_connected_guessable)
+        def _check_introducer_connected_guessable(res):
+            html = res.replace('\n', ' ')
+            self.failUnlessIn('<div class="furl">pb://someIntroducer/introducer</div>', html)
+            self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Introducer</div>', html), res)
+        d.addCallback(_check_introducer_connected_guessable)
+        return d
+
     def test_helper_status(self):
         d = defer.succeed(None)
 
@@ -632,23 +680,27 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
 
         # enable helper, not connected
         def _set_helper_not_connected(ign):
-            self.s.uploader.helper_furl = "pb://someHelper"
+            self.s.uploader.helper_furl = "pb://someHelper/secret"
             self.s.uploader.helper_connected = False
             return self.GET("/")
         d.addCallback(_set_helper_not_connected)
         def _check_helper_not_connected(res):
             html = res.replace('\n', ' ')
+            self.failUnlessIn('<div class="furl">pb://someHelper/[censored]</div>', html)
+            self.failIfIn('pb://someHelper/secret', html)
             self.failUnless(re.search('<div class="status-indicator connected-no"></div>[ ]*<div>Helper not connected</div>', html), res)
         d.addCallback(_check_helper_not_connected)
 
         # enable helper, connected
         def _set_helper_connected(ign):
-            self.s.uploader.helper_furl = "pb://someHelper"
+            self.s.uploader.helper_furl = "pb://someHelper/secret"
             self.s.uploader.helper_connected = True
             return self.GET("/")
         d.addCallback(_set_helper_connected)
         def _check_helper_connected(res):
             html = res.replace('\n', ' ')
+            self.failUnlessIn('<div class="furl">pb://someHelper/[censored]</div>', html)
+            self.failIfIn('pb://someHelper/secret', html)
             self.failUnless(re.search('<div class="status-indicator connected-yes"></div>[ ]*<div>Helper</div>', html), res)
         d.addCallback(_check_helper_connected)
         return d
diff --git a/src/allmydata/web/root.py b/src/allmydata/web/root.py
index c23d39ce..1895d067 100644
--- a/src/allmydata/web/root.py
+++ b/src/allmydata/web/root.py
@@ -198,8 +198,16 @@ class Root(rend.Page):
 
         return ctx.tag[ul]
 
-    def data_introducer_furl(self, ctx, data):
-        return self.client.introducer_furl
+    def data_introducer_furl_prefix(self, ctx, data):
+        ifurl = self.client.introducer_furl
+        # trim off the secret swissnum
+        (prefix, _, swissnum) = ifurl.rpartition("/")
+        if not ifurl:
+            return None
+        if swissnum == "introducer":
+            return ifurl
+        else:
+            return "%s/[censored]" % (prefix,)
 
     def data_introducer_description(self, ctx, data):
         if self.data_connected_to_introducer(ctx, data) == "no":
@@ -211,13 +219,17 @@ class Root(rend.Page):
             return "yes"
         return "no"
 
-    def data_helper_furl(self, ctx, data):
+    def data_helper_furl_prefix(self, ctx, data):
         try:
             uploader = self.client.getServiceNamed("uploader")
         except KeyError:
             return None
         furl, connected = uploader.get_helper_info()
-        return furl
+        if not furl:
+            return None
+        # trim off the secret swissnum
+        (prefix, _, swissnum) = furl.rpartition("/")
+        return "%s/[censored]" % (prefix,)
 
     def data_helper_description(self, ctx, data):
         if self.data_connected_to_helper(ctx, data) == "no":
diff --git a/src/allmydata/web/welcome.xhtml b/src/allmydata/web/welcome.xhtml
index 439bfbe3..1c794e44 100644
--- a/src/allmydata/web/welcome.xhtml
+++ b/src/allmydata/web/welcome.xhtml
@@ -139,14 +139,14 @@
                     <div><n:attr name="class">status-indicator connected-<n:invisible n:render="string" n:data="connected_to_introducer" /></n:attr></div>
                     <div n:render="string" n:data="introducer_description" />
                   </h3>
-                  <div class="furl" n:render="string" n:data="introducer_furl" />
+                  <div class="furl" n:render="string" n:data="introducer_furl_prefix" />
                 </div>
                 <div>
                   <h3>
                     <div><n:attr name="class">status-indicator connected-<n:invisible n:render="string" n:data="connected_to_helper" /></n:attr></div>
                     <div n:render="string" n:data="helper_description" />
                   </h3>
-                  <div class="furl" n:render="string" n:data="helper_furl" />
+                  <div class="furl" n:render="string" n:data="helper_furl_prefix" />
                 </div>
               </div><!--/span-->
               <div class="span6">
-- 
2.45.2