Commits

clach04 committed 977b1b6 Draft

woof- 2012-05-31: Workaround for Python 2.7, more verbose URL output (convenience for wget), simple client functionality (woof <URL>)
from http://www.home.unix-ag.org/simon/woof.html

Comments (0)

Files changed (1)

 # File upload support loosely based on code from Stephen English <steve@secomputing.co.uk>
 
 import sys, os, errno, socket, getopt, commands, tempfile
-import cgi, urllib, BaseHTTPServer
+import cgi, urllib, urlparse, BaseHTTPServer
+import readline
 import ConfigParser
 import shutil, tarfile, zipfile
 import struct
 
    return candidates[0]
 
-   
+
+# our own HTTP server class, fixing up a change in python 2.7
+# since we do our fork() in the request handler
+# the server must not shutdown() the socket.
+
+class ForkingHTTPServer (BaseHTTPServer.HTTPServer):
+   def process_request(self, request, client_address):
+      self.finish_request (request, client_address)
+      self.close_request (request)
+
+
 # Main class implementing an HTTP-Requesthandler, that serves just a single
 # file and redirects all other requests to this file (this passes the actual
 # filename to the client).
 
          self.send_response (200)
          self.send_header ("Content-Type", "application/octet-stream")
+         self.send_header ("Content-Disposition", "attachment;filename=%s" % urllib.quote (os.path.basename (self.filename)))
          if os.path.isfile (self.filename):
             self.send_header ("Content-Length",
                               os.path.getsize (self.filename))
                   tfile = tarfile.open (mode=('w|' + compressed),
                                         fileobj=self.wfile)
                   tfile.add (self.filename,
-                             arcname=os.path.basename(self.filename))
+                             arcname=os.path.basename (self.filename))
                   tfile.close ()
          except Exception, e:
             print e
    FileServHTTPRequestHandler.filename = filename
 
    try:
-      httpd = BaseHTTPServer.HTTPServer ((ip_addr, port),
-                                         FileServHTTPRequestHandler)
+      httpd = ForkingHTTPServer ((ip_addr, port), FileServHTTPRequestHandler)
    except socket.error:
       print >>sys.stderr, "cannot bind to IP address '%s' port %d" % (ip_addr, port)
       sys.exit (1)
    if not ip_addr:
       ip_addr = find_ip ()
    if ip_addr:
-      print "Now serving on http://%s:%s/" % (ip_addr, httpd.server_port)
+      if filename:
+         location = "http://%s:%s/%s" % (ip_addr, httpd.server_port,
+                                         urllib.quote (os.path.basename (filename)))
+         if os.path.isdir (filename):
+            if compressed == 'gz':
+               location += ".tar.gz"
+            elif compressed == 'bz2':
+               location += ".tar.bz2"
+            elif compressed == 'zip':
+               location += ".zip"
+            else:
+               location += ".tar"
+      else:
+         location = "http://%s:%s/" % (ip_addr, httpd.server_port)
+
+      print "Now serving on %s" % location
 
    while cpid != 0 and maxdownloads > 0:
       httpd.handle_request ()
            %s [-i <ip_addr>] [-p <port>] [-c <count>] [-z|-j|-Z|-u] <dir>
            %s [-i <ip_addr>] [-p <port>] [-c <count>] -s
            %s [-i <ip_addr>] [-p <port>] [-c <count>] -U
+
+           %s <url>
    
     Serves a single file <count> times via http on port <port> on IP
     address <ip_addr>.
 
     When -s is specified instead of a filename, %s distributes itself.
 
-    When -U is specified, woof provides an upload form and allows uploading files.
+    When -U is specified, woof provides an upload form, allowing file uploads.
    
     defaults: count = %d, port = %d
 
+    If started with an url as an argument, woof acts as a client,
+    downloading the file and saving it in the current directory.
+
     You can specify different defaults in two locations: /etc/woofrc
     and ~/.woofrc can be INI-style config files containing the default
     port and the default count. The file in the home directory takes
         count = 2
         ip = 127.0.0.1
         compressed = gz
-   """ % (name, name, name, name, name, defmaxdown, defport)
+   """ % (name, name, name, name, name, name, defmaxdown, defport)
 
    if errmsg:
       print >>sys.stderr, errmsg
 
 
 
+def woof_client (url):
+   urlparts = urlparse.urlparse (url, "http")
+   if urlparts[0] not in [ "http", "https" ] or urlparts[1] == '':
+      return None
+
+   fname = None
+
+   f = urllib.urlopen (url)
+
+   f_meta = f.info ()
+   disp = f_meta.getheader ("Content-Disposition")
+
+   if disp:
+      disp = disp.split (";")
+
+   if disp and disp[0].lower () == 'attachment':
+      fname = [x[9:] for x in disp[1:] if x[:9].lower () == "filename="]
+      if len (fname):
+         fname = fname[0]
+      else:
+         fname = None
+
+   if fname == None:
+      url = f.geturl ()
+      urlparts = urlparse.urlparse (url)
+      fname = urlparts[2]
+
+   if not fname:
+      fname = "woof-out.bin"
+
+   if fname:
+      fname = urllib.unquote (fname)
+      fname = os.path.basename (fname)
+
+   readline.set_startup_hook (lambda: readline.insert_text (fname))
+   fname = raw_input ("Enter target filename: ")
+   readline.set_startup_hook (None)
+
+   override = False
+
+   destfile = None
+   destfilename = os.path.join (".", fname)
+   try:
+      destfile = os.open (destfilename,
+                          os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0644)
+   except OSError, e:
+      if e.errno == errno.EEXIST:
+         override = raw_input ("File exists. Overwrite (y/n)? ")
+         override = override.lower () in [ "y", "yes" ]
+      else:
+         raise
+
+   if destfile == None:
+      if override == True:
+         destfile = os.open (destfilename, os.O_WRONLY | os.O_CREAT, 0644)
+      else:
+         for suffix in [".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9"]:
+            destfilename = os.path.join (".", fname + suffix)
+            try:
+               destfile = os.open (destfilename,
+                                   os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0644)
+               break
+            except OSError, e:
+               if e.errno == errno.EEXIST:
+                  continue
+               raise
+
+         if not destfile:
+            destfile, destfilename = tempfile.mkstemp (prefix = fname + ".",
+                                                    dir = ".")
+         print "alternate filename is:", destfilename
+
+   print "downloading file: %s -> %s" % (fname, destfilename)
+
+   shutil.copyfileobj (f, os.fdopen (destfile, "w"))
+
+   return 1;
+
+
+
 def main ():
    global cpid, upload, compressed
 
    port = 8080
    ip_addr = ''
 
-   config = ConfigParser.ConfigParser()
-   config.read (['/etc/woofrc', os.path.expanduser('~/.woofrc')])
+   config = ConfigParser.ConfigParser ()
+   config.read (['/etc/woofrc', os.path.expanduser ('~/.woofrc')])
 
    if config.has_option ('main', 'port'):
       port = config.getint ('main', 'port')
 
    else:
       if len (filenames) == 1:
+         if woof_client (filenames[0]) != None:
+            sys.exit (0)
+
          filename = os.path.abspath (filenames[0])
       else:
          usage (defaultport, defaultmaxdown,
    try:
       main ()
    except KeyboardInterrupt:
-      pass
+      print