4 from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \
6 from allmydata.scripts.common_http import do_http, format_http_error
7 from allmydata.util.encodingutil import unicode_to_output, quote_output, is_printable_ascii, to_str
10 nodeurl = options['node-url']
11 aliases = options.aliases
13 stdout = options.stdout
14 stderr = options.stderr
16 if not nodeurl.endswith("/"):
18 if where.endswith("/"):
21 rootcap, path = get_alias(aliases, where, DEFAULT_ALIAS)
22 except UnknownAliasError, e:
25 url = nodeurl + "uri/%s" % urllib.quote(rootcap)
27 # move where.endswith check here?
28 url += "/" + escape_path(path)
29 assert not url.endswith("/")
31 resp = do_http("GET", url)
32 if resp.status == 404:
33 print >>stderr, "No such file or directory"
35 if resp.status != 200:
36 print >>stderr, format_http_error("Error during GET", resp)
45 # The webapi server should always output printable ASCII.
46 if is_printable_ascii(data):
50 print >>stderr, "The JSON response contained unprintable characters:"
51 print >>stderr, quote_output(data, quotemarks=False)
55 parsed = simplejson.loads(data)
57 print >>stderr, "error: %s" % quote_output(e.args[0], quotemarks=False)
58 print >>stderr, "Could not parse JSON response:"
59 print >>stderr, quote_output(data, quotemarks=False)
64 if nodetype == "dirnode":
65 children = d['children']
67 # paths returned from get_alias are always valid UTF-8
68 childname = path.split("/")[-1].decode('utf-8')
69 children = {childname: (nodetype, d)}
70 if "metadata" not in d:
72 childnames = sorted(children.keys())
75 # we build up a series of rows, then we loop through them to compute a
76 # maxwidth so we can format them tightly. Size, filename, and URI are the
77 # variable-width ones.
81 for name in childnames:
82 child = children[name]
86 # See webapi.txt for a discussion of the meanings of unix local
87 # filesystem mtime and ctime, Tahoe mtime and ctime, and Tahoe
88 # linkmotime and linkcrtime.
89 ctime = child[1].get("metadata", {}).get('tahoe', {}).get("linkcrtime")
91 ctime = child[1]["metadata"].get("ctime")
93 mtime = child[1].get("metadata", {}).get('tahoe', {}).get("linkmotime")
95 mtime = child[1]["metadata"].get("mtime")
96 rw_uri = to_str(child[1].get("rw_uri"))
97 ro_uri = to_str(child[1].get("ro_uri"))
99 # match for formatting that GNU 'ls' does
100 if (now - ctime) > 6*30*24*60*60:
105 ctime_s = time.strftime(fmt, time.localtime(ctime))
108 if childtype == "dirnode":
112 elif childtype == "filenode":
114 size = str(child[1].get("size", "?"))
130 if childtype == "dirnode":
133 uri = rw_uri or ro_uri
137 line.append(t0+t1+t2+t3)
140 if not options["classify"]:
143 encoding_error = False
145 line.append(unicode_to_output(name) + classify)
146 except UnicodeEncodeError:
147 encoding_error = True
148 line.append(quote_output(name) + classify)
152 if options["readonly-uri"]:
153 line.append(quote_output(ro_uri or "-", quotemarks=False))
155 rows.append((encoding_error, line))
159 for (encoding_error, row) in rows:
160 for i,cell in enumerate(row):
161 while len(max_widths) <= i:
163 while len(left_justifys) <= i:
164 left_justifys.append(False)
165 max_widths[i] = max(max_widths[i], len(cell))
166 if cell.startswith("URI"):
167 left_justifys[i] = True
168 if len(left_justifys) == 1:
169 left_justifys[0] = True
171 for i in range(len(max_widths)):
175 piece += str(max_widths[i])
177 fmt_pieces.append(piece)
178 fmt = " ".join(fmt_pieces)
181 for (encoding_error, row) in rows:
183 print >>stderr, (fmt % tuple(row)).rstrip()
186 print >>stdout, (fmt % tuple(row)).rstrip()
189 print >>stderr, "\nThis listing included files whose names could not be converted to the terminal" \
190 "\noutput encoding. Their names are shown using backslash escapes and in quotes."
192 print >>stderr, "\nThis listing included unknown objects. Using a webapi server that supports" \
193 "\na later version of Tahoe may help."