[tahoe-dev] uricap.diff.txt
zooko
zooko at zooko.com
Fri May 16 11:51:42 PDT 2008
Brian:
Here is a diff of a change that I made that might interact with the
webish.py refactoring that you are doing.
The idea is: start accepting "cap" instead of "uri" in all of the
various places where it matters (while still generating "uri" for
backwards compatibility). This patch also generalizes and fixes the
regex for URL caps per Ben Laurie's suggestion [1].
This patch also refactors uri.py to have separate notions of
encodings of caps "for humans" and encodings of caps "for
computers". The latter may in the future be more highly compressed.
This patch is fairly complete, but I think I didn't get it passing
all of its unit tests because I couldn't figure out something about
control flow in webish.py.
This patch is one of those "forward compatibility" things that makes
me want to put it into the next Tahoe release.
Regards,
Zooko
[1] http://allmydata.org/pipermail/tahoe-dev/2008-April/000511.html
-------
diff -rN -u old-trunk-uri_cap/src/allmydata/test/test_uri.py new-
trunk-uri_cap/src/allmydata/test/test_uri.py
--- old-trunk-uri_cap/src/allmydata/test/test_uri.py 2008-05-16
12:40:05.000000000 -0600
+++ new-trunk-uri_cap/src/allmydata/test/test_uri.py 2008-05-16
12:40:06.000000000 -0600
@@ -29,17 +29,46 @@
self.failUnlessIdentical(u, u3)
self.failUnlessEqual(u.get_verifier(), None)
+ def _help_test_humanencoding(self, data):
+ u0 = uri.LiteralFileURI(data)
+ lcap = u0.to_human_encoding()
+
+ def _t(u):
+ self.failUnless(IURI.providedBy(u))
+ self.failUnless(IFileURI.providedBy(u))
+ self.failIf(IDirnodeURI.providedBy(u))
+ self.failUnlessEqual(u.data, data)
+ self.failUnlessEqual(u.get_size(), len(data))
+ self.failUnless(u.is_readonly())
+ self.failIf(u.is_mutable())
+
+ u = uri.LiteralFileURI.init_from_human_encoding(lcap)
+ _t(u)
+
+ u2 = uri.from_human_encoding(u.to_string())
+ _t(u2)
+
+ u3 = uri.from_human_encoding(u.to_human_encoding())
+ _t(u3)
+
+ u4 = u.get_readonly()
+ self.failUnlessIdentical(u, u4)
+ self.failUnlessEqual(u.get_verifier(), None)
+
def test_empty(self):
data = "" # This data is some *very* small data!
- return self._help_test(data)
+ self._help_test(data)
+ self._help_test_humanencoding(data)
def test_pack(self):
data = "This is some small data"
- return self._help_test(data)
+ self._help_test(data)
+ self._help_test_humanencoding(data)
def test_nonascii(self):
data = "This contains \x00 and URI:LIT: and \n, oh my."
- return self._help_test(data)
+ self._help_test(data)
+ self._help_test_humanencoding(data)
class Compare(unittest.TestCase):
def test_compare(self):
@@ -86,21 +115,30 @@
u1a = IFileURI(u.to_string())
self.failUnlessEqual(u1a, u)
+ def _t(u):
+ self.failUnlessEqual(u.storage_index, storage_index)
+ self.failUnlessEqual(u.key, key)
+ self.failUnlessEqual(u.uri_extension_hash,
uri_extension_hash)
+ self.failUnlessEqual(u.needed_shares, needed_shares)
+ self.failUnlessEqual(u.total_shares, total_shares)
+ self.failUnlessEqual(u.size, size)
+ self.failUnless(u.is_readonly())
+ self.failIf(u.is_mutable())
+ self.failUnless(IURI.providedBy(u))
+ self.failUnless(IFileURI.providedBy(u))
+ self.failIf(IDirnodeURI.providedBy(u))
+ self.failUnlessEqual(u.get_size(), 1234)
+ self.failUnless(u.is_readonly())
+ self.failIf(u.is_mutable())
+
u2 = uri.from_string(u.to_string())
- self.failUnlessEqual(u2.storage_index, storage_index)
- self.failUnlessEqual(u2.key, key)
- self.failUnlessEqual(u2.uri_extension_hash, uri_extension_hash)
- self.failUnlessEqual(u2.needed_shares, needed_shares)
- self.failUnlessEqual(u2.total_shares, total_shares)
- self.failUnlessEqual(u2.size, size)
- self.failUnless(u2.is_readonly())
- self.failIf(u2.is_mutable())
- self.failUnless(IURI.providedBy(u2))
- self.failUnless(IFileURI.providedBy(u2))
- self.failIf(IDirnodeURI.providedBy(u2))
- self.failUnlessEqual(u2.get_size(), 1234)
- self.failUnless(u2.is_readonly())
- self.failIf(u2.is_mutable())
+ _t(u2)
+
+ u3 = uri.from_human_encoding(u.to_human_encoding())
+ _t(u3)
+
+ u4 = uri.from_human_encoding(u.to_string())
+ _t(u4)
v = u.get_verifier()
self.failUnless(isinstance(v.to_string(), str))
@@ -163,13 +201,17 @@
def test_create_invalid(self):
not_uri = "I am not a URI"
self.failUnlessRaises(TypeError, uri.from_string, not_uri)
+ self.failUnlessRaises(TypeError, uri.from_human_encoding,
not_uri)
class Constraint(unittest.TestCase):
def test_constraint(self):
good="http://127.0.0.1:8123/uri/URI%3ADIR2%
3Agh3l5rbvnv2333mrfvalmjfr4i%
3Alz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma/"
+ good2="http://127.0.0.1:8123/cap/CAP%3ADIR2%
3Agh3l5rbvnv2333mrfvalmjfr4i%
3Alz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma/"
uri.NewDirectoryURI.init_from_human_encoding(good)
+ uri.NewDirectoryURI.init_from_human_encoding(good2)
self.failUnlessRaises(AssertionError,
uri.NewDirectoryURI.init_from_string, good)
+ self.failUnlessRaises(AssertionError,
uri.NewDirectoryURI.init_from_string, good2)
bad = good + '==='
self.failUnlessRaises(AssertionError,
uri.NewDirectoryURI.init_from_human_encoding, bad)
self.failUnlessRaises(AssertionError,
uri.NewDirectoryURI.init_from_string, bad)
@@ -193,45 +235,64 @@
u1a = IMutableFileURI(u.to_string())
self.failUnlessEqual(u1a, u)
+ def _t(u):
+ self.failUnlessEqual(u.writekey, writekey)
+ self.failUnlessEqual(u.fingerprint, fingerprint)
+ self.failIf(u.is_readonly())
+ self.failUnless(u.is_mutable())
+ self.failUnless(IURI.providedBy(u))
+ self.failUnless(IMutableFileURI.providedBy(u))
+ self.failIf(IDirnodeURI.providedBy(u))
+
u2 = uri.from_string(u.to_string())
- self.failUnlessEqual(u2.writekey, writekey)
- self.failUnlessEqual(u2.fingerprint, fingerprint)
- self.failIf(u2.is_readonly())
- self.failUnless(u2.is_mutable())
- self.failUnless(IURI.providedBy(u2))
- self.failUnless(IMutableFileURI.providedBy(u2))
- self.failIf(IDirnodeURI.providedBy(u2))
+ _t(u2)
+
+ u2h = uri.from_human_encoding(u.to_human_encoding())
+ _t(u2h)
+
+ u2hs = uri.from_human_encoding(u.to_string())
+ _t(u2hs)
- u3 = u2.get_readonly()
readkey = hashutil.ssk_readkey_hash(writekey)
- self.failUnlessEqual(u3.fingerprint, fingerprint)
- self.failUnlessEqual(u3.readkey, readkey)
- self.failUnless(u3.is_readonly())
- self.failUnless(u3.is_mutable())
- self.failUnless(IURI.providedBy(u3))
- self.failUnless(IMutableFileURI.providedBy(u3))
- self.failIf(IDirnodeURI.providedBy(u3))
+ def _tr(u):
+ self.failUnlessEqual(u.fingerprint, fingerprint)
+ self.failUnlessEqual(u.readkey, readkey)
+ self.failUnless(u.is_readonly())
+ self.failUnless(u.is_mutable())
+ self.failUnless(IURI.providedBy(u))
+ self.failUnless(IMutableFileURI.providedBy(u))
+ self.failIf(IDirnodeURI.providedBy(u))
+
+ u3 = u2.get_readonly()
+ _tr(u3)
u4 = uri.ReadonlySSKFileURI(readkey, fingerprint)
- self.failUnlessEqual(u4.fingerprint, fingerprint)
- self.failUnlessEqual(u4.readkey, readkey)
- self.failUnless(u4.is_readonly())
- self.failUnless(u4.is_mutable())
- self.failUnless(IURI.providedBy(u4))
- self.failUnless(IMutableFileURI.providedBy(u4))
- self.failIf(IDirnodeURI.providedBy(u4))
+ _tr(u4)
u4a = uri.from_string(u4.to_string())
self.failUnlessEqual(u4a, u4)
self.failUnless("ReadonlySSKFileURI" in str(u4a))
self.failUnlessIdentical(u4a.get_readonly(), u4a)
+ u4h = uri.from_human_encoding(u4.to_human_encoding())
+ self.failUnlessEqual(u4h, u4)
+ self.failUnless("ReadonlySSKFileURI" in str(u4h))
+ self.failUnlessIdentical(u4h.get_readonly(), u4h)
+
+ u4hs = uri.from_human_encoding(u4.to_string())
+ self.failUnlessEqual(u4hs, u4)
+ self.failUnless("ReadonlySSKFileURI" in str(u4hs))
+ self.failUnlessIdentical(u4hs.get_readonly(), u4hs)
+
u5 = u4.get_verifier()
self.failUnless(IVerifierURI.providedBy(u5))
self.failUnlessEqual(u5.storage_index, u.storage_index)
u6 = IVerifierURI(u5.to_string())
self.failUnless(IVerifierURI.providedBy(u6))
self.failUnlessEqual(u6.storage_index, u.storage_index)
+ u6h = uri.from_human_encoding(u5.to_human_encoding())
+ self.failUnless(IVerifierURI.providedBy(u6h))
+ self.failUnlessEqual(u6h.storage_index, u.storage_index)
u7 = u.get_verifier()
self.failUnless(IVerifierURI.providedBy(u7))
self.failUnlessEqual(u7.storage_index, u.storage_index)
@@ -256,13 +317,19 @@
u1a = IDirnodeURI(u1.to_string())
self.failUnlessEqual(u1a, u1)
+ def _t(u):
+ self.failUnlessEqual(u1.to_string(), u.to_string())
+ self.failIf(u.is_readonly())
+ self.failUnless(u.is_mutable())
+ self.failUnless(IURI.providedBy(u))
+ self.failIf(IFileURI.providedBy(u))
+ self.failUnless(IDirnodeURI.providedBy(u))
+
u2 = uri.from_string(u1.to_string())
- self.failUnlessEqual(u1.to_string(), u2.to_string())
- self.failIf(u2.is_readonly())
- self.failUnless(u2.is_mutable())
- self.failUnless(IURI.providedBy(u2))
- self.failIf(IFileURI.providedBy(u2))
- self.failUnless(IDirnodeURI.providedBy(u2))
+ _t(u2)
+
+ u2h = uri.from_human_encoding(u1.to_human_encoding())
+ _t(u2h)
u3 = u2.get_readonly()
self.failUnless(u3.is_readonly())
@@ -280,8 +347,15 @@
u3a = uri.from_string(u3.to_string())
self.failUnlessIdentical(u3a, u3a.get_readonly())
+ u3h = uri.from_human_encoding(u3.to_human_encoding())
+ self.failUnlessIdentical(u3h, u3h.get_readonly())
+
+ u3hs = uri.from_human_encoding(u3.to_string())
+ self.failUnlessIdentical(u3hs, u3hs.get_readonly())
+
u4 = uri.ReadonlyNewDirectoryURI
(u2._filenode_uri.get_readonly())
self.failUnlessEqual(u4.to_string(), u3.to_string())
+ self.failUnlessEqual(u4.to_human_encoding(),
u3.to_human_encoding())
self.failUnless(u4.is_readonly())
self.failUnless(u4.is_mutable())
self.failUnless(IURI.providedBy(u4))
diff -rN -u old-trunk-uri_cap/src/allmydata/uri.py new-trunk-uri_cap/
src/allmydata/uri.py
--- old-trunk-uri_cap/src/allmydata/uri.py 2008-05-16
12:40:05.000000000 -0600
+++ new-trunk-uri_cap/src/allmydata/uri.py 2008-05-16
12:40:06.000000000 -0600
@@ -14,12 +14,13 @@
BASE32STR_128bits = '(%s{25}%s)' % (base32.BASE32CHAR,
base32.BASE32CHAR_3bits)
BASE32STR_256bits = '(%s{51}%s)' % (base32.BASE32CHAR,
base32.BASE32CHAR_1bits)
+URI='(?:URI|CAP)'
SEP='(?::|%3A)'
NUMBER='([0-9]+)'
# URIs (soon to be renamed "caps") are always allowed to come with
a leading
# 'http://127.0.0.1:8123/uri/' that will be ignored.
-OPTIONALHTTPLEAD=r'(?:https?://(127.0.0.1|localhost):8123/uri/)?'
+OPTIONALHTTPLEAD=r'(?:https?://(?:127.0.0.1|localhost):8123/(?:uri|
cap)/)?'
class _BaseURI:
@@ -33,14 +34,18 @@
return cmp(self.to_string(), them.to_string())
def to_human_encoding(self):
return 'http://127.0.0.1:8123/uri/'+self.to_string()
+ # def __repr__(self):
+ # return "%s(%s)" % (self.__class__.__name__,
self.to_human_encoding())
+ # def __str__(self):
+ # return self.to_human_encoding()
class CHKFileURI(_BaseURI):
implements(IURI, IFileURI)
- STRING_RE=re.compile('^URI:CHK:'+BASE32STR_128bits+':'+
+ STRING_RE=re.compile('^'+URI+':CHK:'+BASE32STR_128bits+':'+
BASE32STR_256bits+':'+NUMBER+':'+NUMBER
+':'+NUMBER+
'$')
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'CHK'+SEP+
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'CHK'+SEP+
BASE32STR_128bits+SEP+BASE32STR_256bits+SEP
+NUMBER+
SEP+NUMBER+SEP+NUMBER+'$')
@@ -56,12 +61,19 @@
self.storage_index = hashutil.storage_index_hash(key)
assert len(self.storage_index) == 16 # sha256 hash
truncated to 128
+ def abbrev(self):
+ return base32.b2a(self.storage_index)
+
@classmethod
def init_from_human_encoding(cls, uri):
mo = cls.HUMAN_RE.search(uri)
assert mo, uri
- return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)),
- int(mo.group(3)), int(mo.group(4)), int(mo.group
(5)))
+ k = mo.group(1)
+ assert k
+ h = mo.group(2)
+ assert h
+ return cls(base32.a2b(k), base32.a2b(h), int(mo.group(3)),
+ int(mo.group(4)), int(mo.group(5)))
@classmethod
def init_from_string(cls, uri):
@@ -102,9 +114,9 @@
class CHKFileVerifierURI(_BaseURI):
implements(IVerifierURI)
- STRING_RE=re.compile('^URI:CHK-Verifier:'+BASE32STR_128bits+':'+
+ STRING_RE=re.compile('^'+URI+':CHK-Verifier:'+BASE32STR_128bits
+':'+
BASE32STR_256bits+':'+NUMBER+':'+NUMBER
+':'+NUMBER)
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'CHK-
Verifier'+SEP+
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'CHK-
Verifier'+SEP+
BASE32STR_128bits+SEP+BASE32STR_256bits+SEP
+NUMBER+
SEP+NUMBER+SEP+NUMBER)
@@ -147,8 +159,8 @@
class LiteralFileURI(_BaseURI):
implements(IURI, IFileURI)
- STRING_RE=re.compile('^URI:LIT:'+base32.BASE32STR_anybytes+'$')
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'LIT'+SEP
+base32.BASE32STR_anybytes+'$')
+ STRING_RE=re.compile('^'+URI+':LIT:'+base32.BASE32STR_anybytes+'$')
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'LIT'+SEP
+base32.BASE32STR_anybytes+'$')
def __init__(self, data=None):
if data is not None:
@@ -186,10 +198,11 @@
class WriteableSSKFileURI(_BaseURI):
implements(IURI, IMutableFileURI)
- BASE_STRING='URI:SSK:'
- STRING_RE=re.compile('^'+BASE_STRING+BASE32STR_128bits+':'+
+ BASE_STR='URI:SSK:' # produce this string
+ BASE_STR_OPT=URI+':SSK:' # accept this regex
+ STRING_RE=re.compile('^'+BASE_STR_OPT+BASE32STR_128bits+':'+
BASE32STR_256bits+'$')
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'SSK'+SEP+
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'SSK'+SEP+
BASE32STR_128bits+SEP+BASE32STR_256bits+'$')
def __init__(self, writekey, fingerprint):
@@ -217,9 +230,6 @@
return 'URI:SSK:%s:%s' % (base32.b2a(self.writekey),
base32.b2a(self.fingerprint))
- def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.abbrev())
-
def abbrev(self):
return base32.b2a(self.writekey[:5])
@@ -235,9 +245,10 @@
class ReadonlySSKFileURI(_BaseURI):
implements(IURI, IMutableFileURI)
- BASE_STRING='URI:SSK-RO:'
- STRING_RE=re.compile('^URI:SSK-RO:'+BASE32STR_128bits
+':'+BASE32STR_256bits+'$')
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'SSK-RO'+SEP
+BASE32STR_128bits+SEP+BASE32STR_256bits+'$')
+ BASE_STR='URI:SSK-RO:' # produce this str
+ BASE_STR_OPT=URI+':SSK-RO:' # accept this regex
+ STRING_RE=re.compile('^'+BASE_STR_OPT+BASE32STR_128bits
+':'+BASE32STR_256bits+'$')
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'SSK-RO'+SEP
+BASE32STR_128bits+SEP+BASE32STR_256bits+'$')
def __init__(self, readkey, fingerprint):
self.readkey = readkey
@@ -263,9 +274,6 @@
return 'URI:SSK-RO:%s:%s' % (base32.b2a(self.readkey),
base32.b2a(self.fingerprint))
- def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.abbrev())
-
def abbrev(self):
return base32.b2a(self.readkey[:5])
@@ -281,9 +289,10 @@
class SSKVerifierURI(_BaseURI):
implements(IVerifierURI)
- BASE_STRING='URI:SSK-Verifier:'
- STRING_RE=re.compile('^'+BASE_STRING+BASE32STR_128bits
+':'+BASE32STR_256bits+'$')
- HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'SSK-RO'+SEP
+BASE32STR_128bits+SEP+BASE32STR_256bits+'$')
+ BASE_STR='URI:SSK-Verifier:' # produce this str
+ BASE_STR_OPT=URI+':SSK-Verifier:' # accept this regex
+ STRING_RE=re.compile('^'+BASE_STR_OPT+BASE32STR_128bits
+':'+BASE32STR_256bits+'$')
+ HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'SSK-
Verifier'+SEP+BASE32STR_128bits+SEP+BASE32STR_256bits+'$')
def __init__(self, storage_index, fingerprint):
assert len(storage_index) == 16
@@ -313,16 +322,13 @@
def __init__(self, filenode_uri=None):
self._filenode_uri = filenode_uri
- def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.abbrev())
-
@classmethod
def init_from_string(cls, uri):
- mo = cls.BASE_STRING_RE.search(uri)
+ mo = re.search(cls.BASE_STR_OPT, uri)
assert mo, (uri, cls)
bits = uri[mo.end():]
fn = cls.INNER_URI_CLASS.init_from_string(
- cls.INNER_URI_CLASS.BASE_STRING+bits)
+ cls.INNER_URI_CLASS.BASE_STR+bits)
return cls(fn)
@classmethod
@@ -333,15 +339,15 @@
while bits and bits[-1] == '/':
bits = bits[:-1]
fn = cls.INNER_URI_CLASS.init_from_string(
- cls.INNER_URI_CLASS.BASE_STRING+urllib.unquote(bits))
+ cls.INNER_URI_CLASS.BASE_STR+urllib.unquote(bits))
return cls(fn)
def to_string(self):
fnuri = self._filenode_uri.to_string()
- mo = re.match(self.INNER_URI_CLASS.BASE_STRING, fnuri)
+ mo = re.match(self.INNER_URI_CLASS.BASE_STR_OPT, fnuri)
assert mo, fnuri
bits = fnuri[mo.end():]
- return self.BASE_STRING+bits
+ return self.BASE_STR+bits
def abbrev(self):
return self._filenode_uri.to_string().split(':')[2][:5]
@@ -358,9 +364,10 @@
class NewDirectoryURI(_NewDirectoryBaseURI):
implements(INewDirectoryURI)
- BASE_STRING='URI:DIR2:'
- BASE_STRING_RE=re.compile('^'+BASE_STRING)
- BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'DIR2'+SEP)
+ BASE_STR='URI:DIR2:' # produce this str
+ BASE_STR_OPT=URI+':DIR2:' # accept this regex
+ BASE_STRING_RE=re.compile('^'+BASE_STR_OPT)
+ BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'DIR2'+SEP)
INNER_URI_CLASS=WriteableSSKFileURI
def __init__(self, filenode_uri=None):
@@ -377,9 +384,10 @@
class ReadonlyNewDirectoryURI(_NewDirectoryBaseURI):
implements(IReadonlyNewDirectoryURI)
- BASE_STRING='URI:DIR2-RO:'
- BASE_STRING_RE=re.compile('^'+BASE_STRING)
- BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'DIR2-
RO'+SEP)
+ BASE_STR='URI:DIR2-RO:' # produce this str
+ BASE_STR_OPT=URI+':DIR2-RO:' # accept this regex
+ BASE_STRING_RE=re.compile('^'+BASE_STR_OPT)
+ BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'DIR2-
RO'+SEP)
INNER_URI_CLASS=ReadonlySSKFileURI
def __init__(self, filenode_uri=None):
@@ -396,9 +404,10 @@
class NewDirectoryURIVerifier(_NewDirectoryBaseURI):
implements(IVerifierURI)
- BASE_STRING='URI:DIR2-Verifier:'
- BASE_STRING_RE=re.compile('^'+BASE_STRING)
- BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+'URI'+SEP+'DIR2-
Verifier'+SEP)
+ BASE_STR='URI:DIR2-Verifier:' # produce this str
+ BASE_STR_OPT=URI+':DIR2-Verifier:' # accept this regex
+ BASE_STRING_RE=re.compile('^'+BASE_STR_OPT)
+ BASE_HUMAN_RE=re.compile('^'+OPTIONALHTTPLEAD+URI+SEP+'DIR2-
Verifier'+SEP)
INNER_URI_CLASS=SSKVerifierURI
def __init__(self, filenode_uri=None):
@@ -412,29 +421,65 @@
def from_string(s):
- if s.startswith('URI:CHK:'):
+ mo = re.match(URI, s)
+ if not mo:
+ raise TypeError("badly formed capability: %s" % s)
+ if s[mo.end(0)] != ':':
+ raise TypeError("badly formed capability: %s" % s)
+ typespec = s[mo.end(0)+1:]
+ if typespec.startswith('CHK:'):
return CHKFileURI.init_from_string(s)
- elif s.startswith('URI:CHK-Verifier:'):
+ elif typespec.startswith('CHK-Verifier:'):
return CHKFileVerifierURI.init_from_string(s)
- elif s.startswith('URI:LIT:'):
+ elif typespec.startswith('LIT:'):
return LiteralFileURI.init_from_string(s)
- elif s.startswith('URI:SSK:'):
+ elif typespec.startswith('SSK:'):
return WriteableSSKFileURI.init_from_string(s)
- elif s.startswith('URI:SSK-RO:'):
+ elif typespec.startswith('SSK-RO:'):
return ReadonlySSKFileURI.init_from_string(s)
- elif s.startswith('URI:SSK-Verifier:'):
+ elif typespec.startswith('SSK-Verifier:'):
return SSKVerifierURI.init_from_string(s)
- elif s.startswith('URI:DIR2:'):
+ elif typespec.startswith('DIR2:'):
return NewDirectoryURI.init_from_string(s)
- elif s.startswith('URI:DIR2-RO:'):
+ elif typespec.startswith('DIR2-RO:'):
return ReadonlyNewDirectoryURI.init_from_string(s)
- elif s.startswith('URI:DIR2-Verifier:'):
+ elif typespec.startswith('DIR2-Verifier:'):
return NewDirectoryURIVerifier.init_from_string(s)
else:
- raise TypeError("unknown URI type: %s.." % s[:12])
+ raise TypeError("unknown capability type: %s" % s)
registerAdapter(from_string, str, IURI)
+def from_human_encoding(s):
+ assert isinstance(s, basestring), "precondition: s is required
to be a string, but it was %s :: %s" % (s, type(s))
+ mo = re.match(OPTIONALHTTPLEAD, s)
+ if mo:
+ s = s[mo.end(0):]
+ mo = re.match(URI+SEP, s)
+ if not mo:
+ raise TypeError("ill-formed capability %r" % s)
+ typespec = s[mo.end(0):]
+ if typespec.startswith('CHK:'):
+ return CHKFileURI.init_from_human_encoding(s)
+ elif typespec.startswith('CHK-Verifier:'):
+ return CHKFileVerifierURI.init_from_human_encoding(s)
+ elif typespec.startswith('LIT:'):
+ return LiteralFileURI.init_from_human_encoding(s)
+ elif typespec.startswith('SSK:'):
+ return WriteableSSKFileURI.init_from_human_encoding(s)
+ elif typespec.startswith('SSK-RO:'):
+ return ReadonlySSKFileURI.init_from_human_encoding(s)
+ elif typespec.startswith('SSK-Verifier:'):
+ return SSKVerifierURI.init_from_human_encoding(s)
+ elif typespec.startswith('DIR2:'):
+ return NewDirectoryURI.init_from_human_encoding(s)
+ elif typespec.startswith('DIR2-RO:'):
+ return ReadonlyNewDirectoryURI.init_from_human_encoding(s)
+ elif typespec.startswith('DIR2-Verifier:'):
+ return NewDirectoryURIVerifier.init_from_human_encoding(s)
+ else:
+ raise TypeError("unknown capability type: %s" % s)
+
def is_uri(s):
try:
uri = from_string(s)
@@ -442,6 +487,13 @@
except (TypeError, AssertionError):
return False
+def is_human_encoding(s):
+ try:
+ uri = from_human_encoding(s)
+ return True
+ except (TypeError, AssertionError):
+ return False
+
def from_string_dirnode(s):
u = from_string(s)
assert IDirnodeURI.providedBy(u)
diff -rN -u old-trunk-uri_cap/src/allmydata/webish.py new-trunk-
uri_cap/src/allmydata/webish.py
--- old-trunk-uri_cap/src/allmydata/webish.py 2008-05-16
12:40:05.000000000 -0600
+++ new-trunk-uri_cap/src/allmydata/webish.py 2008-05-16
12:40:06.000000000 -0600
@@ -12,6 +12,7 @@
IMutableFileNode
import allmydata # to display import path
from allmydata import download
+from allmydata import uri as urimodule
from allmydata.upload import FileHandle, FileName
from allmydata import provisioning
from allmydata import get_package_versions_string
@@ -143,15 +144,19 @@
# sure we censor these too.
if queryargs.startswith("uri="):
queryargs = "[uri=CENSORED]"
+ if queryargs.startswith("cap="):
+ queryargs = "[cap=CENSORED]"
queryargs = "?" + queryargs
if path.startswith("/uri"):
path = "/uri/[CENSORED].."
- uri = path + queryargs
+ if path.startswith("/cap"):
+ path = "/cap/[CENSORED].."
+ theuri = path + queryargs
log.msg(format="web: %(clientip)s %(method)s %(uri)s %(code)
s %(length)s",
clientip=self.getClientIP(),
method=self.method,
- uri=uri,
+ uri=theuri,
code=self.code,
length=(self.sentLength or "-"),
facility="tahoe.webish",
@@ -827,11 +832,16 @@
d = self._check_replacement(name)
d.addCallback(lambda res:
self._node.create_empty_directory(name))
d.addCallback(lambda res: "directory created")
- elif t == "uri":
+ elif t == "uri" or t == "cap":
if not name:
raise RuntimeError("set-uri requires a name")
- newuri = get_arg(req, "uri")
- assert newuri is not None
+ newuristr = get_arg(req, "uri")
+ assert isinstance(newuristr, basestring), (repr
(newuristr), type(newuristr))
+ assert urimodule.is_human_encoding(newuristr), (repr
(newuristr), type(newuristr))
+ if newuristr is None:
+ newuristr = get_arg(req, "cap")
+ newuri = urimodule.from_human_encoding(newuristr)
+
d = self._check_replacement(name)
d.addCallback(lambda res: self._node.set_uri(name,
newuri))
d.addCallback(lambda res: newuri)
@@ -1018,7 +1028,7 @@
# take the last step
d.addCallback(self._get_or_create_directories,
self._path[-1:])
d.addCallback(self._upload_localdir, localdir)
- elif t == "uri":
+ elif t == "uri" or t == "cap":
d.addCallback(self._attach_uri, req.content, name)
elif t == "mkdir":
d.addCallback(self._mkdir, name)
@@ -1240,9 +1250,9 @@
return FileDownloader(node, filename), ()
elif t == "json":
return FileJSONMetadata(node), ()
- elif t == "uri":
+ elif t == "uri" or t == "cap":
return FileURI(node), ()
- elif t == "readonly-uri":
+ elif t == "readonly-uri" or t == "readonly-cap":
return FileReadOnlyURI(node), ()
else:
return child_error("bad t=%s" % t)
@@ -1257,9 +1267,9 @@
return Directory(self.name, node, path), ()
elif t == "json":
return DirectoryJSONMetadata(node), ()
- elif t == "uri":
+ elif t == "uri" or t == "cap":
return DirectoryURI(node), ()
- elif t == "readonly-uri":
+ elif t == "readonly-uri" or t == "readonly-cap":
return DirectoryReadonlyURI(node), ()
elif t == "manifest":
return Manifest(node, path), ()
@@ -1623,13 +1633,19 @@
segments.append('')
segments = tuple(segments)
if segments:
- if segments[0] == "uri":
+ if (segments[0] == "uri") or (segments[0] == "cap"):
if len(segments) == 1 or segments[1] == '':
- uri = get_arg(req, "uri", None)
- if uri is not None:
+ uristr = get_arg(req, "uri", None)
+ if uristr is not None:
there = url.URL.fromContext(ctx)
there = there.clear("uri")
- there = there.child("uri").child(uri)
+ there = there.child("uri").child(uristr)
+ return there, ()
+ uristr = get_arg(req, "cap", None)
+ if uristr is not None:
+ there = url.URL.fromContext(ctx)
+ there = there.clear("cap")
+ there = there.child("cap").child(uristr)
return there, ()
if len(segments) == 1:
# /uri
@@ -1665,9 +1681,10 @@
return WebError(http.BAD_REQUEST, errmsg), ()
if len(segments) < 2:
return rend.NotFound
- uri = segments[1]
- d = defer.maybeDeferred(client.create_node_from_uri,
uri)
- d.addCallback(lambda node: VDrive(node, uri))
+ uristr = segments[1]
+ uriobj = urimodule.from_human_encoding(uristr)
+ d = defer.maybeDeferred(client.create_node_from_uri,
uristr)
+ d.addCallback(lambda node: VDrive(node, uristr))
d.addCallback(lambda vd: vd.locateChild(ctx,
segments[2:]))
def _trap_KeyError(f):
f.trap(KeyError)
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: uricap.diff.txt
Url: http://allmydata.org/pipermail/tahoe-dev/attachments/20080516/10f6407d/attachment-0001.txt
More information about the tahoe-dev
mailing list