1
2
3 """
4 Upload a file.
5
6 This is the guts of the command-line front-end app fcpupload.
7
8 It is adapted from put.py, just with nicer defaults and feedback.
9 """
10
11
12
13 import sys, os, getopt, traceback, mimetypes
14
15 import node
16
17
18
19 progname = sys.argv[0]
20
21
22
23 -def usage(msg=None, ret=1):
24 """
25 Prints usage message then exits
26 """
27 if msg:
28 sys.stderr.write(msg+"\n")
29 sys.stderr.write("Usage: %s [options] key_uri [filename]\n" % progname)
30 sys.stderr.write("Type '%s -h' for help\n" % progname)
31 sys.exit(ret)
32
33
34
36 """
37 print help options, then exit
38 """
39
40 print "\n".join(("%s: a simple command-line freenet key insertion command" % progname,
41 "Usage: %s [options] <filename>" % progname,
42 "",
43 "Arguments:",
44 " <key_uri>",
45 " A freenet key URI, such as 'freenet:KSK@gpl.txt'",
46 " Note that the 'freenet:' part may be omitted if you feel lazy",
47 " <filename>",
48 " The filename from which to source the key's data. If this filename",
49 " is '-', or is not given, then the data will be sourced from",
50 " standard input",
51 "",
52 "Options:",
53 " -h, -?, --help",
54 " Print this help message",
55 " -v, --verbose",
56 " Print verbose progress messages to stderr, do -v twice for more detail",
57 " -H, --fcpHost=<hostname>",
58 " Connect to FCP service at host <hostname>",
59 " -P, --fcpPort=<portnum>",
60 " Connect to FCP service at port <portnum>",
61 " -m, --mimetype=<mimetype>",
62 " The mimetype under which to insert the key. If not given, then",
63 " an attempt will be made to guess it from the filename. If no",
64 " filename is given, or if this attempt fails, the mimetype",
65 " 'text/plain' will be used as a fallback",
66 " -c, --compress",
67 " Enable compression of inserted data (default is no compression)",
68 " -d, --disk",
69 " Try to have the node access file on disk directly , it will try then a fallback is provided",
70 " nb:give the path relative to node filesystem not from where you're running this program",
71 " For the direct access to succeed, the absolute path seen by the node and by this script must be the same",
72 " -p, --persistence=",
73 " Set the persistence type, one of 'connection', 'reboot' or 'forever'",
74 " -g, --global",
75 " Do it on the FCP global queue",
76 " -w, --wait",
77 " Wait for completion",
78 " -r, --priority",
79 " Set the priority (0 highest, 6 lowest, default 3)",
80 " -e, --realtime",
81 " Use the realtime queue (fast for small files)",
82 " -t, --timeout=",
83 " Set the timeout, in seconds, for completion. Default one year",
84 " -V, --version",
85 " Print version number and exit",
86 "",
87 "Environment:",
88 " Instead of specifying -H and/or -P, you can define the environment",
89 " variables FCP_HOST and/or FCP_PORT respectively"))
90
91
92
93
95 """
96 Front end for fcpput utility
97 """
98
99 verbosity = node.ERROR
100 verbose = False
101 fcpHost = node.defaultFCPHost
102 fcpPort = node.defaultFCPPort
103 mimetype = None
104 wait = False
105
106 opts = {
107 "Verbosity" : 0,
108 "persistence" : "forever",
109 "async" : True,
110 "priority" : 3,
111 "Global": "true",
112 "MaxRetries" : -1,
113 }
114
115
116 try:
117 cmdopts, args = getopt.getopt(
118 sys.argv[1:],
119 "?hvH:P:m:gcdp:wr:et:V",
120 ["help", "verbose", "fcpHost=", "fcpPort=", "mimetype=", "global","compress","disk",
121 "persistence=", "wait",
122 "priority=", "realtime", "timeout=", "version",
123 ]
124 )
125 except getopt.GetoptError:
126
127 usage()
128 sys.exit(2)
129 output = None
130 verbose = False
131
132
133 makeDDARequest=False
134 opts['nocompress'] = True
135
136 for o, a in cmdopts:
137 if o in ("-V", "--version"):
138 print "This is %s, version %s" % (progname, node.fcpVersion)
139 sys.exit(0)
140
141 elif o in ("-?", "-h", "--help"):
142 help()
143 sys.exit(0)
144
145 elif o in ("-v", "--verbosity"):
146 if verbosity < node.DETAIL:
147 verbosity = node.DETAIL
148 else:
149 verbosity += 1
150 opts['Verbosity'] = 1023
151 verbose = True
152
153 elif o in ("-H", "--fcpHost"):
154 fcpHost = a
155
156 elif o in ("-P", "--fcpPort"):
157 try:
158 fcpPort = int(a)
159 except:
160 usage("Invalid fcpPort argument %s" % repr(a))
161
162 elif o in ("-m", "--mimetype"):
163 mimetype = a
164
165 elif o in ("-c", "--compress"):
166 opts['nocompress'] = False
167
168 elif o in ("-d","--disk"):
169 makeDDARequest=True
170
171
172 elif o in ("-p", "--persistence"):
173 if a not in ("connection", "reboot", "forever"):
174 usage("Persistence must be one of 'connection', 'reboot', 'forever'")
175 opts['persistence'] = a
176
177 elif o in ("-g", "--global"):
178 opts['Global'] = "true"
179
180 elif o in ("-w", "--wait"):
181 opts['async'] = False
182 wait = True
183
184 elif o in ("-r", "--priority"):
185 try:
186 pri = int(a)
187 if pri < 0 or pri > 6:
188 raise hell
189 except:
190 usage("Invalid priority '%s'" % pri)
191 opts['priority'] = int(a)
192
193 elif o in ("-e", "--realtime"):
194 opts['realtime'] = True
195
196 elif o in ("-t", "--timeout"):
197 try:
198 timeout = node.parseTime(a)
199 except:
200 usage("Invalid timeout '%s'" % a)
201 opts['timeout'] = timeout
202
203
204 nargs = len(args)
205 if nargs < 1 or nargs > 2:
206 usage("Invalid number of arguments")
207
208 keytypes = ["USK", "KSK", "SSK", "CHK"]
209 if nargs == 2:
210 infile = args[1]
211 uri = args[0]
212 if not uri.startswith("freenet:"):
213 uri = "freenet:" + uri
214 if not uri[len("freenet:"):len("freenet:")+3] in keytypes:
215 print uri, uri[len("freenet:"):len("freenet:")+4]
216 usage("The first argument must be a key. Example: CHK@/<filename>")
217 else:
218
219 infile = args[0]
220 uri = "freenet:CHK@/" + node.toUrlsafe(infile)
221
222
223 if infile and uri[-2:] == "@/" and uri[:3] in keytypes:
224 uri += node.toUrlsafe(infile)
225
226
227
228 if infile and not mimetype:
229 base, ext = os.path.splitext(infile)
230 if ext:
231 mimetype = mimetypes.guess_type(ext)[0]
232
233 if mimetype:
234
235
236
237
238 opts['mimetype'] = mimetype
239
240
241 try:
242 n = node.FCPNode(host=fcpHost, port=fcpPort, verbosity=verbosity,
243 logfile=sys.stderr)
244 except:
245 if verbose:
246 traceback.print_exc(file=sys.stderr)
247 usage("Failed to connect to FCP service at %s:%s" % (fcpHost, fcpPort))
248
249
250 TestDDARequest=False
251
252
253 freenet_uri = None
254
255 if makeDDARequest:
256 if infile is not None:
257 ddareq=dict()
258 ddafile = os.path.abspath(infile)
259 ddareq["Directory"]= os.path.dirname(ddafile)
260
261
262
263 ddareq["WantReadDirectory"]="True"
264 ddareq["WantWriteDirectory"]="false"
265 print "Absolute filepath used for node direct disk access :",ddareq["Directory"]
266 print "File to insert :",os.path.basename( ddafile )
267 TestDDARequest=n.testDDA(**ddareq)
268
269 if TestDDARequest:
270 opts["file"]=ddafile
271 putres = n.put(uri,**opts)
272 else:
273 sys.stderr.write("%s: disk access failed to insert file %s fallback to direct\n" % (progname,ddafile) )
274 else:
275 sys.stderr.write("%s: disk access needs a disk filename\n" % progname )
276
277
278 if not TestDDARequest:
279
280 if not infile:
281 data = sys.stdin.read()
282 else:
283 try:
284 data = file(infile, "rb").read()
285 except:
286 n.shutdown()
287 usage("Failed to read input from file %s" % repr(infile))
288
289 try:
290
291
292 opts["data"] = data
293 if infile:
294 opts["file"] = infile
295 n.listenGlobal()
296 putres = n.put(uri, **opts)
297 if not wait:
298 opts["chkonly"] = True
299 opts["async"] = False
300
301 opts["priority"] = 0
302 opts["realtime"] = True
303 opts["persistence"] = "connection"
304 opts["Global"] = False
305 freenet_uri = n.put(uri,**opts)
306
307 except:
308 if verbose:
309 traceback.print_exc(file=sys.stderr)
310 n.shutdown()
311 sys.stderr.write("%s: Failed to insert key %s\n" % (progname, repr(uri)))
312 sys.exit(1)
313
314 if not wait:
315
316 putres.waitTillReqSent()
317 else:
318
319 sys.stdout.write(putres)
320 sys.stdout.flush()
321
322 n.shutdown()
323
324
325 if not wait:
326 print freenet_uri
327
328 sys.exit(0)
329
330
331
332
333
334
335