From 0d4a826f0edfd7e26bd83be6a039cd5788e19c0e Mon Sep 17 00:00:00 2001
From: David-Sarah Hopwood <david-sarah@jacaranda.org>
Date: Thu, 27 Dec 2012 05:08:53 +0000
Subject: [PATCH] Allow welcome and storage status pages to display a non-ASCII
 node nickname. fixes #1298

Signed-off-by: David-Sarah Hopwood <davidsarah@jacaranda.org>
---
 src/allmydata/storage_client.py        |  2 +-
 src/allmydata/test/test_web.py         | 72 +++++++++++++++++++++++++-
 src/allmydata/web/introducer.xhtml     |  2 +-
 src/allmydata/web/storage_status.xhtml |  2 +-
 src/allmydata/web/welcome.xhtml        |  4 +-
 5 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/src/allmydata/storage_client.py b/src/allmydata/storage_client.py
index 4390baba..a0cd7dda 100644
--- a/src/allmydata/storage_client.py
+++ b/src/allmydata/storage_client.py
@@ -252,7 +252,7 @@ class NativeStorageServer:
         return self._tubid
 
     def get_nickname(self):
-        return self.announcement["nickname"].decode("utf-8")
+        return self.announcement["nickname"]
     def get_announcement(self):
         return self.announcement
     def get_remote_host(self):
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 146fdf2c..2c6c0ceb 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -166,6 +166,59 @@ class FakeHistory:
     def list_all_helper_statuses(self):
         return []
 
+class FakeDisplayableServer(StubServer):
+    def __init__(self, serverid, nickname):
+        StubServer.__init__(self, serverid)
+        self.announcement = {"my-version": "allmydata-tahoe-fake",
+                             "service-name": "storage",
+                             "nickname": nickname}
+    def is_connected(self):
+        return True
+    def get_permutation_seed(self):
+        return ""
+    def get_remote_host(self):
+        return ""
+    def get_last_loss_time(self):
+        return None
+    def get_announcement_time(self):
+        return None
+    def get_announcement(self):
+        return self.announcement
+    def get_nickname(self):
+        return self.announcement["nickname"]
+
+class FakeBucketCounter(object):
+    def get_state(self):
+        return {"last-complete-bucket-count": 0}
+    def get_progress(self):
+        return {"estimated-time-per-cycle": 0,
+                "cycle-in-progress": False,
+                "remaining-wait-time": 0}
+
+class FakeLeaseChecker(object):
+    def __init__(self):
+        self.expiration_enabled = False
+        self.mode = "age"
+        self.override_lease_duration = None
+        self.sharetypes_to_expire = {}
+    def get_state(self):
+        return {"history": None}
+    def get_progress(self):
+        return {"estimated-time-per-cycle": 0,
+                "cycle-in-progress": False,
+                "remaining-wait-time": 0}
+
+class FakeStorageServer(service.MultiService):
+    name = 'storage'
+    def __init__(self, nodeid, nickname):
+        service.MultiService.__init__(self)
+        self.my_nodeid = nodeid
+        self.nickname = nickname
+        self.bucket_counter = FakeBucketCounter()
+        self.lease_checker = FakeLeaseChecker()
+    def get_stats(self):
+        return {"storage_server.accepting_immutable_shares": False}
+
 class FakeClient(Client):
     def __init__(self):
         # don't upcall to Client.__init__, since we only want to initialize a
@@ -173,13 +226,16 @@ class FakeClient(Client):
         service.MultiService.__init__(self)
         self.all_contents = {}
         self.nodeid = "fake_nodeid"
-        self.nickname = "fake_nickname"
+        self.nickname = u"fake_nickname \u263A"
         self.introducer_furl = "None"
         self.stats_provider = FakeStatsProvider()
         self._secret_holder = SecretHolder("lease secret", "convergence secret")
         self.helper = None
         self.convergence = "some random string"
         self.storage_broker = StorageFarmBroker(None, permute_peers=True)
+        # fake knowledge of another server
+        self.storage_broker.test_add_server("other_nodeid",
+                                            FakeDisplayableServer("other_nodeid", u"other_nickname \u263B"))
         self.introducer_client = None
         self.history = FakeHistory()
         self.uploader = FakeUploader()
@@ -191,6 +247,7 @@ class FakeClient(Client):
                                        None, None, None)
         self.nodemaker.all_contents = self.all_contents
         self.mutable_file_default = SDMF_VERSION
