Dangermouse
-----------

Negative key caching
Handle spaces in locations

Keys are not cached until they are used to verify another key or message.
This has corollaries:
	On startup, user's public key is not written to the cache
	Domain keys are never cached
Need to rethink this to decide whether to emulate Gale behavior (save a key
if it is verified) or retain this behavior.

FuguWin
-------

Make user download win32api extensions in addition to py152, if they don't
have either installed.

Installer should use ShellExecute instead of CMD.exe.

Fix select/copy/paste?

Set up GALE_SYS_DIR and FUGU_DIR to point to different directories as
appropriate.

	Peter sez:
	GALE_SYS_DIR on Windows is '<install_dir>/gale'. The user dir used to
	be '<install_dir>/<user_name>', but I just looked and it seems to have
	changed to just <install_dir>. I'll probably change it back. I've been
	debating installing the user dir in \Windows\Profiles\<user_name>
	which is the place you are supposed to put user files on Windows, but
	I like to keep everything in one directory.


PyGale features
---------------

gkgen

Make pygale API not require callbacks anywhere.

Bugs
----

Sender colorization doesn't work on delayed puff verification
(but I don't really care)

No public/private puff warning on Windows?

Is there a memory leak?  I just turned on puff history persistence on all
screens.  Next time I quit, check the memory usage and see if it's the same
after a restart.  There may be public keys cached in memory, but that
shouldn't total 10M.

Things to test for symlink keys: (all should work in 0.9.9c)
	sending to sym.tlau@cs (a sym key to tlau@cs)
	doing so when the sym key isn't in the cache
	sending to symA.tlau@cs (a symlink loop with symB.tlau@cs)
	sending to symC.tlau@cs (a symlink to a nonexistent key)

Also, an existing bug seems to be that if you encrypt a message to someone
whose key isn't in the cache, the key doesn't get saved to the cache.  In
fact, how could it?  You don't know whether the key you retrieved was valid
or not.  But it looks like gsend puts it in the cache nevertheless.  Fugu
doesn't currently cache keys, but perhaps it should.  (Gsend caches keys,
but will never overwrite a newer key with an older one.)

Starting up multiple copies seems to hose the fuguconfig.xml file.

Check for missing/bad private key either in setup wizard or when Fugu
starts up.

UI features
-----------

An option to have the "subscribe to" do both . and / for you (sjh)

Dock and undock the screen buttonbar; let it float so that people can bring
up the main window only as necessary.

Color icon on new puffs

Slim mode

XML configuration for puff displays, better configuration for colors.

Ryan wants to disable the status bar

