From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Wed, 18 Feb 2004 16:34:57 +0600 From: Alexey Morozov To: ALT Devel discussion list Message-ID: <20040218103457.GK17184@pyro.hopawar.private.net> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="fDERRRNgB4on1jOB" Content-Disposition: inline User-Agent: Mutt/1.4.2.1i Subject: [devel] IMAP headers cache =?koi8-r?b?xMzR?= mutt X-BeenThere: devel@altlinux.ru X-Mailman-Version: 2.1.4 Precedence: list Reply-To: ALT Devel discussion list List-Id: ALT Devel discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Feb 2004 10:35:22 -0000 Archived-At: List-Archive: List-Post: --fDERRRNgB4on1jOB Content-Type: multipart/mixed; boundary="yiup30KVCQiHUZFC" Content-Disposition: inline Content-Transfer-Encoding: 8bit --yiup30KVCQiHUZFC Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: 8bit 2ldv: Дмитрий, а Вы не могли бы пересобрать mutt с патчиком, взятым с http://dwyn.net/mutt/. У меня работает, причем, на медленных линиях/больших ящиках - просто спасение (по моим наблюдениям, UID'ы закачиваются примерно в 30 раз быстрее хидеров). P.S. Еще оффлайн-режим сделать, и тогда mutt вообще станет приличной читалкой :-P --yiup30KVCQiHUZFC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mutt.spec" Name: mutt %define pversion 1.4.2.1 Version: %{pversion}i Release: alt2 Serial: 3 %def_without dotlock %define docdir %_docdir/%name-%version Summary: A text mode mail and news user agent License: GPL Group: Networking/Mail Url: http://www.mutt.org/ Source: ftp://ftp.%name.org/pub/%name/%name-%version.tar.bz2 Source1: http://jblosser.firinn.org/pub/config/%name/%name-16.xpm Source2: http://jblosser.firinn.org/pub/config/%name/%name-32.xpm Source3: http://www.math.fu-berlin.de/~guckes/%name/%name-48.xpm Source4: %name.menu Source5: http://www.fefe.de/%{name}faq/faq.html Source6: mutt-FAQ.ru.html Source7: http://solidlinux.com/~justin/%name/%name-gnupg-howto.txt Source10: patchlist.sh %define rr_version 1.4 %define vvv_version 1.4 Patch11: http://mutt.kiev.ua/download/%name-%rr_version/%name-%rr_version.rr.compressed-alt.patch Patch12: http://mutt.kiev.ua/download/%name-%vvv_version/%name-%vvv_version.vvv.initials.patch Patch13: http://mutt.kiev.ua/download/%name-%vvv_version/%name-%vvv_version.vvv.nntp-alt.patch Patch14: http://mutt.kiev.ua/download/%name-%vvv_version/%name-%vvv_version.vvv.quote.patch Patch21: %name-1.3.22.1-alt-no_dotlock.patch Patch22: %name-1.2.5-alt-8bitpgp.patch Patch23: %name-1.3.28-alt-flea.patch Patch24: %name-1.3.22.1-alt-altyesorno.patch Patch25: %name-1.3.22.1-alt-send_charset-koi8-r.patch Patch26: %name-1.3.22.1-alt-muttrc-show-docs.patch Patch27: %name-1.3.22.1-alt-compressed-hooks.patch Patch28: %name-1.4-alt-m4_fixes.patch Patch29: %name-1.4-owl-muttbug-tmp.patch Patch30: %name-1.4-owl-tmp.patch Patch31: %name-1.4-alt-tmp.patch Patch32: %name-1.4-alt-fixes.patch Patch33: %name-1.4-alt-gpg.patch Patch41: %name-1.4-headercache.patch Requires: MTA, urlview %set_autoconf_version 2.13 %set_automake_version 1.4 BuildPreReq: rpm-build >= 4.0.4-alt10, autoconf = 2.13, automake = 1.4 BuildPreReq: OpenSP groff-base libncurses-devel libssl-devel sgml-tools %description Mutt is a feature-rich text-based mail user agent. Mutt supports local and remote mail spools (POP3 and IMAP, including with SSL), MIME, OpenPGP (PGP/MIME) with GnuPG and PGP, colored display, threading, and a lot of customization including arbitrary message headers, key remapping, colors, and more. %prep %setup -q -n %name-%pversion %__install -p -m755 %SOURCE10 . %patch11 -p1 %patch12 -p1 %patch13 -p1 %patch14 -p1 %patch21 -p1 %patch22 -p1 %patch23 -p1 %patch24 -p1 %patch25 -p1 %patch26 -p1 %patch27 -p1 %patch28 -p1 %patch29 -p1 %patch30 -p1 %patch31 -p1 %patch32 -p1 %patch33 -p1 %patch41 -p1 find -type f -name \*.orig -print -delete %build export ac_cv_path_GDB=/usr/bin/gdb export ac_cv_path_ISPELL=/usr/bin/ispell export ac_cv_path_SENDMAIL=/usr/sbin/sendmail %if_without dotlock export mutt_cv_worldwrite=no export mutt_cv_groupwrite=no %endif # Correct manual name (#2710). %__subst -p 's,/manual\.txt\\n,/manual.txt.bz2\\n,g' Muttrc.head.in %add_optflags -D_GNU_SOURCE libtoolize --copy --force aclocal -I m4 autoheader make -C m4 -f Makefile.am.in automake autoconf %configure \ --with-sharedir=%_sysconfdir \ --with-docdir=%docdir \ --enable-pop \ --enable-imap \ --enable-nntp \ --disable-warnings \ --with-ncurses \ --disable-domain \ --enable-nfs-fix \ --with-charmaps \ --with-ssl \ --enable-compressed make clean make -C doc clean-real %make_build %install %makeinstall sharedir=$RPM_BUILD_ROOT%_sysconfdir docdir=$RPM_BUILD_ROOT%docdir # Icons. %__install -pD -m644 %SOURCE1 $RPM_BUILD_ROOT%_miconsdir/%name.xpm %__install -pD -m644 %SOURCE2 $RPM_BUILD_ROOT%_iconsdir/%name.xpm %__install -pD -m644 %SOURCE3 $RPM_BUILD_ROOT%_liconsdir/%name.xpm # Menu. %__install -pD -m644 %SOURCE4 $RPM_BUILD_ROOT%_menudir/%name # More docs. %__install -p -m644 %SOURCE5 %SOURCE6 %SOURCE7 *.nntp \ $RPM_BUILD_ROOT%docdir/ find $RPM_BUILD_ROOT%docdir/ -name \*.txt -size +8k -print0 | xargs -r0 %__bzip2 -9 -- # Fix configs. find $RPM_BUILD_ROOT%_sysconfdir -type f -print0 | xargs -r0 %__grep -FZl "$RPM_BUILD_ROOT" | xargs -r0 %__subst -p "s|$RPM_BUILD_ROOT||g" -- %find_lang %name %post %update_menus %postun %clean_menus %files -f %name.lang %if_with dotlock %attr(2711,root,mail) %_bindir/mutt_dotlock %endif %config(noreplace) %_sysconfdir/Muttrc %_bindir/flea %_bindir/mutt %_bindir/muttbug %_bindir/pgp* %_mandir/man?/* %_menudir/%name %_iconsdir/*.xpm %_iconsdir/*/*.xpm %docdir %changelog * Tue Feb 17 2004 Alexey Morozov 3:1.4.2.1i-alt2 - added headercache patch (http://dwyn.net/mutt/) * Fri Feb 13 2004 Dmitry V. Levin 3:1.4.2.1i-alt1 - Updated to 1.4.2.1i (cvs-20020213-bound patch included into release). * Mon Feb 09 2004 Dmitry V. Levin 3:1.4.1i-alt3 - Backported patch from CVS to fix Mutt crash on certain e-mails; this can occur when an UTF-8 locale is used on wide terminals. * Thu Aug 28 2003 Dmitry V. Levin 3:1.4.1i-alt2 - Corrected manual filename entry (#2710). * Sat Mar 22 2003 Dmitry V. Levin 3:1.4.1i-alt1 - Updated to 1.4.1i. - Optimized by size "rr.compressed" and "vvv.nntp" patches. - Enabled regeneration of manual.txt. - Enabled compression of large text documentation files. - Updated sample gpg.rc file. * Fri Jan 24 2003 Dmitry V. Levin 2:1.4i-alt3 - Improved the package description (Owl). - Temporary files handling fixes (Owl). - Additional temporary files handling fixes for rr/vvv patches. * Thu Oct 31 2002 Dmitry V. Levin 2:1.4i-alt2 - Fixed -I/usr/include compilation warnings. - Explicitly use autoconf-2.13 and automake-1.4 for build. - Use subst instead of perl for build. * Thu May 30 2002 Dmitry V. Levin 2:1.4i-alt1 - 1.4i. * Tue May 07 2002 Dmitry V. Levin 2:1.3.99i-alt1 - 1.3.99i. - Don't use dotlocking for mailboxes, fcntl(2) should be enough. * Tue Apr 16 2002 Dmitry V. Levin 2:1.3.28i-alt2 - Fixed flea dependencies. - Optimized and updated buildrequires. * Fri Mar 15 2002 Dmitry V. Levin 2:1.3.28i-alt1 - 1.3.28i. - Added mutt-FAQ.ru.html (mike). * Mon Jan 28 2002 Dmitry V. Levin 2:1.3.27i-alt1 - 1.3.27i. - Set default send_charset to "us-ascii:iso-8859-1:koi8-r:koi8-u:windows-1251:utf-8" (#405). * Mon Jan 21 2002 Dmitry V. Levin 2:1.3.26i-alt1 - 1.3.26i. * Fri Jan 04 2002 Dmitry V. Levin 2:1.3.25i-alt1 - 1.3.25i (security). * Mon Dec 10 2001 Dmitry V. Levin 1:1.3.24i-alt1 - 1.3.24i. * Mon Nov 12 2001 Dmitry V. Levin 1:1.3.23.2i-alt1 - 1.3.23.2i. * Thu Nov 01 2001 Dmitry V. Levin 1:1.3.23.1i-alt1 - 1.3.23.1i. * Thu Sep 27 2001 Dmitry V. Levin 1.3.22.1i-alt2 - Added more default keybindings for F1 key. - Added default hooks for compressed folders. - Added mutt-gnupg-howto.txt * Tue Sep 18 2001 Dmitry V. Levin 1.3.22.1i-alt1 - 1.3.22.1i - Added patches from http://mutt.kiev.ua/download/. * Mon Jul 30 2001 Alexander Bokovoy 1.2.5i-ipl16mdk - NNTP support fixed, NNTPPost added. - Corrected mutt_dotlock permissions (ldv). - Corrected requires (ldv). * Wed Jul 25 2001 Alexander Bokovoy 1.2.5i-ipl15mdk - NNTP support added. See mutt-nntp.html for details and configuration * Fri Jun 29 2001 AEN 1.2.5i-ipl14mdk - ru.po fixed * Wed May 23 2001 Dmitry V. Levin 1.2.5i-ipl14mdk - Fixed autodependencies. * Tue May 22 2001 Dmitry V. Levin 1.2.5i-ipl12mdk - Modified 8bitpgp patch to fix build with new cpp (Mikhail Zabaluev ). * Fri Mar 23 2001 Dmitry V. Levin 1.2.5i-ipl11mdk - Added altyesorno patch (based on patch from Alexey Voinov ). * Tue Mar 20 2001 Dmitry V. Levin 1.2.5i-ipl10mdk - Merged RH patches * Thu Feb 22 2001 Dmitry V. Levin 1.2.5i-ipl9mdk - Added special recognition for "iso-8859-1" charmap. * Wed Jan 17 2001 Dmitry V. Levin 1.2.5i-ipl8mdk - Cleanup pgp patch. - Added special recognition for "ansi-x3-4-1968" charmap. * Fri Jan 05 2001 Dmitry V. Levin 1.2.5i-ipl7mdk - Added default charmap recognition. * Sat Dec 09 2000 Dmitry V. Levin 1.2.5i-ipl6mdk - Enabled ssl support. - Disabled forced 7bit pgp signed data convertion. - Fixed out $RPM_BUILD_ROOT from config file. * Tue Oct 12 2000 Dmitry V. Levin 1.2.5i-ipl5mdk - Addeded faq.html - Automatically added BuildRequires. * Wed Oct 04 2000 Daouda Lo 1.2.5i-5mdk - provide icons for menu * Mon Sep 04 2000 Dmitry V. Levin 1.2.5i-ipl4mdk - RE adaptions * Mon Aug 07 2000 Frederic Lepied 1.2.5-3mdk - automatically added BuildRequires * Wed Aug 2 2000 Vincent Danen 1.2.5i-2mdk - some of us like docs and samples so put them back in - fix docdir - more macros * Sat Jul 29 2000 Geoffrey Lee 1.2.5i-1mdk - new version - macrosifications - build for the BM * Fri Jul 07 2000 DindinX 1.2.4i-2mdk - merge Geoffrey Lee's spec changes - remove /etc/mimes.types from %files which caused a conflit w/ mailcap * Fri Jul 07 2000 Thierry Vignaud 1.2.4i-1mdk - new release (This version fixes a couple of problems present in 1.2.2, and one problem leading to crashes whose fix was missing from 1.2.3.) * Mon Jun 26 2000 DindinX 1.2.2i-3mdk - put the Serial: tag back * Fri Jun 23 2000 DindinX 1.2.2i-2mdk - fix the build as user the right way :) * Thu Jun 22 2000 Vincent Danen 1.2.2i-1mdk - 1.2.2i - removed %defattr which was causing readonly inboxes - build with ncurses instead of slang to get colors working properly - removed SSL support (won't compile due to keymaps bug) - fixed build * Tue Jun 20 2000 Vincent Danen 1.2i-2mdk - enable charmaps in configure - removed --enable-compressed (no patch) * Mon Jun 19 2000 Vincent Danen 1.2i-1mdk - 1.2i - enable SSL and NFS fixes in configure * Wed Apr 27 2000 DindinX 1.0.1i-7mdk - Recompile fix. - fix the color scheme. * Wed Apr 5 2000 Chmouel Boudjnah 1.0.1i-6mdk - By default active colors. - Believe me or not, fix menu and %post. - Use find_lang macros for locales. * Tue Apr 4 2000 Chmouel Boudjnah 1.0.1i-5mdk - Fix another chmousucks in menu (yes me too i can believe it). * Mon Apr 3 2000 Chmouel Boudjnah 1.0.1i-4mdk - Fix chmousucks in menu. - Add icons in menu. * Fri Mar 31 2000 Chmouel Boudjnah 1.0.1i-3mdk - Fix menu entry (don't only cp the meny entry from your debian box dindin ;)). * Fri Mar 24 2000 DindinX 1.0.1i-2mdk - Specs and group fixes - Added menu support * Sun Feb 06 2000 Andre Steden - 1.0.1 - add compressed folders patch - add colour patch * Sat Nov 06 1999 John Buswell - Build Release * Thu Oct 28 1999 Chmouel Boudjnah - 1.0. * Wed Oct 6 1999 Chmouel Boudjnah - 1.0pre3. * Mon Aug 09 1999 Daouda LO -0.95.7 -added manual.sgml in documents. * Sun May 09 1999 Chmouel Boudjnah - Fix bug of locales. * Wed Apr 28 1999 Chmouel Boudjnah - Mandrake adaptations. - update to 0.99.5. * Mon Mar 8 1999 Bill Nottingham - update to 0.95.4 - fixes a /tmp race * Wed Feb 24 1999 Bill Nottingham - the RETURN OF WMCONFIG! Aiyeee! * Fri Feb 12 1999 Bill Nottingham - 0.95.3 - fixes mailcap handling * Mon Jan 4 1999 Bill Nottingham - 0.95.1 * Sat Dec 12 1998 Bill Nottingham - 0.95 * Fri Jul 31 1998 Bill Nottingham - backport some 0.94.2 security fixes - fix un-setgid - update to 0.93.2 * Tue Jul 28 1998 Jeff Johnson - security fix - update to 0.93.1. - turn off setgid mail. * Thu May 07 1998 Prospector System - translations modified for de, fr, tr * Tue Apr 21 1998 Cristian Gafton - updated to 0.91.1 * Fri Apr 10 1998 Cristian Gafton - updated to mutt-0.89.1 * Thu Oct 16 1997 Otto Hammersmith - Updated to mutt 0.85. - added wmconfig entries. - removed mime.types * Mon Sep 1 1997 Donnie Barnes - Rebuilt to insure all sources were fresh and patches were clean. * Wed Aug 6 1997 Manoj Kasichainula - Initial version for 0.81(e) --yiup30KVCQiHUZFC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mutt-1.4-headercache.patch" diff -urN -X exclude-diff mutt-1.4/globals.h mutt-1.4-headercache/globals.h --- mutt-1.4/globals.h 2002-01-03 12:57:19.000000000 -0800 +++ mutt-1.4-headercache/globals.h 2002-12-14 11:20:58.000000000 -0800 @@ -56,6 +56,7 @@ WHERE char *ImapHomeNamespace INITVAL (NULL); WHERE char *ImapPass INITVAL (NULL); WHERE char *ImapUser INITVAL (NULL); +WHERE char *ImapHeadercache INITVAL (NULL); #endif WHERE char *Inbox; WHERE char *Ispell; diff -urN -X exclude-diff mutt-1.4/imap/imap.c mutt-1.4-headercache/imap/imap.c --- mutt-1.4/imap/imap.c 2002-04-07 14:19:14.000000000 -0700 +++ mutt-1.4-headercache/imap/imap.c 2002-12-14 18:44:07.000000000 -0800 @@ -29,6 +29,7 @@ #include "browser.h" #include "message.h" #include "imap_private.h" +#include "imap_headercache.h" #ifdef USE_SSL # include "mutt_ssl.h" #endif @@ -530,6 +531,13 @@ /* Clean up path and replace the one in the ctx */ imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); + + if (idata->hcache) + { + imap_headercache_close(idata->hcache); + idata->hcache = NULL; + } + FREE(&(idata->mailbox)); idata->mailbox = safe_strdup (buf); imap_qualify_path (buf, sizeof (buf), &mx, idata->mailbox); @@ -540,6 +548,7 @@ idata->ctx = ctx; /* clear mailbox status */ + idata->uidvalidity = 0; idata->status = 0; memset (idata->rights, 0, (RIGHTSMAX+7)/8); idata->newMailCount = 0; @@ -585,6 +594,15 @@ if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) goto fail; } + /* save UIDVALIDITY for the header cache */ + else if (ascii_strncasecmp("OK [UIDVALIDITY", pc, 14) == 0) + { + dprint(2, (debugfile, "Getting mailbox UIDVALIDITY\n")); + pc += 3; + pc = imap_next_word(pc); + + sscanf(pc, "%u", &(idata->uidvalidity)); + } else { pc = imap_next_word (pc); @@ -662,6 +680,9 @@ ctx->hdrs = safe_malloc (count * sizeof (HEADER *)); ctx->v2r = safe_malloc (count * sizeof (int)); ctx->msgcount = 0; + + idata->hcache = imap_headercache_open(idata); + if (count && (imap_read_headers (idata, 0, count-1) < 0)) { mutt_error _("Error opening mailbox"); @@ -671,6 +692,7 @@ dprint (2, (debugfile, "imap_open_mailbox: msgcount is %d\n", ctx->msgcount)); FREE (&mx.mbox); + return 0; fail: @@ -891,6 +913,7 @@ int n; int err_continue = M_NO; /* continue on error? */ int rc; + IMAP_HEADER h; idata = (IMAP_DATA*) ctx->data; @@ -930,8 +953,20 @@ /* mark these messages as unchanged so second pass ignores them. Done * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */ for (n = 0; n < ctx->msgcount; n++) - if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed) - ctx->hdrs[n]->active = 0; + { + if (ctx->hdrs[n]->deleted) + { + if (idata->hcache) + { + h.data = HEADER_DATA(ctx->hdrs[n]); + imap_headercache_delete(idata->hcache, &h); + } + + if (ctx->hdrs[n]->changed) + ctx->hdrs[n]->active = 0; + } + } + if (imap_exec (idata, cmd.data, 0) != 0) { mutt_error (_("Expunge failed")); @@ -949,6 +984,23 @@ { ctx->hdrs[n]->changed = 0; + if (idata->hcache) + { + h.data = HEADER_DATA(ctx->hdrs[n]); + + h.read = ctx->hdrs[n]->read; + h.old = ctx->hdrs[n]->old; + h.deleted = ctx->hdrs[n]->deleted; + h.flagged = ctx->hdrs[n]->flagged; + h.replied = ctx->hdrs[n]->replied; + h.changed = ctx->hdrs[n]->changed; + h.sid = ctx->hdrs[n]->index + 1; + h.received = ctx->hdrs[n]->received; + h.content_length = ctx->hdrs[n]->content->length; + + imap_headercache_update(idata->hcache, &h); + } + mutt_message (_("Saving message status flags... [%d/%d]"), n+1, ctx->msgcount); @@ -1076,6 +1128,11 @@ idata->reopen &= IMAP_REOPEN_ALLOW; idata->state = IMAP_AUTHENTICATED; + if (idata->hcache) + { + imap_headercache_close(idata->hcache); + idata->hcache = NULL; + } FREE (&(idata->mailbox)); mutt_free_list (&idata->flags); } diff -urN -X exclude-diff mutt-1.4/imap/imap_headercache.c mutt-1.4-headercache/imap/imap_headercache.c --- mutt-1.4/imap/imap_headercache.c 1969-12-31 16:00:00.000000000 -0800 +++ mutt-1.4-headercache/imap/imap_headercache.c 2002-12-14 19:13:47.000000000 -0800 @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2002 Tudor Bosman + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#include "mutt.h" +#include "imap.h" +#include "imap_private.h" +#include "imap_headercache.h" +#include "mx.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* Delete all messages from headercache */ +static int imap_headercache_purge(IMAP_HEADERCACHE *hc) +{ + int rc = -1; + DIR *dir; + struct dirent *ent; + + dir = opendir(hc->name); + if (!dir) + { + mutt_error(_("IMAP headercache: can't purge directory %s: %s"), hc->name, + strerror(errno)); + mutt_sleep(2); + return -1; + } + + while ((ent = readdir(dir)) != NULL) + { + if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + continue; + + sprintf(hc->tmpname, "%s/%s", hc->name, ent->d_name); + if (unlink(hc->tmpname) == -1) + { + mutt_error(_("IMAP headercache: can't unlink file %s: %s"), hc->tmpname, + strerror(errno)); + mutt_sleep(2); + goto bail; + } + } + + rc = 0; + +bail: + closedir(dir); + + return rc; +} + +/* Open headercache */ +IMAP_HEADERCACHE *imap_headercache_open(IMAP_DATA *idata) +{ + IMAP_HEADERCACHE *hc; + char hcdir[_POSIX_PATH_MAX + 1]; + FILE *f; + size_t len; + char *p; + + if (!ImapHeadercache || ImapHeadercache[0] == '\0') + return NULL; + + strfcpy(hcdir, ImapHeadercache, _POSIX_PATH_MAX); + mutt_expand_path(hcdir, _POSIX_PATH_MAX); + + hc = safe_malloc(sizeof(IMAP_HEADERCACHE)); + + len = strlen(hcdir) + strlen(idata->conn->account.host) + + strlen(idata->mailbox) + 5; + + hc->name = safe_malloc(len); + hc->tmpname = safe_malloc(len + NAME_MAX + 2); + + sprintf(hc->name, "%s/%s", hcdir, idata->conn->account.host); + + if (mkdir(hcdir, 0777) == -1 && errno != EEXIST) + { + mutt_error(_("Can't create IMAP headercache root directory %s: %s"), + hcdir, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) + { + mutt_error(_("Can't create IMAP headercache server directory %s: %s"), + hc->name, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + p = idata->mailbox; + while ((p = strchr(p, '/')) != NULL) + { + *p = '\0'; + sprintf(hc->name, "%s/%s/%s", hcdir, + idata->conn->account.host, idata->mailbox); + + if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) + { + mutt_error(_("Can't create IMAP headercache mailbox directory %s: %s"), + hc->name, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + *p = '/'; + p++; + } + + sprintf(hc->name, "%s/%s/%s", hcdir, + idata->conn->account.host, idata->mailbox); + + if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) + { + mutt_error(_("Can't create IMAP headercache mailbox directory %s: %s"), + hc->name, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + sprintf(hc->tmpname, "%s/uidvalidity", hc->name); + f = fopen(hc->tmpname, "r"); + + if (f) + { + fscanf(f, "%u", &hc->uidvalidity); + if (idata->uidvalidity != hc->uidvalidity) + { + fclose(f); + f = NULL; + } + } + + if (!f) + { + if (imap_headercache_purge(hc) == -1) + goto bail; + + sprintf(hc->tmpname, "%s/uidvalidity", hc->name); + f = fopen(hc->tmpname, "w"); + if (!f) + { + mutt_error(_("Can't create IMAP headercache uidvalidity file %s: %s"), + hc->tmpname, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + hc->uidvalidity = idata->uidvalidity; + + fprintf(f, "%u\n", hc->uidvalidity); + fclose(f); + } + + return hc; + +bail: + safe_free((void **)&hc->tmpname); + safe_free((void **)&hc->name); + safe_free((void **)&hc); + + return NULL; +} + +/* Close headercache */ +void imap_headercache_close(IMAP_HEADERCACHE *hc) +{ + safe_free((void **)&hc->tmpname); + safe_free((void **)&hc->name); + safe_free((void **)&hc); +} + +static void imap_headercache_writehdr(FILE *f, IMAP_HEADER *h) +{ + /* Write the stuff in the header. This must have a fixed length, as it is + * overwritten in case of imap_headercache_update + */ + fprintf(f, "%1x %1x %1x %1x %1x %1x %8x %16lx %16lx %8x\n", + h->read, h->old, h->deleted, h->flagged, h->replied, h->changed, + h->sid, h->received, h->content_length, HEADER_DATA(h)->uid); +} + +/* Add message to headercache */ +int imap_headercache_add(IMAP_HEADERCACHE *hc, IMAP_HEADER *h, FILE *from, + size_t hdrsz) +{ + FILE *f; +#define BUFSIZE 4096 + char buf[BUFSIZE]; + size_t sz; + int rc = -1; + + sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); + + f = fopen(hc->tmpname, "w"); + if (!f) + { + mutt_error(_("Can't create IMAP headercache message file %s: %s"), + hc->tmpname, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + imap_headercache_writehdr(f, h); + + while ((sz = fread(buf, 1, (hdrsz < BUFSIZE ? hdrsz : BUFSIZE), from)) != 0) + { + hdrsz -= sz; + fwrite(buf, 1, sz, f); + } + + fclose(f); + + rc = 0; + +bail: + return rc; +} + +/* Update flags in headercache message */ +int imap_headercache_update(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) +{ + FILE *f; + int rc = -1; + + sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); + + f = fopen(hc->tmpname, "r+"); + if (!f) + goto bail; + + imap_headercache_writehdr(f, h); + + fclose(f); + + rc = 0; + +bail: + return rc; +} + +/* Delete message from headercache */ +int imap_headercache_delete(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) +{ + int rc = -1; + + sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); + + if (unlink(hc->tmpname) == -1) + { + mutt_error(_("Can't delete IMAP headercache message %s: %s"), + hc->tmpname, strerror(errno)); + mutt_sleep(2); + goto bail; + } + + rc = 0; + +bail: + return rc; +} + +/* Find message in headercache */ +FILE *imap_headercache_find(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) +{ + FILE *f = NULL; + unsigned int flag_read, flag_old, flag_deleted, flag_flagged, flag_replied; + unsigned int flag_changed; + unsigned int uid; + unsigned long received; + unsigned long content_length; + + sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); + + f = fopen(hc->tmpname, "r"); + if (!f) + goto bail; + + fscanf(f, "%x %x %x %x %x %x %x %lx %lx %x\n", + &flag_read, &flag_old, &flag_deleted, &flag_flagged, &flag_replied, + &flag_changed, &h->sid, &received, &content_length, &uid); + + if (uid != HEADER_DATA(h)->uid) + { + fclose(f); + f = NULL; + goto bail; + } + + h->received = received; + h->read = flag_read; + h->old = flag_old; + h->deleted = flag_deleted; + h->flagged = flag_flagged; + h->replied = flag_replied; + h->changed = flag_changed; + h->content_length = (long)content_length; + +bail: + return f; +} + +/* Close file returned by imap_headercache_find */ +void imap_headercache_done(IMAP_HEADERCACHE *hc, FILE *f) +{ + fclose(f); +} + diff -urN -X exclude-diff mutt-1.4/imap/imap_headercache.h mutt-1.4-headercache/imap/imap_headercache.h --- mutt-1.4/imap/imap_headercache.h 1969-12-31 16:00:00.000000000 -0800 +++ mutt-1.4-headercache/imap/imap_headercache.h 2002-12-14 19:13:40.000000000 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002 Tudor Bosman + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +#ifndef _IMAP_HEADERCACHE_H +#define _IMAP_HEADERCACHE_H +#include "imap_private.h" +#include "message.h" + +typedef struct IMAP_HEADERCACHE +{ + char *name; + char *tmpname; + unsigned int uidvalidity; + int exists; +} IMAP_HEADERCACHE; + +struct IMAP_DATA; + +IMAP_HEADERCACHE *imap_headercache_open(struct IMAP_DATA *idata); + +void imap_headercache_close(IMAP_HEADERCACHE *hc); + +int imap_headercache_add(IMAP_HEADERCACHE *hc, IMAP_HEADER *h, FILE *from, + size_t hdrsz); +int imap_headercache_update(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); +int imap_headercache_delete(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); + +FILE *imap_headercache_find(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); +void imap_headercache_done(IMAP_HEADERCACHE *hc, FILE *f); + +#endif + diff -urN -X exclude-diff mutt-1.4/imap/imap_private.h mutt-1.4-headercache/imap/imap_private.h --- mutt-1.4/imap/imap_private.h 2001-07-03 02:50:05.000000000 -0700 +++ mutt-1.4-headercache/imap/imap_private.h 2002-12-14 16:23:05.000000000 -0800 @@ -21,6 +21,7 @@ #define _IMAP_PRIVATE_H 1 #include "imap.h" +#include "imap_headercache.h" #include "mutt_socket.h" /* -- symbols -- */ @@ -148,7 +149,7 @@ int state; } IMAP_COMMAND; -typedef struct +typedef struct IMAP_DATA { /* This data is specific to a CONNECTION to an IMAP server */ CONNECTION *conn; @@ -174,6 +175,7 @@ char *mailbox; unsigned short check_status; unsigned char reopen; + unsigned int uidvalidity; unsigned char rights[(RIGHTSMAX + 7)/8]; unsigned int newMailCount; IMAP_CACHE cache[IMAP_CACHE_LEN]; @@ -181,6 +183,7 @@ /* all folder flags - system flags AND keywords */ LIST *flags; + IMAP_HEADERCACHE *hcache; } IMAP_DATA; /* I wish that were called IMAP_CONTEXT :( */ diff -urN -X exclude-diff mutt-1.4/imap/Makefile.am mutt-1.4-headercache/imap/Makefile.am --- mutt-1.4/imap/Makefile.am 2001-05-28 12:14:31.000000000 -0700 +++ mutt-1.4-headercache/imap/Makefile.am 2002-12-14 19:27:05.000000000 -0800 @@ -22,4 +22,5 @@ noinst_HEADERS = auth.h imap_private.h message.h libimap_a_SOURCES = auth.c auth_login.c browse.c command.c imap.c imap.h \ - message.c utf7.c util.c $(AUTHENTICATORS) $(GSSSOURCES) + imap_headercache.c imap_headercache.h message.c utf7.c util.c \ + $(AUTHENTICATORS) $(GSSSOURCES) diff -urN -X exclude-diff mutt-1.4/imap/message.c mutt-1.4-headercache/imap/message.c --- mutt-1.4/imap/message.c 2002-04-07 14:19:14.000000000 -0700 +++ mutt-1.4-headercache/imap/message.c 2002-12-14 15:57:44.000000000 -0800 @@ -25,6 +25,7 @@ #include "mutt.h" #include "mutt_curses.h" #include "imap_private.h" +#include "imap_headercache.h" #include "message.h" #include "mx.h" @@ -54,9 +55,14 @@ int msgno; IMAP_HEADER h; int rc, mfhrc, oldmsgcount; + IMAP_HEADERCACHE *hc = NULL; + int msgbegin_hc; int fetchlast = 0; + const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; + msgno = msgbegin; + ctx = idata->ctx; if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) @@ -87,36 +93,150 @@ } unlink (tempfile); + oldmsgcount = ctx->msgcount; + + msgbegin_hc = msgbegin; + + hc = idata->hcache; + +restart: /* make sure context has room to hold the mailbox */ while ((msgend) >= idata->ctx->hdrmax) mx_alloc_memory (idata->ctx); - oldmsgcount = ctx->msgcount; idata->reopen &= ~IMAP_NEWMAIL_PENDING; idata->newMailCount = 0; + if (hc) + { + snprintf(buf, sizeof(buf), "FETCH %d:%d (UID)", msgbegin_hc + 1, + msgend + 1); + imap_cmd_start(idata, buf); + + for (msgno = msgbegin_hc; msgno <= msgend; msgno++) + { + if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) + mutt_message (_("Fetching message UIDs... [%d/%d]"), msgno + 1, + msgend + 1); + + /* XXX */ + ctx->hdrs[msgno] = NULL; + + /* XXX leaking h.data on successful exit */ + memset (&h, 0, sizeof (h)); + h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); + + do + { + FILE *cache_fp; + + mfhrc = 0; + + rc = imap_cmd_step (idata); + if (rc != IMAP_CMD_CONTINUE) + break; + + if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, NULL)) == -1) + continue; + else if (mfhrc < 0) + break; + + cache_fp = imap_headercache_find(hc, &h); + if (cache_fp) + { + /* update context with message header */ + ctx->hdrs[msgno] = mutt_new_header (); + + ctx->hdrs[msgno]->index = h.sid - 1; + + /* messages which have not been expunged are ACTIVE (borrowed from mh + * folders) */ + ctx->hdrs[msgno]->active = 1; + ctx->hdrs[msgno]->read = h.read; + ctx->hdrs[msgno]->old = h.old; + ctx->hdrs[msgno]->deleted = h.deleted; + ctx->hdrs[msgno]->flagged = h.flagged; + ctx->hdrs[msgno]->replied = h.replied; + ctx->hdrs[msgno]->changed = h.changed; + ctx->hdrs[msgno]->received = h.received; + ctx->hdrs[msgno]->data = (void *) (h.data); + + /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends + * on h.received being set */ + ctx->hdrs[msgno]->env = mutt_read_rfc822_header (cache_fp, ctx->hdrs[msgno], + 0, 0); + /* content built as a side-effect of mutt_read_rfc822_header */ + ctx->hdrs[msgno]->content->length = h.content_length; + + imap_headercache_done(hc, cache_fp); + } + } + while (mfhrc == -1); + + /* in case we get new mail while fetching the headers */ + if (idata->reopen & IMAP_NEWMAIL_PENDING) + { + msgbegin_hc = msgno + 1; + msgend = idata->newMailCount - 1; + goto restart; + } + /* XXX freshen... etc */ + } + } + + /* Remember where we left if we get new mail while fetching actual headers */ + msgbegin_hc = msgno; + + /* Now, either one of the following is true: + * 1. We don't have a headercache (hc == 0) + * 2. All messages found in the cache have ctx->hdrs[msgno] != NULL, and + * filled up. + */ + + /* + * Make one request for everything. This makes fetching headers an + * order of magnitude faster if you have a large mailbox. + * + * If we get more messages while doing this, we make another + * request for all the new messages. + */ + if (!hc) + { + snprintf (buf, sizeof (buf), + "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgbegin + 1, + msgend + 1, hdrreq); + + imap_cmd_start (idata, buf); + } + for (msgno = msgbegin; msgno <= msgend ; msgno++) { if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, msgend + 1); - if (msgno + 1 > fetchlast) + /* If the message is in the cache, skip it */ + if (hc) { - /* - * Make one request for everything. This makes fetching headers an - * order of magnitude faster if you have a large mailbox. - * - * If we get more messages while doing this, we make another - * request for all the new messages. - */ - snprintf (buf, sizeof (buf), - "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, - msgend + 1, hdrreq); - - imap_cmd_start (idata, buf); + if (ctx->hdrs[msgno]) + { + ctx->msgcount++; + continue; + } + else if (msgno >= fetchlast) + { + /* Find the longest "run" of messages not in the cache and fetch it in + * one go + */ + for (fetchlast = msgno + 1; + fetchlast <= msgend && !ctx->hdrs[fetchlast]; fetchlast++); + + snprintf (buf, sizeof (buf), + "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, + fetchlast, hdrreq); - fetchlast = msgend + 1; + imap_cmd_start (idata, buf); + } } /* freshen fp, h */ @@ -130,6 +250,8 @@ */ do { + size_t hdrsz; + mfhrc = 0; rc = imap_cmd_step (idata); @@ -144,12 +266,16 @@ /* make sure we don't get remnants from older larger message headers */ fputs ("\n\n", fp); + hdrsz = (size_t)ftell(fp); + /* update context with message header */ ctx->hdrs[msgno] = mutt_new_header (); ctx->hdrs[msgno]->index = h.sid - 1; +#if 0 if (h.sid != ctx->msgcount + 1) dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); +#endif /* messages which have not been expunged are ACTIVE (borrowed from mh * folders) */ ctx->hdrs[msgno]->active = 1; @@ -163,6 +289,13 @@ ctx->hdrs[msgno]->data = (void *) (h.data); rewind (fp); + + if (hc) + { + imap_headercache_add(hc, &h, fp, hdrsz); + rewind(fp); + } + /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends * on h.received being set */ ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], @@ -172,8 +305,7 @@ ctx->msgcount++; } - while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || - ((msgno + 1) >= fetchlast))); + while (mfhrc == -1); if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) { @@ -186,11 +318,9 @@ /* in case we get new mail while fetching the headers */ if (idata->reopen & IMAP_NEWMAIL_PENDING) { + msgbegin = msgno + 1; msgend = idata->newMailCount - 1; - while ((msgend) >= ctx->hdrmax) - mx_alloc_memory (ctx); - idata->reopen &= ~IMAP_NEWMAIL_PENDING; - idata->newMailCount = 0; + goto restart; } } @@ -731,6 +861,7 @@ IMAP_DATA* idata; long bytes; int rc = -1; /* default now is that string isn't FETCH response*/ + int fetch_rc; idata = (IMAP_DATA*) ctx->data; @@ -753,9 +884,15 @@ /* FIXME: current implementation - call msg_parse_fetch - if it returns -2, * read header lines and call it again. Silly. */ - if (msg_parse_fetch (h, buf) != -2) + fetch_rc = msg_parse_fetch(h, buf); + if (fetch_rc == 0) + return 0; + else if (fetch_rc != -2) return rc; - + + if (!fp) + return -2; + if (imap_get_literal_count (buf, &bytes) < 0) return rc; imap_read_literal (fp, idata, bytes); diff -urN -X exclude-diff mutt-1.4/imap/util.c mutt-1.4-headercache/imap/util.c --- mutt-1.4/imap/util.c 2002-04-29 05:08:03.000000000 -0700 +++ mutt-1.4-headercache/imap/util.c 2002-12-14 16:25:14.000000000 -0800 @@ -255,6 +255,7 @@ if (!idata) return NULL; + idata->hcache = NULL; idata->conn = NULL; idata->capstr = NULL; idata->state = IMAP_DISCONNECTED; diff -urN -X exclude-diff mutt-1.4/init.h mutt-1.4-headercache/init.h --- mutt-1.4/init.h 2002-04-25 06:26:37.000000000 -0700 +++ mutt-1.4-headercache/init.h 2002-12-14 11:18:41.000000000 -0800 @@ -818,6 +818,11 @@ ** .pp ** This variable defaults to your user name on the local machine. */ + { "imap_headercache", DT_STR, R_NONE, UL &ImapHeadercache, UL 0 }, + /* + ** .pp + ** The location of the IMAP headercache directory. + */ #endif { "implicit_autoview", DT_BOOL,R_NONE, OPTIMPLICITAUTOVIEW, 0}, /* --yiup30KVCQiHUZFC-- --fDERRRNgB4on1jOB Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.2 (GNU/Linux) iD8DBQFAMz/RX5DZdJn19V0RAoVxAJ9usKS7vL3AYZFvJnjFcvM5X/eF6wCgi412 CJrjJscYp/91yB9pXSu8c3E= =zlcx -----END PGP SIGNATURE----- --fDERRRNgB4on1jOB--