Your message dated Sun, 18 Sep 2005 00:09:52 -0500 with message-id <[EMAIL PROTECTED]> and subject line Closing has caused the attached Bug report to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what I am talking about this indicates a serious mail system misconfiguration somewhere. Please contact me immediately.) Debian bug tracking system administrator (administrator, Debian Bugs database) -------------------------------------- Received: (at submit) by bugs.debian.org; 30 Aug 2001 03:49:43 +0000 >From [EMAIL PROTECTED] Wed Aug 29 22:49:43 2001 Return-path: <[EMAIL PROTECTED]> Received: from mail303.mail.bellsouth.net (imf03bis.bellsouth.net) [205.152.58.163] by master.debian.org with esmtp (Exim 3.12 1 (Debian)) id 15cIpr-0005Ut-00; Wed, 29 Aug 2001 22:49:43 -0500 Received: from mizar.alcor.net ([66.156.8.104]) by imf03bis.bellsouth.net (InterMail vM.5.01.01.01 201-252-104) with ESMTP id <[EMAIL PROTECTED]> for <[EMAIL PROTECTED]>; Wed, 29 Aug 2001 23:50:10 -0400 Received: from mdz by mizar.alcor.net with local (Exim 3.32 #1 (Debian)) id 15cIpL-0001y9-00 for <[EMAIL PROTECTED]>; Wed, 29 Aug 2001 23:49:11 -0400 Date: Wed, 29 Aug 2001 23:49:11 -0400 From: Matt Zimmerman <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Subject: Ability to read archive files Message-ID: <[EMAIL PROTECTED]> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="8X7/QrJGcKSMr1RN" Content-Disposition: inline User-Agent: Mutt/1.3.20i Sender: Matt Zimmerman <[EMAIL PROTECTED]> Delivered-To: [EMAIL PROTECTED] --8X7/QrJGcKSMr1RN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Package: xmms Severity: wishlist Tags: patch I sent this patch upstream a couple of years ago, but never heard any response back, so I guess they weren't interested. I'm filing it here so that if someone else finds it useful, maybe they'll integrate it with the current version. -- - mdz --8X7/QrJGcKSMr1RN Content-Type: message/rfc822 Content-Disposition: inline Date: Sat, 11 Dec 1999 05:07:02 -0500 From: Matt Zimmerman <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Subject: XMMS and compressed files/archives Message-ID: <[EMAIL PROTECTED]> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="ew6BAiZeqk4r7MaW" User-Agent: Mutt/1.1.1i --ew6BAiZeqk4r7MaW Content-Type: text/plain; charset=us-ascii I imagine that most people use xmms for playing mp3 files, I think one of its strengths is the input plugin architecture, allowing it to combine many formats into a single music collection. Some non-mp3 formats, such as the various MOD formats, compress rather well. Having a number of these in my collection, I thought it would be nice if xmms could scan the compressed archives and extract files on-demand. Attached is a patch (against 0.9.5.1, but I tested it with the latest CVS) that allows it to do just that. The changes are basically: - The addition of an 'archive' module (archive.h, archive.c) with functions for testing whether a file is an archive, listing its members, and extracting a member into a temporary file - The __playlist_ins function in playlist.c takes an addional argument, the name of the archive file if the specified file is contained in an archive - The playlist_ins function in playlist.c will check to see if a file is an archive, and scan it as appropriate - The PlaylistEntry structure contains additional elements for holding the name of the archive file and the temporary file - A new playlist_ins_archive function to scan an archive for addition to the playlist - Archive type is determined solely by filename extension. It may be desirable to check for magic numbers, etc. eventually. Currently, .gz, .bz2, .tar.gz, .tar.bz2, .tar, and .zip are supported. .zip is by far the fastest to extract a single member, because of the central directory. I have been using it for a while now, and it seems to work well. YMMV. There are some known issues with it: - It does not extract each file before running input_check_file() on it. I decided this would be too slow. So, compressed files are not available for reading by the input plugins. This is not a problem for the mikmod plugin, but the WAV plugin (and perhaps others) want to read the file. Plugins which want to read the file will fail to recognize archive members. - For the same reason, song titles and durations are not known until the song has been selected for playing (and thus extracted). - I couldn't come up with a good way to determine when the temporary files should be deleted, so they hang around until the playlist entry is deleted. This also means that if the file is already extracted, it will be reused if the song is played again. - The .m3u playlist format doesn't provide a way to store information about archives. I work around this by only storing the name of the archive, so when the playlist is loaded, all files in the archive will be loaded. It would be nice if the playlist could contain only certain files in an archive. It is a little rough around the edges, but I thought you might be interested in looking at it. There is currently no copyright notice on the new module, but it would be my intention that it would fall under the GPL along with the rest of the code, if it were merged. The only critical change I think is necessary is for it to use mkstemp(3) or some such to create a secure temporary file. Currently, it extracts the file under its original name in /tmp. My thanks to you and the rest of the xmms team for a great application. Feel free to contact me about these modifications. -- - mdz --ew6BAiZeqk4r7MaW Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="xmms-archives.diff" diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/Makefile.am xmms-0.9.5.1+mdz/xmms/Makefile.am *** xmms-0.9.5.1/xmms/Makefile.am Sun Sep 5 02:36:41 1999 --- xmms-0.9.5.1+mdz/xmms/Makefile.am Wed Dec 1 19:56:48 1999 *************** *** 45,50 **** --- 45,51 ---- hints.c hints.h \ about.c about.h \ plugin.h \ + archive.c archive.h \ xmms.h getopt.c getopt1.c getopt.h EXTRA_DIST= xmms_logo.xpm diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/archive.c xmms-0.9.5.1+mdz/xmms/archive.c *** xmms-0.9.5.1/xmms/archive.c Wed Dec 31 16:00:00 1969 --- xmms-0.9.5.1+mdz/xmms/archive.c Fri Dec 10 21:56:47 1999 *************** *** 0 **** --- 1,260 ---- + #include <fcntl.h> + #include <fnmatch.h> + + #include "xmms.h" + + #define ARCHIVE_MAX_ARGS 16 + + typedef struct { + /* Shell wildcard pattern */ + gchar *archive_pattern; + + /* Command to list archive members */ + gchar *list_command[ARCHIVE_MAX_ARGS + 1]; + + /* offset from beginning of line to filename */ + gint list_offset; + + /* Command to extract one member from an archive */ + gchar *extract_command[ARCHIVE_MAX_ARGS + 1]; + + } archive_type; + + /* List of recognized archive types */ + + static const archive_type archive_types[] = { + /* gzip'd tar archives */ + { "*.tar.gz", + { "tar", "tzf", "ARCHIVE_NAME", NULL }, 0, + { "tar", "xzOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL } + }, + + /* bzip2'd tar archives (requires a recent tar) */ + { "*.tar.bz2", + { "tar", "tIf", "ARCHIVE_NAME", NULL }, 0, + { "tar", "xIOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL } + }, + + /* tar archives */ + { "*.tar", + { "tar", "tf", "ARCHIVE_NAME", NULL }, 0, + { "tar", "xOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL } + }, + + /* zip archives */ + { "*.zip", + { "unzip", "-qql", "ARCHIVE_NAME", NULL }, 28, + { "unzip", "-qqp", "ARCHIVE_NAME", "MEMBER_NAME", NULL } + }, + + /* gzip'd files */ + { "*.gz", + { NULL }, -1, /* Member filename implied by archive filename */ + { "gzip", "-dqc", "ARCHIVE_NAME", NULL } + }, + + /* bzip2'd files */ + { "*.bz2", + { NULL }, -1, /* Member filename implied by archive filename */ + { "bzip2", "-dqc", "ARCHIVE_NAME", NULL } + }, + + { NULL, { NULL }, -1, { NULL } } + + }; + + /* Find the associated type for a given (possible) archive file */ + + static const archive_type *archive_get_type(const gchar *archive) + { + const archive_type *type; + + for(type = archive_types ; + type != NULL && type ->archive_pattern != NULL ; + ++type) { + + if (fnmatch(type->archive_pattern, archive, 0) == 0) + return type; + } + + return NULL; + } + + /* Is the specified file an archive? */ + + gboolean archive_isarchive(const gchar *archive) + { + const archive_type *type = archive_get_type(archive); + + return type == NULL ? FALSE : TRUE; + } + + /* List the members of an archive */ + + GList *archive_list_members(const gchar *archive) + { + const archive_type *type = archive_get_type(archive); + gchar *list_command[ARCHIVE_MAX_ARGS]; + guint arg; + GList *members = NULL; + + if (type == NULL) + return NULL; + + if (type->list_command[0] == NULL) { + /* Member filename implied by removing extension */ + + /* + * XXX - This code makes some assumptions about single-file + * archives of this type (e.g. gzip, bzip2): + * + * 1. The filename does not have a compound extension + * (e.g. .tar.gz) + * + * 2. The filename has an extension (at least one dot in the filename) + * + * It will fail if these conditions are not met, so if archive + * types are added that do not meet these conditions, this will + * have to be fixed */ + + gchar *temp = g_strdup(archive); + gchar *ext = strrchr(temp, '.'); + gchar *slash = strrchr(temp, '/'); + gchar *member; + + if (ext == NULL) + return NULL; + + *ext = '\0'; + member = (slash == NULL) ? g_strdup(archive) : g_strdup(slash + 1); + + members = g_list_append(members, member); + + g_free(temp); + + return members; + } else { + /* Need to execute a command to get the list of memmbers */ + int commandpipe[2]; + int waitstatus; + char buf[1024]; + + for(arg = 0 ; + arg < ARCHIVE_MAX_ARGS && type->list_command[arg] != NULL ; + ++arg) { + if (strcmp(type->list_command[arg], "ARCHIVE_NAME") == 0) + list_command[arg] = g_strdup(archive); + else + list_command[arg] = g_strdup(type->list_command[arg]); + + } + + list_command[arg] = NULL; + + if (pipe(commandpipe) == 0) { + if (fork()) { + FILE *child; + char *line; + close(commandpipe[1]); + + child = fdopen(commandpipe[0], "r"); + while ( (line = fgets(buf, 1024, child)) != NULL) { + char *newline = strrchr(line, '\n'); + + if (newline != NULL) + *newline = '\0'; + + if (type->list_offset > 0) + line += type->list_offset; + + members = g_list_append(members, g_strdup(line)); + } + + waitstatus = wait(NULL); + } else { + close(commandpipe[0]); + dup2(commandpipe[1], fileno(stdout)); + execvp(list_command[0], list_command); + exit(255); + } + + } else { + fprintf(stderr, "archive_get_members: error creating pipe (%d)\n", + errno); + } + + for(arg = 0 ; list_command[arg] != NULL ; ++arg) { + g_free(list_command[arg]); + } + } + + return members; + } + + /* Extract one member of an archive */ + + gchar *archive_extract_member(const gchar *archive, const gchar *member) + { + const archive_type *type = archive_get_type(archive); + gchar *extract_command[ARCHIVE_MAX_ARGS]; + gchar *temp_file = NULL; + int temp_file_fd = -1; + guint arg; + int waitstatus; + + if (type == NULL || archive == NULL || member == NULL) + return NULL; + + /* XXX - this should be changed to guarantee uniqueness and be somewhat + * more secure + */ + temp_file = g_strdup("/tmp/"); + temp_file = g_strconcat(temp_file, member, NULL); + + unlink(temp_file); + temp_file_fd = open(temp_file, O_WRONLY|O_CREAT|O_EXCL, 0600); + if (temp_file_fd < 0) { + g_free(temp_file); + fprintf(stderr, + "archive_extract_member: Problems opening temp file %s: %s\n", + temp_file, strerror(errno)); + return NULL; + } + + for(arg = 0 ; + arg < ARCHIVE_MAX_ARGS && type->extract_command[arg] != NULL ; + ++arg) { + if (strcmp(type->extract_command[arg], "ARCHIVE_NAME") == 0) + extract_command[arg] = g_strdup(archive); + else if (strcmp(type->extract_command[arg], "TEMP_NAME") == 0) + extract_command[arg] = g_strdup(temp_file); + else if (strcmp(type->extract_command[arg], "MEMBER_NAME") == 0) + extract_command[arg] = g_strdup(member); + else + extract_command[arg] = g_strdup(type->extract_command[arg]); + + } + + extract_command[arg] = NULL; + + if (fork()) { + waitstatus = wait(NULL); + } else { + dup2(temp_file_fd, fileno(stdout)); + execvp(extract_command[0], extract_command); + exit(255); + } + + for(arg = 0 ; extract_command[arg] != NULL ; ++arg) { + g_free(extract_command[arg]); + } + + if (waitstatus > 0) { + return temp_file; + } else { + g_free(temp_file); + fprintf(stderr, "Problem executing extract commend, wait status: %d\n", + waitstatus); + return NULL; + } + } diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/archive.h xmms-0.9.5.1+mdz/xmms/archive.h *** xmms-0.9.5.1/xmms/archive.h Wed Dec 31 16:00:00 1969 --- xmms-0.9.5.1+mdz/xmms/archive.h Thu Dec 2 12:21:06 1999 *************** *** 0 **** --- 1,5 ---- + #include "xmms.h" + + gboolean archive_isarchive(const gchar *archive); + GList *archive_list_members(const gchar *archive); + gchar *archive_extract_member(const gchar *archive, const gchar *member); diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/playlist.c xmms-0.9.5.1+mdz/xmms/playlist.c *** xmms-0.9.5.1/xmms/playlist.c Sat Sep 25 06:05:25 1999 --- xmms-0.9.5.1+mdz/xmms/playlist.c Fri Dec 10 21:51:18 1999 *************** *** 57,62 **** --- 57,68 ---- g_free(entry->filename); if (entry->title) g_free(entry->title); + if (entry->archive_filename) + g_free(entry->archive_filename); + if (entry->temp_filename) { + unlink(entry->temp_filename); + g_free(entry->temp_filename); + } g_free(entry); node = node->next; } *************** *** 112,121 **** --- 118,136 ---- else playlist_position = NULL; } + if (entry->filename) g_free(entry->filename); if (entry->title) g_free(entry->title); + if (entry->archive_filename) + g_free(entry->archive_filename); + + if (entry->temp_filename) { + unlink(entry->temp_filename); + g_free(entry->temp_filename); + } + playlist = g_list_remove_link(playlist, node); g_free(entry); g_list_free_1(node); *************** *** 139,150 **** } ! static void __playlist_ins(gchar * filename, glong pos) { PlaylistEntry *entry; entry = g_malloc0(sizeof (PlaylistEntry)); entry->filename = g_strdup(filename); entry->length = -1; pthread_mutex_lock(&playlist_mutex); --- 154,172 ---- } ! static void __playlist_ins(gchar * filename, gchar * archive_filename, ! glong pos) { PlaylistEntry *entry; entry = g_malloc0(sizeof (PlaylistEntry)); entry->filename = g_strdup(filename); + entry->archive_filename = NULL; + entry->temp_filename = NULL; + + if (archive_filename != NULL) + entry->archive_filename = g_strdup(archive_filename); + entry->length = -1; pthread_mutex_lock(&playlist_mutex); *************** *** 162,169 **** if (ext && ((!strcasecmp(ext, ".m3u") || !strcasecmp(ext, ".pls")))) playlist_load_ins(filename, pos); else if (input_check_file(filename)) ! __playlist_ins(filename, pos); } /* void playlist_add_dir(gchar * path) */ --- 184,194 ---- if (ext && ((!strcasecmp(ext, ".m3u") || !strcasecmp(ext, ".pls")))) playlist_load_ins(filename, pos); else + if (archive_isarchive(filename)) + playlist_ins_archive(filename, pos); + else if (input_check_file(filename)) ! __playlist_ins(filename, NULL, pos); } /* void playlist_add_dir(gchar * path) */ *************** *** 191,197 **** node = list; while (node) { ! __playlist_ins(node->data, pos); entries++; if (pos > 0) pos++; --- 216,222 ---- node = list; while (node) { ! __playlist_ins(node->data, NULL, pos); entries++; if (pos > 0) pos++; *************** *** 221,227 **** } else if (input_check_file(filename)) { ! __playlist_ins(filename, pos); entries++; if (pos > 0) pos++; --- 246,252 ---- } else if (input_check_file(filename)) { ! __playlist_ins(filename, NULL, pos); entries++; if (pos > 0) pos++; *************** *** 236,241 **** --- 261,293 ---- } /* + * Add all members of an archive to the playlist + */ + guint playlist_ins_archive(gchar *archive, glong pos) + { + GList *list, *node; + guint entries = 0; + + if ( (list = archive_list_members(archive)) != NULL) { + node = list; + while (node != NULL) + { + if (input_check_file(node->data)) { + __playlist_ins(node->data, archive, pos); + entries++; + if (pos > 0) + pos++; + } + + node = g_list_next(node); + } + } + + return entries; + } + + + /* * I'm not sure if this is the correct way to do it but it seems to work fine */ *************** *** 324,331 **** PL_LOCK(); entry = g_list_nth(playlist, get_playlist_position())->data; PL_UNLOCK(); ! ! input_play(entry->filename); if (input_get_time() != -1) { --- 376,399 ---- PL_LOCK(); entry = g_list_nth(playlist, get_playlist_position())->data; PL_UNLOCK(); ! ! if (entry->archive_filename != NULL && entry->temp_filename == NULL) { ! gchar *temp_filename = archive_extract_member(entry->archive_filename, ! entry->filename); ! PL_LOCK(); ! entry->temp_filename = temp_filename; ! PL_UNLOCK(); ! ! if (entry->temp_filename == NULL) { ! fprintf(stderr, "Failed to unarchive %s from %s!\n", ! entry->filename, entry->archive_filename); ! } ! } ! ! if (entry->temp_filename != NULL) ! input_play(entry->temp_filename); ! else ! input_play(entry->filename); if (input_get_time() != -1) { *************** *** 608,613 **** --- 676,684 ---- FILE *file; gchar *ext; gboolean is_pls = FALSE; + GHashTable *archives = NULL; + + archives = g_hash_table_new(g_str_hash, g_str_equal); if ((file = fopen(filename, "w")) != NULL) { *************** *** 626,639 **** while (node) { entry = (PlaylistEntry *) node->data; ! if (is_pls) fprintf(file, "File%d=%s\n", g_list_position(playlist, node) + 1, entry->filename); ! else ! fprintf(file, "%s\n", entry->filename); node = node->next; } PL_UNLOCK(); fclose(file); return TRUE; } return FALSE; --- 697,725 ---- while (node) { entry = (PlaylistEntry *) node->data; ! if (is_pls) { fprintf(file, "File%d=%s\n", g_list_position(playlist, node) + 1, entry->filename); ! fprintf(file, "ArchiveFile%d=%s\n", ! g_list_position(playlist, node) + 1, ! entry->archive_filename); ! } else { ! if (entry->archive_filename != NULL) { ! /* Only include archives once */ ! if (!g_hash_table_lookup(archives, entry->archive_filename)) { ! g_hash_table_insert(archives, entry->archive_filename, entry->archive_filename); ! fprintf(file, "%s\n", entry->archive_filename); ! } ! } else { ! fprintf(file, "%s\n", entry->filename); ! } ! ! } node = node->next; } PL_UNLOCK(); fclose(file); + + g_hash_table_destroy(archives); return TRUE; } return FALSE; *************** *** 665,680 **** *temp = '\0'; else { ! __playlist_ins(filename, pos); return; } temp = g_strdup_printf("%s/%s", path, filename); ! __playlist_ins(temp, pos); g_free(temp); g_free(path); } else ! __playlist_ins(filename, pos); } guint playlist_load_ins(gchar * filename, glong pos) --- 751,768 ---- *temp = '\0'; else { ! __playlist_ins(filename, NULL, pos); return; } temp = g_strdup_printf("%s/%s", path, filename); ! __playlist_ins(temp, NULL, pos); g_free(temp); g_free(path); } + else if (archive_isarchive(filename)) + playlist_ins_archive(filename, pos); else ! __playlist_ins(filename, NULL, pos); } guint playlist_load_ins(gchar * filename, glong pos) diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/playlist.h xmms-0.9.5.1+mdz/xmms/playlist.h *** xmms-0.9.5.1/xmms/playlist.h Sun Sep 12 14:02:33 1999 --- xmms-0.9.5.1+mdz/xmms/playlist.h Wed Dec 1 21:45:04 1999 *************** *** 20,26 **** typedef struct { ! gchar *filename; gchar *title; gint length; gboolean selected; --- 20,28 ---- typedef struct { ! gchar *filename; /* Member name, if an archive member */ ! gchar *archive_filename; ! gchar *temp_filename; gchar *title; gint length; gboolean selected; *************** *** 35,40 **** --- 37,43 ---- /* void playlist_add_dir(gchar * dir); */ #define playlist_add_dir(directory) playlist_ins_dir(directory, -1) guint playlist_ins_dir(gchar * dir, glong pos); + guint playlist_ins_archive(gchar *archive, glong pos); /* void playlist_add_url_string(gchar * string); */ #define playlist_add_url_string(string) playlist_ins_url_string(string, -1) guint playlist_ins_url_string(gchar * string, glong pos); diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/xmms.h xmms-0.9.5.1+mdz/xmms/xmms.h *** xmms-0.9.5.1/xmms/xmms.h Sun Sep 5 02:36:42 1999 --- xmms-0.9.5.1+mdz/xmms/xmms.h Wed Dec 1 19:57:36 1999 *************** *** 75,80 **** --- 75,81 ---- #include "equalizer.h" #include "about.h" #include "hints.h" + #include "archive.h" #include "config.h" --ew6BAiZeqk4r7MaW-- --8X7/QrJGcKSMr1RN-- --------------------------------------- Received: (at 110623-done) by bugs.debian.org; 18 Sep 2005 05:10:25 +0000 >From [EMAIL PROTECTED] Sat Sep 17 22:10:25 2005 Return-path: <[EMAIL PROTECTED]> Received: from ns3.jiffynet-hosting.net (server146.jiffynet-hosting.net) [69.57.162.87] by spohr.debian.org with esmtp (Exim 3.36 1 (Debian)) id 1EGrRZ-00066Z-00; Sat, 17 Sep 2005 22:10:25 -0700 Received: from dsl-201-129-37-187.prod-infinitum.com.mx ([201.129.37.187] helo=[192.168.1.48]) by server146.jiffynet-hosting.net with asmtp (Exim 4.34) id 1EGrRN-0003o5-9g for [EMAIL PROTECTED]; Sun, 18 Sep 2005 01:10:18 -0400 Subject: Closing From: David Moreno Garza <[EMAIL PROTECTED]> To: [EMAIL PROTECTED] Content-Type: text/plain Date: Sun, 18 Sep 2005 00:09:52 -0500 Message-Id: <[EMAIL PROTECTED]> Mime-Version: 1.0 X-Mailer: Evolution 2.2.3 Content-Transfer-Encoding: 7bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server146.jiffynet-hosting.net X-AntiAbuse: Original Domain - bugs.debian.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - debian.org X-Source: X-Source-Args: X-Source-Dir: Delivered-To: [EMAIL PROTECTED] X-Spam-Checker-Version: SpamAssassin 2.60-bugs.debian.org_2005_01_02 (1.212-2003-09-23-exp) on spohr.debian.org X-Spam-Level: X-Spam-Status: No, hits=-2.0 required=4.0 tests=BAYES_00,ONEWORD autolearn=no version=2.60-bugs.debian.org_2005_01_02 I'm closing this bug since: - The patch attached is no longer able to be applied. - Last activity on the bug was in 2001. Cheers, -- David Moreno Garza <[EMAIL PROTECTED]> | http://www.damog.net/ <[EMAIL PROTECTED]> | GPG: C671257D Come to where the flavor is. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]