Python Avahi Object

A simple class to publish a network service via zeroconf with avahi. Requires python-avahi and python-dbus. All calls to the avahi and dbus libraries are wrapped by the class.

Example usage :

from ZeroconfService import ZeroconfService
import time
 
service = ZeroconfService(name="Joe's awesome FTP server",
                          port=3000,  stype="_ftp._tcp")
service.publish()
time.sleep(10)
service.unpublish()

[download ZeroconfService.py]

import avahi
import dbus
 
__all__ = ["ZeroconfService"]
 
class ZeroconfService:
    """A simple class to publish a network service with zeroconf using
    avahi.
 
    """
 
    def __init__(self, name, port, stype="_http._tcp",
                 domain="", host="", text=""):
        self.name = name
        self.stype = stype
        self.domain = domain
        self.host = host
        self.port = port
        self.text = text
 
    def publish(self):
        bus = dbus.SystemBus()
        server = dbus.Interface(
                         bus.get_object(
                                 avahi.DBUS_NAME,
                                 avahi.DBUS_PATH_SERVER),
                        avahi.DBUS_INTERFACE_SERVER)
 
        g = dbus.Interface(
                    bus.get_object(avahi.DBUS_NAME,
                                   server.EntryGroupNew()),
                    avahi.DBUS_INTERFACE_ENTRY_GROUP)
 
        g.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC,dbus.UInt32(0),
                     self.name, self.stype, self.domain, self.host,
                     dbus.UInt16(self.port), self.text)
 
        g.Commit()
        self.group = g
 
    def unpublish(self):
        self.group.Reset()
 
 
def test():
    service = ZeroconfService(name="TestService", port=3000)
    service.publish()
    raw_input("Press any key to unpublish the service ")
    service.unpublish()
 
 
if __name__ == "__main__":
    test()

Droopy: easy file receiving

What is it ?
Droopy is a mini Web server whose sole purpose is to let others upload files to your computer.

Droopy in the browser.

Why ?
Say you’re chatting with a friend on MSN Messenger (perhaps with the excellent pidgin ?). She wants to send you amazing photos she took last week-end, so she uses Messenger file transfer. Unfortunately, the zip file is over 50 MB and it’s painfully slow. Now relax, droopy comes to rescue.

Does it work on my computer ?
You can use it on Unix (Linux, BSD, MacOSX) and Windows. Droopy is a python script so you’ll need to have Python installed.

How to use it ?

Note: A tutorial on how to set up Droopy on Windows was very kindly written by Ronan. The rest of this section focuses on Linux and MacOSX.

Droopy is a command-line program. I’ll suppose you’ve downloaded and saved the file in ~/bin/. Go to the directory where you want the uploaded files to be stored, for example:

mkdir ~/uploads
cd ~/uploads 

Then, run droopy. You can give a message and a picture to display:

python ~/bin/droopy -m "Hi, it's me Bob. You can send me a file." -p ~/avatar.png

And it’s up and running on port 8000 of you computer. Check it out at http://localhost:8000, and give your computer’s address to your friends.

Droopy in the terminal.

Type droopy -h to see all options:

Usage: droopy [options] [PORT]

Options:
  -h, --help                            show this help message and exit
  -d DIRECTORY, --directory DIRECTORY   set the directory to upload files to
  -m MESSAGE, --message MESSAGE         set the message
  -p PICTURE, --picture PICTURE         set the picture
  --dl                                  provide download links
  --save-config                         save options in a configuration file
  --delete-config                       delete the configuration file and exit

License
Droopy is a free software distributed under the BSD License. There’s a git repository at http://gitorious.org/droopy. New releases are announced on Freshmeat.

Feedback and contribution
I’d love to hear about your experience using droopy. If you have ideas to improve it, please let me know. Pierre – stackp@online.fr.

[download droopy]

Find big files

[download big]

#!/bin/sh
# find the biggest files under the current directory.

find . -type f -printf "%k %p\n" | sort -rn | head

Find recent files

[download recent]

#!/bin/sh
# Find files created or modified less than 1 day ago

find . -mtime -1 -print

massmailer

massmailer sends a similar (multipart mime) e-mail to a bunch of people. The list of recipients is not disclosed: each e-mail is addressed individually. massmailer has been developped and successfully used for the organization of a scientific conference.

[download massmailer]

#!/usr/bin/env python
 
# Licensed under the Python License (see http://www.python.org/psf/license/)
# Copyright (C) 2008 Pierre Duquesne <stackp@online.fr>
 
