summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xwoof108
1 files changed, 59 insertions, 49 deletions
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 <simon@budig.de>
+# Copyright (C) 2004-2009 Simon Budig <simon@budig.de>
#
# 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, <colin.marquardt@zmd.de>
# FreeBSD support with the help from Andy Gimblett, <A.M.Gimblett@swansea.ac.uk>
# Cygwin support by Stefan Reichör <stefan@xsteve.at>
+# tarfile usage suggested by Morgan Lefieux <comete@geekandfree.org>
-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 <ip_addr>] [-p <port>] [-c <count>] [-u] <file/dir>
- %s [-i <ip_addr>] [-p <port>] [-c <count>] [-u] -s
+ Usage: %s [-i <ip_addr>] [-p <port>] [-c <count>] <file>
+ %s [-i <ip_addr>] [-p <port>] [-c <count>] [-z|-j|-u] <dir>
+ %s [-i <ip_addr>] [-p <port>] [-c <count>] -s
Serves a single file <count> times via http on port <port> on IP
address <ip_addr>.
- 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)