Save puffs to file (need to write a nice-looking file selector dialog that
doesn't prompt you whether you want to overwrite a file or not!)

Make sender color customization be a list, not a dict

Resend/forward puff

Copy entire puff to clipboard

Email puff via rightclick menu

Researchy features
------------------

Predict category based on:
	text of puff
	previous categories, weighted over time and volume
	previously puffed to categories
	user interests

Related work:
	Darragh & Witten's Reactive Keyboard
	Laird & Saul's TDAG
	Hidden Markov models

	text classification (not clustering)

JTR's comments
--------------

5 - Having the thumbnails wrap with the text is a little unattractive.
    Maybe the puff box could have a vertical line near the left side
    dividing it in two?  I think this would make the full size
    thumbnails more appealing, too.

6 - Having detached the send box, I'd like for things like C-R to
    still affect it.  I detached the send box, moved it over to the
    side, and expanded the puff pane to fill the whole thing, and
    found that it wasn't nearly as handy when I lost my favorite key
    binding.

Puff flow control
-----------------

Sources, sinks, filters.  Don't forget about color-coding puffs based on
some attribute.  Either the puff renderer ought to be paramaterizable, or
there should be a filter that sets the "color" of a puff.

Windows stack traces
--------------------

pygale:250:verify
callback(self)
pygale:693:lambda
p=p.verify(lambda p, s=self: s.verify_done(p))
pygale:712:verify_done
self._puff_callback(puff)
TypeError: call of non-function (type None)

Stack trace from molly (perhaps related to new keys?)
----------------------

  File "fugu.py", line 26, in ?
    main()
  File "fugu.py", line 23, in main
    ui.main()
  File "ui.py", line 2494, in main
    m.mainloop()
  File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 492, in mainloop
    self.tk.mainloop(n)
  File "engine.py", line 125, in <lambda>
  File "engine.py", line 143, in read_ready
  File "pygale/pygale.py", line 676, in handle_read
    self._puffs.append(self.process_puff(puffdata))
  File "pygale/pygale.py", line 715, in process_puff
    p = p.verify(lambda p, s=self: s._puff_callback(p))
  File "pygale/pygale.py", line 262, in verify
    p.__fragments.update(gale_pack.group_to_dict(frag))
  File "pygale/gale_pack.py", line 100, in group_to_dict
    (frag_name_len, frag) = pop_int(frag)
  File "pygale/gale_pack.py", line 132, in pop_int
    num = unpack32bit(p[:4])
  File "pygale/gale_pack.py", line 33, in unpack32bit
    return (ord(s[0])<<24) | (ord(s[1])<<16) \
IndexError: string index out of range

Dan's stack trace on quit:
--------------------------

Error: 1
IOError Exception in Tk callback
  Function: <method GaleWin.quit of GaleWin instance at 8331190> (type: <type 'instance method'>)
  Args: ()
Traceback (innermost last):
  File "/usr/lib/python1.5/site-packages/Pmw/Pmw_0_8/lib/PmwBase.py", line 1349, in __call__
    return apply(self.func, args)
  File "/usr/local/fugu/lib/fugu-0.9.8a/ui.py", line 899, in quit
    Config.persist_pufflog(FUGUDIR)
  File "/usr/local/fugu/lib/fugu-0.9.8a/config.py", line 644, in persist_pufflog
    traceback.print_exc()
  File "/tmp/py-root/usr/lib/python1.5/traceback.py", line 135, in print_exc
    print_exception(etype, value, tb, limit, file)
  File "/tmp/py-root/usr/lib/python1.5/traceback.py", line 79, in print_exception
    _print(file, 'Traceback (innermost last):')
  File "/tmp/py-root/usr/lib/python1.5/traceback.py", line 9, in _print
    file.write(str+terminator)
IOError: [Errno 5] Input/output error

Heath's iconify trace:

Error: 1
AttributeError Exception in Tk callback
  Function: <function <lambda> at 8315f18> (type: <type 'function'>)
  Args: (<Tkinter.Event instance at 83e4850>,)
  Event type: KeyPress (type num: 2)
Traceback (innermost last):
  File "/xyz/apps/fugu/lib/fugu-0.9.7f/Pmw/Pmw_0_8_1/lib/PmwBase.py", line 1480, in __call__
    return apply(self.func, args)
  File "/xyz/apps/fugu/lib/fugu-0.9.9/ui.py", line 959, in <lambda>
    self._puffwidget.bind('<Control-z>', lambda e, s=self:
AttributeError: iconify

Thumbnail trace:

  File "fugu.py", line 39, in ?
    main()
  File "fugu.py", line 36, in main
    ui.main()
  File "ui.py", line 2066, in main
    m.mainloop()
  File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 492, in mainloop
    self.tk.mainloop(n)
  File "engine.py", line 125, in <lambda>
  File "engine.py", line 143, in read_ready
  File "pygale/asyncurl.py", line 79, in fetch_url3
    self.callback(self.data)
  File "thumbcache.py", line 100, in <lambda>
    asyncurl.fetch_url(thumburl, lambda data, f=thumbimg, ef=errorfunc,
  File "thumbcache.py", line 126, in getthumb2
    getthumb3(id, thumbimg, errorfunc)
  File "thumbcache.py", line 135, in getthumb3
    os.unlink(thumbimg)
OSError: [Errno 2] No such file or directory: '/home/tlau/.gale/thumbs/mikef@praxis.etla.net'


Dan, after restarting his galed:

Traceback (innermost last):
File "/xyz/bin/fugu", line 39, in ?  main()
File "/xyz/bin/fugu", line 36, in main
ui.main()
File "/xyz/apps/fugu/lib/fugu-0.9.9/ui.py", line 2054, in main
m.mainloop()
File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 492, in mainloop
self.tk.mainloop(n)
File "/xyz/apps/fugu/lib/fugu-0.9.9/pygale/engine.py", line 125, in <lambda>
Tkinter.READABLE, lambda f, m, s=self, h=handle:
File "/xyz/apps/fugu/lib/fugu-0.9.9/pygale/engine.py", line 143, in read_ready
self._callback_map[handle]()
File "/xyz/apps/fugu/lib/fugu-0.9.9/pygale/pygale.py", line 549, in <lambda>
self._engine.add_callback(sock, lambda self=self, s=sock, h=host,
File "/xyz/apps/fugu/lib/fugu-0.9.9/pygale/pygale.py", line 569, in connect3
self._on_connect(host)
File "/xyz/apps/fugu/lib/fugu-0.9.9/ui.py", line 357, in <lambda>
self._galeconn.set_onconnect(lambda h, r=reconnect, s=self:
File "/xyz/apps/fugu/lib/fugu-0.9.9/ui.py", line 371, in on_sendconn
self._galeconn.sub_to(akd_cat)
File "/xyz/apps/fugu/lib/fugu-0.9.9/pygale/pygale.py", line 617, in sub_to
self._sock.send(req)
socket.error: (32, 'Broken pipe')

If you try to use someone else's fuguconfig.xml you get this nasty trace:

[...]
  File "/usr/local/lib/fugu-0.9.9b/pygale/sign.py", line 214, in <lambda>
    decode_sig(signature, msg_data, lambda k, u=keyobj, c=callback:
  File "/usr/local/lib/fugu-0.9.9b/pygale/sign.py", line 232, in decode_done
    callback(upper_key)
  File "/usr/local/lib/fugu-0.9.9b/pygale/authcache.py", line 293, in <lambda>
    self.find_pubkey_fromdisk(keyobj, lambda k, s=self, cb=callback:
  File "/usr/local/lib/fugu-0.9.9b/pygale/authcache.py", line 298, in find_pubkey2
    callback(keyobj)
  File "/usr/local/lib/fugu-0.9.9b/pygale/pygale.py", line 830, in <lambda>
    authcache.find_pubkey(keyobj, lambda k, c=cb: lookup_id_done(k, c))
  File "/usr/local/lib/fugu-0.9.9b/pygale/pygale.py", line 846, in lookup_id_done
    callback((key.name(), key.comment()))
  File "/usr/local/lib/fugu-0.9.9b/pygale/pygale.py", line 898, in <lambda>
    lookup_id(userid, lambda n, id=userid, p=p, c=conn:
  File "/usr/local/lib/fugu-0.9.9b/pygale/pygale.py", line 907, in finish_notify_in
    p = p.sign_message(namepair[0])
  File "/usr/local/lib/fugu-0.9.9b/pygale/pygale.py", line 149, in sign_message
    privkey = authcache.private(signer)
  File "/usr/local/lib/fugu-0.9.9b/pygale/authcache.py", line 327, in private
    return apply(KeyCache.private, args)
  File "/usr/local/lib/fugu-0.9.9b/pygale/authcache.py", line 52, in private
    return self.__private[name]
KeyError: corin@cs.washington.edu

  File "fugu.py", line 39, in ?
    main()
  File "fugu.py", line 36, in main
    ui.main()
  File "ui.py", line 2198, in main
    m.mainloop()
  File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 492, in mainloop
    self.tk.mainloop(n)
  File "engine.py", line 125, in <lambda>
  File "engine.py", line 143, in read_ready
  File "pygale/asyncurl.py", line 79, in fetch_url3
    self.callback(self.data)
  File "thumbcache.py", line 127, in <lambda>
    asyncurl.fetch_url(thumburl, lambda data, f=thumbimg, ef=errorfunc,
  File "thumbcache.py", line 153, in getthumb2
    getthumb3(id, thumbimg, errorfunc)
  File "thumbcache.py", line 168, in getthumb3
    for (t, cb) in THUMB_CBS[id]:
KeyError: lbedford@dublin.wbtsystems.com

While I was away for AAAI:

Error: 1
TypeError Exception in Tk callback
  Function: <function callit at b658ff8> (type: <type 'function'>)
  Args: ()
Traceback (innermost last):
  File "/usr/lib/python1.5/site-packages/Pmw-0.8.4/Pmw_0_8_4/lib/PmwBase.py", line 1690, in __call__
    return apply(self.func, args)
  File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 227, in callit
    apply(func, args)
  File "connection.py", line 201, in timer_callback
    engine.timeout.process()
  File "pygale/engine.py", line 32, in process
    callback()
  File "pygale/authcache.py", line 181, in <lambda>
    timeout_callback = lambda k=keyobj, s=self, l=client:\
  File "pygale/authcache.py", line 214, in handle_AKD_timeout
    self.cleanup_akd(key)
  File "pygale/authcache.py", line 204, in cleanup_akd
    cb(keyobj)
  File "pygale/sign.py", line 313, in <lambda>
    authcache.find_pubkey_akd(key, lambda key, d=sigdata, m=msg_data,
  File "pygale/sign.py", line 326, in decode_sig4
    authcache.save_pubkey_todisk(key)
  File "pygale/authcache.py", line 339, in save_pubkey_todisk
    return apply(KeyCache.save_pubkey_todisk, args)
  File "pygale/authcache.py", line 278, in save_pubkey_todisk
    f.write(keyobj.data())
TypeError: read-only buffer, None

Dan's reconnect bug:
Restart galed
Reconnect in Fugu
the automatic connect is already in progress
a single screen connects twice; once to ofb.net immediately (because of the
manual reconnect), and once to ofb.net.gale.org (perhaps because of the
automatic connect)

John Meacham's feature requests:
    random feature requests:
    -searchable puffs, 
    -multiple views of all puffs in buffer, with the ability to restrict the
    puffs in a given window arbitrarily, like only those from author foo, or
    only those that contain regex bar.
    -ability to snarf puffs from some sort of log upon startup. or populate
    puff buffer from log when changing subscriptions... 
    -ability to call external editor for the sending of puffs... , reply to
    (author/cat) would spawn an editor on a temporary file, fugu would send the
    puff once it gets the SIGCHLD (notification of death of editor) if the
    tempory file was modified. (similar to how mutt spawns vi externally).
    -ability to pipe selected puff or puffs through arbitrary commands.
    -ability to select an arbitrary set of puffs to perform these complicated
    operations on.

    if just one were to be implemented i would like to see the external editor,
    this also gives the ability to compose multiple puffs at once for free :)

JTR:

    I think I might dig it if metadata like "Subscribed to gib:ber:ish" was set
    off in a different font and with horizontal rules above.


            if os.path.exists(conffile):
		confvars = gale_env.parse_sys_conf(conffile)
		result = 'Reading Gale settings from ' + conffile

    conffile can be, say, "conf" with no path attached at this point, which
    means that if there's a file or directory called "conf" in the current
    directory it will try to open it.  This should, perhaps, be in a try
    block, and it should handle the case where conffile has a directory
    path better.

Shayde/Liam's traceback on public unsigned key:
  File "./roe.py", line 24, in evhandler
    for i in c.next_puffs():
  File "./pygale/pygale.py", line 716, in next_puffs
    self._engine.process(0)
  File "./pygale/engine.py", line 83, in process
    callback()
  File "./pygale/pygale.py", line 701, in handle_read
    self._puffs.append(self.process_puff(puffdata))
  File "./pygale/pygale.py", line 740, in process_puff
    p = p.verify(lambda p, s=self: s._puff_callback(p))
  File "./pygale/pygale.py", line 256, in verify
    callback(self)
  File "./pygale/pygale.py", line 740, in <lambda>
    p = p.verify(lambda p, s=self: s._puff_callback(p))
  File "./pygale/authcache.py", line 183, in <lambda>
    client.set_puff_callback(lambda p, s=self, k=keyobj,
  File "./pygale/authcache.py", line 240, in handle_key_puff
    sign.import_pubkey(keyobj, self.finish_key_puff, 0)
  File "./pygale/sign.py", line 230, in import_pubkey
    decode_sig(signature, msg_data, lambda k, u=keyobj, c=callback:
NameError: msg_data

When my home directory (with the thumbcache) goes down:
10-19 17:31:39 <exceptions.OSError instance at 88b8cc0>

Caused a crash out of the blue on apathy:

	Traceback (most recent call last):
	  File "fugu.py", line 42, in ?
	    main()
	  File "fugu.py", line 39, in main
	    ui.main()
	  File "ui.py", line 2259, in main
	    else:
	  File "/uns/share/lib/python1.6/lib-tk/Tkinter.py", line 494, in mainloop
	    self.tk.mainloop(n)
	  File "/scratch/tlau/fugu/pygale/engine.py", line 151, in <lambda>
	    Tkinter.WRITABLE, lambda f, m, s=self, h=handle:
	  File "/scratch/tlau/fugu/pygale/engine.py", line 168, in write_ready
	    self._callback_write_map[handle]()
	  File "pygale/asyncurl.py", line 65, in fetch_url2
	    self.callback(None)
	  File "thumbcache.py", line 229, in <lambda>
	    if DEBUG: print 'going to getthumb3 after saving to disk'
	  File "thumbcache.py", line 247, in getthumb2
	    img = bigimg.subsample(2)
	KeyError: hozer@altus.drgw.net


Crash out of the blue on molly, probably having to do with wtanaka's puff:

Traceback (most recent call last):
  File "fugu.py", line 42, in ?
    main()
  File "fugu.py", line 39, in main
    ui.main()
  File "ui.py", line 2367, in main
    m.mainloop()
  File "/usr/local/lib/python2.0/lib-tk/Tkinter.py", line 931, in mainloop
    self.tk.mainloop(n)
  File "/home/tlau/src/fugu/pygale/engine.py", line 145, in <lambda>
    Tkinter.READABLE, lambda f, m, s=self, h=handle:
  File "/home/tlau/src/fugu/pygale/engine.py", line 165, in read_ready
    self._callback_map[handle]()
  File "/home/tlau/src/fugu/pygale/pygale.py", line 715, in handle_read
    self._puffs.append(self.process_puff(puffdata))
  File "/home/tlau/src/fugu/pygale/pygale.py", line 752, in process_puff
    p = p.verify(lambda p, s=self: s._verify_callback(p))
  File "/home/tlau/src/fugu/pygale/pygale.py", line 276, in verify
    sign.decode_sig(sig, frag, lambda key, s=self, p=p, c=callback:
  File "/home/tlau/src/fugu/pygale/sign.py", line 99, in decode_sig
    import_pubkey(keyobj, lambda k, d=sigdata,
  File "/home/tlau/src/fugu/pygale/sign.py", line 128, in import_pubkey
    callback(keyobj)
  File "/home/tlau/src/fugu/pygale/sign.py", line 99, in <lambda>
    import_pubkey(keyobj, lambda k, d=sigdata,
  File "/home/tlau/src/fugu/pygale/sign.py", line 316, in decode_sig2
    authcache.find_pubkey_fromdisk(key, lambda key, d=sigdata, m=msg_data,
  File "/home/tlau/src/fugu/pygale/authcache.py", line 344, in find_pubkey_fromdisk 
    return apply(KeyCache.find_pubkey_fromdisk, args)
  File "/home/tlau/src/fugu/pygale/authcache.py", line 104, in find_pubkey_fromdisk 
    path = os.path.join(prefix, suffix, name)
  File "/usr/local/lib/python2.0/posixpath.py", line 43, in join
    if b[:1] == '/':
TypeError: unsliceable object

TypeError Exception in Tk callback
  Function: <function callit at 0x8576044> (type: <type 'function'>)
  Args: ()
Traceback (innermost last):
  File "/usr/local/lib/python2.0/site-packages/Pmw/Pmw_0_8_1/lib/PmwBase.py", line 1480, in __call__
    return apply(self.func, args)
  File "/usr/local/lib/python2.0/lib-tk/Tkinter.py", line 437, in callit
    apply(func, args)
  File "ui.py", line 645, in <lambda>
    text.after_idle(lambda pl=conf.pufflist(), s=self, c=conf:
  File "ui.py", line 688, in idle_pufflist
    conf.addpuff(p, 0)
  File "connection.py", line 369, in addpuff
    time.localtime(msg.get('id/time')))
TypeError: illegal argument type for built-in operation


Crash on startup when no gale server can be found:

Traceback (innermost last):
  File "/usr/local/bin/fugu", line 42, in ?
    main()
  File "/usr/local/bin/fugu", line 39, in main
    ui.main()
  File "/usr/local/fugu/lib/fugu-0.9.9f/ui.py", line 2349, in main
    m.mainloop()
  File "/usr/lib/python1.5/lib-tk/Tkinter.py", line 492, in mainloop
    self.tk.mainloop(n)
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/engine.py", line 145, in <lambda
>
    Tkinter.READABLE, lambda f, m, s=self, h=handle:
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/engine.py", line 165, in read_re
a
dy
    self._callback_map[handle]()
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/pygale.py", line 562, in <lambda
>
    self._engine.add_callback(sock, lambda self=self, s=sock, h=host,
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/pygale.py", line 589, in connect
3
    self._on_connect(host)
  File "/usr/local/fugu/lib/fugu-0.9.9f/connection.py", line 155, in <lambda>
    self._galec.set_onconnect(lambda h, s=self, sub=sub:
  File "/usr/local/fugu/lib/fugu-0.9.9f/connection.py", line 169, in make_subs
    self.register_filehandler()
  File "/usr/local/fugu/lib/fugu-0.9.9f/connection.py", line 184, in register_f
i
lehandler
    self._galec.set_puff_callback(lambda p, s=self: s._master.recvpuff(s, p))
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/pygale.py", line 665, in set_puf
f
_callback
    self._engine.add_callback(self._sock, self.handle_read)
  File "/usr/local/fugu/lib/fugu-0.9.9f/pygale/engine.py", line 144, in add_cal
l
back
    Tkinter.tkinter.createfilehandler(handle.fileno(),
AttributeError: 'None' object has no attribute 'fileno'

----------------------------------------------------------------------

Setup wizard does not name private key file properly

----------------------------------------------------------------------
Related to network issues via firewall/RoadRunner:

Traceback (most recent call last):
  File "fugu.py", line 46, in ?
    main()
  File "fugu.py", line 43, in main
    ui.main()
  File "ui.py", line 2266, in main
    m.mainloop()
  File "/usr/local/lib/python2.1/lib-tk/Tkinter.py", line 930, in mainloop
    self.tk.mainloop(n)
  File "pygale/engine.py", line 154, in <lambda>
    Tkinter.READABLE, lambda f, m, s=self, h=handle:
  File "pygale/engine.py", line 174, in read_ready
    self._callback_map[handle]()
  File "pygale/pygale.py", line 644, in <lambda>
    self._engine.add_callback(sock, lambda self=self, s=sock, h=host,
  File "pygale/pygale.py", line 651, in connect3
    self.__sockets_in_progress.remove(sock)
ValueError: list.remove(x): x not in list

OFB going up/down causes Fugu crash:

Setting debugging GC
Traceback (most recent call last):
  File "fugu.py", line 46, in ?
    main()
  File "fugu.py", line 43, in main
    ui.main()
  File "ui.py", line 2266, in main
    m.mainloop()
  File "/usr/local/lib/python2.1/lib-tk/Tkinter.py", line 930, in mainloop
    self.tk.mainloop(n)
  File "pygale/engine.py", line 154, in <lambda>
    Tkinter.READABLE, lambda f, m, s=self, h=handle:
  File "pygale/engine.py", line 174, in read_ready
    self._callback_map[handle]()
  File "pygale/pygale.py", line 644, in <lambda>
    self._engine.add_callback(sock, lambda self=self, s=sock, h=host,
  File "pygale/pygale.py", line 672, in connect3
    self._on_connect(host)
  File "ui.py", line 370, in <lambda>
    self._galeconn.set_onconnect(lambda h, r=reconnect, s=self:
  File "ui.py", line 383, in on_sendconn
    self.create_akd_server(reconnect)
  File "ui.py", line 388, in create_akd_server
    self._galeconn.sub_to([akd_cat], cb)
  File "pygale/pygale.py", line 719, in sub_to
    lookup_all_locations(loc_list, lambda l, s=self, cb=cb:
  File "pygale/pygale.py", line 1350, in lookup_all_locations
    lookup_location(loc, loc_cb, do_akd=0)
  File "pygale/pygale.py", line 1244, in lookup_location
    cb(loc, [''])
  File "pygale/pygale.py", line 1348, in <lambda>
    loc_cb = lambda new_loc, keylist, l=loc, c=collector, cb=new_cb:\
  File "pygale/pygale.py", line 1365, in _loc_coll_callback
    cb(collector.getvalues())
  File "pygale/pygale.py", line 1343, in <lambda>
    new_cb = lambda keys, cb=cb:\
  File "pygale/pygale.py", line 1372, in lookup_all_locations_akd
    callback(loc_key_list)
  File "pygale/pygale.py", line 719, in <lambda>
    lookup_all_locations(loc_list, lambda l, s=self, cb=cb:
  File "pygale/pygale.py", line 761, in sub_to2
    self._sock.send(req)
socket.error: (32, 'Broken pipe')

On Joshua's machine:
Fixed.  Caused by a '&' in the GECOS field not being escaped in the XML.

Traceback (most recent call last):
  File "/usr/X11R6/lib/fugu-1.1.6/config.py", line 604, in load_default_config
    self.load_vars(parser.tree)
  File "/usr/X11R6/lib/fugu-1.1.6/config.py", line 524, in load_vars
    'presence')
  File "/usr/X11R6/lib/fugu-1.1.6/config.py", line 347, in getlist
    return node.getlist(nodename)
AttributeError: 'None' object has no attribute 'getlist'
Unable to load default configuration
No configuration file found.  Using defaults.
Traceback (most recent call last):
  File "/usr/X11R6/bin/fugu", line 46, in ?
    main()
  File "/usr/X11R6/bin/fugu", line 43, in main
    ui.main()
  File "/usr/X11R6/lib/fugu-1.1.6/ui.py", line 2228, in main
    m = GaleWin(root)
  File "/usr/X11R6/lib/fugu-1.1.6/ui.py", line 257, in __init__
    self._create_widgets()
  File "/usr/X11R6/lib/fugu-1.1.6/ui.py", line 477, in _create_widgets
    self.regen_screenmenu()
  File "/usr/X11R6/lib/fugu-1.1.6/ui.py", line 1161, in regen_screenmenu
    for conf in Config.SUBLIST:
AttributeError: ConfigClass instance has no attribute 'SUBLIST'

Create a bunch of new screens, select one of them while the Config window
is still up, delete the one currently displayed:

Error: 1
IndexError Exception in Tk callback
  Function: <method ScreenPop.delete of ScreenPop instance at 0x84249b4> (type: <type 'instance method'>)
  Args: ()
Traceback (innermost last):
  File "/usr/local/lib/python2.1/site-packages/Pmw/Pmw_0_8_5/lib/PmwBase.py", line 1690, in __call__
    return apply(self.func, args)
  File "ui.py", line 2093, in delete
    if self._master.is_curscreen(delwindow):
  File "ui.py", line 834, in is_curscreen
    return Config.SUBLIST[self._curscreen] == screen
IndexError: list index out of range
