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:\n%s" % quote_output(data)
54 parsed = simplejson.loads(data)
56 print >>stderr, "error: %s" % quote_output(e.args[0], quotemarks=False)
57 print >>stderr, "Could not parse JSON response:\n%s" % quote_output(data)
62 if nodetype == "dirnode":
63 children = d['children']
65 # paths returned from get_alias are always valid UTF-8
66 childname = path.split("/")[-1].decode('utf-8')
67 children = {childname: (nodetype, d)}
68 if "metadata" not in d:
70 childnames = sorted(children.keys())
73 # we build up a series of rows, then we loop through them to compute a
74 # maxwidth so we can format them tightly. Size, filename, and URI are the
75 # variable-width ones.
79 for name in childnames:
80 child = children[name]
84 # See webapi.txt for a discussion of the meanings of unix local
85 # filesystem mtime and ctime, Tahoe mtime and ctime, and Tahoe
86 # linkmotime and linkcrtime.
87 ctime = child[1].get("metadata", {}).get('tahoe', {}).get("linkcrtime")
89 ctime = child[1]["metadata"].get("ctime")
91 mtime = child[1].get("metadata", {}).get('tahoe', {}).get("linkmotime")
93 mtime = child[1]["metadata"].get("mtime")
94 rw_uri = to_str(child[1].get("rw_uri"))
95 ro_uri = to_str(child[1].get("ro_uri"))
97 # match for formatting that GNU 'ls' does
98 if (now - ctime) > 6*30*24*60*60:
103 ctime_s = time.strftime(fmt, time.localtime(ctime))
106 if childtype == "dirnode":
110 elif childtype == "filenode":
112 size = str(child[1].get("size", "?"))
128 if childtype == "dirnode":
131 uri = rw_uri or ro_uri
135 line.append(t0+t1+t2+t3)
138 if not options["classify"]:
141 encoding_error = False
143 line.append(unicode_to_output(name) + classify)
144 except UnicodeEncodeError:
145 encoding_error = True
146 line.append(quote_output(name) + classify)
150 if options["readonly-uri"]:
151 line.append(quote_output(ro_uri or "-", quotemarks=False))
153 rows.append((encoding_error, line))
157 for (encoding_error, row) in rows:
158 for i,cell in enumerate(row):
159 while len(max_widths) <= i:
161 while len(left_justifys) <= i:
162 left_justifys.append(False)
163 max_widths[i] = max(max_widths[i], len(cell))
164 if cell.startswith("URI"):
165 left_justifys[i] = True
166 if len(left_justifys) == 1:
167 left_justifys[0] = True
169 for i in range(len(max_widths)):
173 piece += str(max_widths[i])
175 fmt_pieces.append(piece)
176 fmt = " ".join(fmt_pieces)
179 for (encoding_error, row) in rows:
181 print >>stderr, (fmt % tuple(row)).rstrip()
184 print >>stdout, (fmt % tuple(row)).rstrip()
187 print >>stderr, "\nThis listing included files whose names could not be converted to the terminal" \
188 "\noutput encoding. Their names are shown using backslash escapes and in quotes."
190 print >>stderr, "\nThis listing included unknown objects. Using a webapi server that supports" \
191 "\na later version of Tahoe may help."