USAGE='''\
usage:
massmailer --server <hostname> --addrlist <addr.txt> --from <addr>
           [--subject <subject>] [--log <logfile>]
           [--text <textfile>] [--img <image>] [--audio <sndfile>]
           [--bin <file>]
 
    massmailer sends a similar (multipart mime) mail to a bunch of people.
    --server <hostname>
          the name of the smtp server
    --addrlist <addr.txt>
          is a text file containing one address per line. Each
          address can be a raw email address, or in the format:
          Name of the person <person@site.org>
    --from <addr>
          is the sender address either formatted as jdoe@site.com or
          "John Doe <jdoe@site.com>"
    --subject <subject>
          the subject of the mail
    --log <logfile>
          a file name for the program to write success and failures
          in a human-readable text file.
    --text <txtfile>
    --img  <image>
    --audio <sndfile>
    --bin <file>
          attach a text file, a picture, an audio file, or any type of file to
          the mail. Files specified with --text don\'t have their filename
          specified in the mime headers (the text only is inserted).
          Use --bin if you want to attach the filename information.
 
Example:
    massmailer --server smtp.site.com --addrlist addr.txt --log log \\
               --from spammer@site.com --subject "Cheap Rolex" \\
               --text buy.txt --img rolex.png\
'''
 
import smtplib, sys, getopt
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEAudio import MIMEAudio
import email, mimetypes
from os.path import basename
 
# -- Parse command line arguments
 
opts, args = getopt.getopt(sys.argv[1:], ':h',\
                              ['server=','log=','addrlist=','from=','subject=',
                               'text=', 'img=', 'audio=', 'bin=', 'help'])
if args != []:
    print "Wrong command line arguments:", "'"+' '.join(args)+"'"
    print "Try '%s --help' for valid options." % sys.argv[0]
    sys.exit(1)
 
servername=None
logfile=None
addrfile=None
fromaddr=None
subject=''
attch=[]
 
for o,a in opts:
    if o=='--text' or o=='--img' or o=='--audio' or o=='--bin':
        attch.append((o[2:],a))
    elif o=='--server': servername=a
    elif o=='--log': logfile=a
    elif o=='--addrlist': addrfile=a
    elif o=='--from': fromaddr=a
    elif o=='--subject': subject=a
    elif o in ['-h', '--help']:
        print USAGE
        sys.exit(0)
 
# -- Print error messages
 
if not (servername and addrfile and fromaddr):
    if not servername:
        print 'Error: No server specified (--server option)'
    if not addrfile:
        print 'Error: No address list specified (--addrlist option)'
    if not fromaddr:
        print 'Error: No sender address specified (--from option)'
    sys.exit(1)
 
# -- Print warning messages
 
warning=''
if not subject:
    warning = warning + 'Warning: No subject specified (--subject option)\n'
if not logfile:
    warning = warning +'Warning: No log file specified (--logfile option)\n'
if attch == []: warning = warning + \
   'Warning: No content specified (--text, --img, --audio, --bin options)\n'
if warning != '':
    print '\n', warning
    inp = raw_input('Are you sure you want to continue [Y/n] ?')
    if inp not in ['Y','y', '']:
        print 'Aborted, bye!'
        sys.exit(0)
 
# -- Store the destination addresses in a list
 
addrlist = [l.strip() for l in open(addrfile).readlines() if l.strip() !='']
if logfile:
    print 'writing log to',logfile
    log = open(logfile, 'w')
else:
    log = sys.stdout
 
# -- Build multi-part mime message
 
msg = MIMEMultipart()
msg['Subject']=subject
msg['From']=fromaddr
msg['To']=''
 
for (ftype, f) in attch:
    fd = open(f)
    content = fd.read()
    if ftype == 'text': msg.attach(MIMEText(content))
    elif ftype == 'img':
        m = MIMEImage(content)
        m.add_header('Content-Disposition','inline', filename=basename(f))
        msg.attach(m)
    # FIXME: mp3 subtype not found
    elif ftype == 'audio': msg.attach(MIMEAudio(content))
    elif ftype == 'bin':
        m = MIMEBase('application', 'octet-stream')
        m.add_header('Content-Disposition','attachment', filename=basename(f))
        m.set_payload(content)
        email.Encoders.encode_base64(m)
        msg.attach(m)
 
    fd.close()
 
# -- Send the message
 
try:
    server = smtplib.SMTP(servername)
except Exception, e:
    print >>log, 'Could not connect to', servername, e.__class__, e
    sys.exit(2)
 
total = len(addrlist)
for (idx, addr) in enumerate(addrlist):
    try:
        msg.replace_header('To', addr)
        server.sendmail(fromaddr, addr, msg.as_string())
        print >>log, 'Success: ', addr
        print 'Progress: %d/%d' % (idx+1, total)
    except Exception, e:
        print >>log, 'Error:',addr, e.__class__, e
 
server.quit()