+        self.addService(FakeStorageServer(self.nodeid, self.nickname))
 
     def startService(self):
         return service.MultiService.startService(self)
@@ -541,6 +598,9 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
             self.failUnlessIn('Welcome to Tahoe-LAFS', res)
             self.failUnlessIn(FAVICON_MARKUP, res)
             self.failUnlessIn('href="https://tahoe-lafs.org/"', res)
+            res_u = res.decode('utf-8')
+            self.failUnlessIn(u'<th>My nickname:</th> <td class="nickname mine">fake_nickname \u263A</td></tr>', res_u)
+            self.failUnlessIn(u'<div class="nickname">other_nickname \u263B</div>', res_u)
 
             self.s.basedir = 'web/test_welcome'
             fileutil.make_dirs("web/test_welcome")
@@ -549,6 +609,16 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
         d.addCallback(_check)
         return d
 
+    def test_storage(self):
+        d = self.GET("/storage")
+        def _check(res):
+            self.failUnlessIn('Storage Server Status', res)
+            self.failUnlessIn(FAVICON_MARKUP, res)
+            res_u = res.decode('utf-8')
+            self.failUnlessIn(u'<li>Server Nickname: <span class="nickname mine">fake_nickname \u263A</span></li>', res_u)
+        d.addCallback(_check)
+        return d
+
     def test_status(self):
         h = self.s.get_history()
         dl_num = h.list_all_download_statuses()[0].get_counter()
diff --git a/src/allmydata/web/introducer.xhtml b/src/allmydata/web/introducer.xhtml
index 6738a290..9be4388f 100644
--- a/src/allmydata/web/introducer.xhtml
+++ b/src/allmydata/web/introducer.xhtml
@@ -13,7 +13,7 @@
   <table class="node-info table-headings-left">
     <tr><th>My nodeid:</th> <td class="nodeid mine data-chars" n:render="string" n:data="my_nodeid" /></tr>
     <tr><th>My versions:</th> <td n:render="string" n:data="version" /></tr>
-    <tr><th>Tahoe-LAFS code imported from:</th> <td n:render="string" n:data="import_path" /></tr>
+    <tr><th>Tahoe-LAFS code imported from:</th> <td n:render="data" n:data="import_path" /></tr>
   </table>
 </div>
 
diff --git a/src/allmydata/web/storage_status.xhtml b/src/allmydata/web/storage_status.xhtml
index 19860a49..d97daf9a 100644
--- a/src/allmydata/web/storage_status.xhtml
+++ b/src/allmydata/web/storage_status.xhtml
@@ -55,7 +55,7 @@
   </table>
 
   <ul>
-    <li>Server Nickname: <span class="nickname mine" n:render="string" n:data="nickname" /></li>
+    <li>Server Nickname: <span class="nickname mine" n:render="data" n:data="nickname" /></li>
     <li>Server Nodeid: <span class="nodeid mine data-chars" n:render="string" n:data="nodeid" /></li>
     <li n:data="stats">Accepting new shares:
      <span n:render="bool" n:data="accepting_immutable_shares" /></li>
diff --git a/src/allmydata/web/welcome.xhtml b/src/allmydata/web/welcome.xhtml
index 16f2cb7e..b493ee79 100644
--- a/src/allmydata/web/welcome.xhtml
+++ b/src/allmydata/web/welcome.xhtml
@@ -16,10 +16,10 @@
   </p>
 
   <table class="node-info table-headings-left">
-    <tr><th>My nickname:</th> <td class="nickname mine" n:render="string" n:data="my_nickname" /></tr>
+    <tr><th>My nickname:</th> <td class="nickname mine" n:render="data" n:data="my_nickname" /></tr>
     <tr><th>My nodeid:</th> <td class="nodeid mine data-chars" n:render="string" n:data="my_nodeid" /></tr>
     <tr><th>My versions:</th> <td n:render="string" n:data="version" /></tr>
-    <tr><th>Tahoe-LAFS code imported from:</th> <td n:render="string" n:data="import_path" /></tr>
+    <tr><th>Tahoe-LAFS code imported from:</th> <td n:render="data" n:data="import_path" /></tr>
     <tr><th>Services running:</th> <td n:render="services" /></tr>
   </table>
 </div>
-- 
2.45.2