From 305ac29ee00fae2eece204eb4db665c93d278fde Mon Sep 17 00:00:00 2001 From: Simon Budig Date: Fri, 13 Feb 2009 00:00:00 +0100 Subject: support for bz2, no dependency on an external 'tar' --- woof | 108 +++++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 59 insertions(+), 49 deletions(-) (limited to 'woof') diff --git a/woof b/woof index c171996..5f708e0 100755 --- a/woof +++ b/woof @@ -2,7 +2,7 @@ # -*- encoding: utf-8 -*- # # woof -- an ad-hoc single file webserver -# Copyright (C) 2004 Simon Budig +# Copyright (C) 2004-2009 Simon Budig # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -23,14 +23,16 @@ # Solaris support by Colin Marquardt, # FreeBSD support with the help from Andy Gimblett, # Cygwin support by Stefan Reichör +# tarfile usage suggested by Morgan Lefieux -import sys, os, popen2, signal, select, socket, getopt, commands +import sys, os, socket, getopt, commands import urllib, BaseHTTPServer import ConfigParser +import shutil, tarfile maxdownloads = 1 cpid = -1 -compressed = True +compressed = 'gz' # Utility function to guess the IP (as a string) where the server can be @@ -55,7 +57,7 @@ def find_ip (): netstat = commands.getoutput ("LC_MESSAGES=C netstat -rn") defiface = [i.split ()[-1] for i in netstat.split ('\n') if i.split ()[0] == "0.0.0.0"] - elif platform in ("Darwin", "FreeBSD"): + elif platform in ("Darwin", "FreeBSD", "NetBSD"): netstat = commands.getoutput ("LC_MESSAGES=C netstat -rn") defiface = [i.split ()[-1] for i in netstat.split ('\n') if len(i) > 2 and i.split ()[0] == "default"] @@ -73,7 +75,7 @@ def find_ip (): if platform == "Linux": ifcfg = commands.getoutput ("LC_MESSAGES=C ifconfig " + defiface[0]).split ("inet addr:") - elif platform in ("Darwin", "FreeBSD", "SunOS"): + elif platform in ("Darwin", "FreeBSD", "SunOS", "NetBSD"): ifcfg = commands.getoutput ("LC_MESSAGES=C ifconfig " + defiface[0]).split ("inet ") @@ -118,8 +120,10 @@ class FileServHTTPRequestHandler (BaseHTTPServer.BaseHTTPRequestHandler): self.path = urllib.quote (urllib.unquote (self.path)) location = "/" + urllib.quote (os.path.basename (self.filename)) if os.path.isdir (self.filename): - if compressed: + if compressed == 'gz': location += ".tar.gz" + elif compressed == 'bz2': + location += ".tar.bz2" else: location += ".tar" @@ -143,51 +147,42 @@ class FileServHTTPRequestHandler (BaseHTTPServer.BaseHTTPRequestHandler): # multiple downloads can happen simultaneously. cpid = os.fork () - os.setpgrp () if cpid == 0: # Child process - size = -1 - datafile = None child = None + type = None if os.path.isfile (self.filename): - size = os.path.getsize (self.filename) - datafile = open (self.filename) + type = "file" elif os.path.isdir (self.filename): - os.environ['woof_dir'], os.environ['woof_file'] = os.path.split (self.filename) - if compressed: - arg = 'z' - else: - arg = '' - child = popen2.Popen3 ('cd "$woof_dir";tar c%sf - "$woof_file"' % arg) - datafile = child.fromchild + type = "dir" + + if not type: + print >> sys.stderr, "can only serve files or directories. Aborting." + sys.exit (1) self.send_response (200) self.send_header ("Content-type", "application/octet-stream") - if size >= 0: - self.send_header ("Content-Length", size) + if os.path.isfile (self.filename): + self.send_header ("Content-Length", + os.path.getsize (self.filename)) self.end_headers () try: - try: - while 1: - if select.select ([datafile], [], [], 2)[0]: - c = datafile.read (1024) - if c: - self.wfile.write (c) - else: - datafile.close () - break - except: - print >>sys.stderr, "Connection broke. Aborting" - - finally: - # for some reason tar doesnt stop working when the pipe breaks - if child: - if child.poll (): - os.killpg (os.getpgid (child.pid), signal.SIGTERM) - + if type == "file": + datafile = file (self.filename) + shutil.copyfileobj (datafile, self.wfile) + datafile.close () + elif type == "dir": + tfile = tarfile.open (mode=('w|' + compressed), + fileobj=self.wfile) + tfile.add (self.filename, + arcname=os.path.basename(self.filename)) + tfile.close () + except: + print >>sys.stderr, "Connection broke. Aborting" + def serve_files (filename, maxdown = 1, ip_addr = '', port = 8080): global maxdownloads @@ -219,21 +214,25 @@ def serve_files (filename, maxdown = 1, ip_addr = '', port = 8080): def usage (defport, defmaxdown, errmsg = None): name = os.path.basename (sys.argv[0]) print >>sys.stderr, """ - Usage: %s [-i ] [-p ] [-c ] [-u] - %s [-i ] [-p ] [-c ] [-u] -s + Usage: %s [-i ] [-p ] [-c ] + %s [-i ] [-p ] [-c ] [-z|-j|-u] + %s [-i ] [-p ] [-c ] -s Serves a single file times via http on port on IP address . - When a directory is specified, a .tar.gz archive gets served (or an - uncompressed tar archive when -u is specified), when -s is specified - instead of a filename, %s distributes itself. + When a directory is specified, an tar archive gets served. By default + it is gzip compressed. You can specify -z for gzip compression, + -j for bzip2 compression or -u for no compression. You can configure your + default compression method in the configuration file described below. + + When -s is specified instead of a filename, %s distributes itself. defaults: count = %d, port = %d 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 - precedence. + precedence. The compression methods are "off", "gz" or "bz2". Sample file: @@ -241,8 +240,8 @@ def usage (defport, defmaxdown, errmsg = None): port = 8008 count = 2 ip = 127.0.0.1 - compressed = true - """ % (name, name, name, defmaxdown, defport) + compressed = gz + """ % (name, name, name, name, defmaxdown, defport) if errmsg: print >>sys.stderr, errmsg print >>sys.stderr @@ -270,13 +269,20 @@ def main (): ip_addr = config.get ('main', 'ip') if config.has_option ('main', 'compressed'): - compressed = config.getboolean ('main', 'compressed') + formats = { 'gz' : 'gz', + 'true' : 'gz', + 'bz' : 'bz2', + 'bz2' : 'bz2', + 'off' : '', + 'false' : '' } + compressed = config.get ('main', 'compressed') + compressed = formats.get (compressed, 'gz') defaultport = port defaultmaxdown = maxdown try: - options, filenames = getopt.getopt (sys.argv[1:], "hsui:c:p:") + options, filenames = getopt.getopt (sys.argv[1:], "hszjui:c:p:") except getopt.GetoptError, desc: usage (defaultport, defaultmaxdown, desc) @@ -307,8 +313,12 @@ def main (): elif option == '-h': usage (defaultport, defaultmaxdown) + elif option == '-z': + compressed = 'gz' + elif option == '-j': + compressed = 'bz2' elif option == '-u': - compressed = False + compressed = '' else: usage (defaultport, defaultmaxdown, "Unknown option: %r" % option) -- cgit v1.2.3