⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pattern.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-2000,2006 Michael R. Elkins <me@mutt.org>, and others *  *     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mapping.h"#include "keymap.h"#include "mailbox.h"#include "copy.h"#include <string.h>#include <stdlib.h>#include <ctype.h>#include <sys/stat.h>#include <unistd.h>#include <stdarg.h>#include "mutt_crypt.h"#ifdef USE_IMAP#include "mx.h"#include "imap/imap.h"#endifstatic int eat_regexp (pattern_t *pat, BUFFER *, BUFFER *);static int eat_date (pattern_t *pat, BUFFER *, BUFFER *);static int eat_range (pattern_t *pat, BUFFER *, BUFFER *);static int patmatch (const pattern_t *pat, const char *buf);struct pattern_flags{  int tag;	/* character used to represent this op */  int op;	/* operation to perform */  int class;  int (*eat_arg) (pattern_t *, BUFFER *, BUFFER *);}Flags[] ={  { 'A', M_ALL,			0,		NULL },  { 'b', M_BODY,		M_FULL_MSG,	eat_regexp },  { 'B', M_WHOLE_MSG,		M_FULL_MSG,	eat_regexp },  { 'c', M_CC,			0,		eat_regexp },  { 'C', M_RECIPIENT,		0,		eat_regexp },  { 'd', M_DATE,		0,		eat_date },  { 'D', M_DELETED,		0,		NULL },  { 'e', M_SENDER,		0,		eat_regexp },  { 'E', M_EXPIRED,		0,		NULL },  { 'f', M_FROM,		0,		eat_regexp },  { 'F', M_FLAG,		0,		NULL },  { 'g', M_CRYPT_SIGN,		0,		NULL },  { 'G', M_CRYPT_ENCRYPT,	0,		NULL },  { 'h', M_HEADER,		M_FULL_MSG,	eat_regexp },  { 'H', M_HORMEL,		0,		eat_regexp },  { 'i', M_ID,			0,		eat_regexp },  { 'k', M_PGP_KEY,		0,		NULL },  { 'l', M_LIST,		0,		NULL },  { 'L', M_ADDRESS,		0,		eat_regexp },  { 'm', M_MESSAGE,		0,		eat_range },  { 'n', M_SCORE,		0,		eat_range },  { 'N', M_NEW,			0,		NULL },  { 'O', M_OLD,			0,		NULL },  { 'p', M_PERSONAL_RECIP,	0,		NULL },  { 'P', M_PERSONAL_FROM,	0,		NULL },  { 'Q', M_REPLIED,		0,		NULL },  { 'r', M_DATE_RECEIVED,	0,		eat_date },  { 'R', M_READ,		0,		NULL },  { 's', M_SUBJECT,		0,		eat_regexp },  { 'S', M_SUPERSEDED,		0,		NULL },  { 't', M_TO,			0,		eat_regexp },  { 'T', M_TAG,			0,		NULL },  { 'u', M_SUBSCRIBED_LIST,	0,		NULL },  { 'U', M_UNREAD,		0,		NULL },  { 'v', M_COLLAPSED,		0,		NULL },  { 'V', M_CRYPT_VERIFIED,	0,		NULL },  { 'x', M_REFERENCE,		0,		eat_regexp },  { 'X', M_MIMEATTACH,		0,		eat_range },  { 'y', M_XLABEL,		0,		eat_regexp },  { 'z', M_SIZE,		0,		eat_range },  { '=', M_DUPLICATED,		0,		NULL },  { '$', M_UNREFERENCED,	0,		NULL },  { 0 }};static pattern_t *SearchPattern = NULL; /* current search pattern */static char LastSearch[STRING] = { 0 };	/* last pattern searched for */static char LastSearchExpn[LONG_STRING] = { 0 }; /* expanded version of						    LastSearch */#define M_MAXRANGE -1/* constants for parse_date_range() */#define M_PDR_NONE	0x0000#define M_PDR_MINUS	0x0001#define M_PDR_PLUS	0x0002#define M_PDR_WINDOW	0x0004#define M_PDR_ABSOLUTE	0x0008#define M_PDR_DONE	0x0010#define M_PDR_ERROR	0x0100#define M_PDR_ERRORDONE	(M_PDR_ERROR | M_PDR_DONE)int mutt_getvaluebychar (char ch, struct mapping_t *table){  int i;  for (i = 0; table[i].name; i++)  {    if (ch == table[i].name[0])      return table[i].value;  }  return (-1);}/* if no uppercase letters are given, do a case-insensitive search */int mutt_which_case (const char *s){  while (*s)  {    if (isalpha ((unsigned char) *s) && isupper ((unsigned char) *s))      return 0; /* case-sensitive */    s++;  }  return REG_ICASE; /* case-insensitive */}static intmsg_search (CONTEXT *ctx, pattern_t* pat, int msgno){  char tempfile[_POSIX_PATH_MAX];  MESSAGE *msg = NULL;  STATE s;  struct stat st;  FILE *fp = NULL;  long lng = 0;  int match = 0;  HEADER *h = ctx->hdrs[msgno];  char *buf;  size_t blen;  if ((msg = mx_open_message (ctx, msgno)) != NULL)  {    if (option (OPTTHOROUGHSRC))    {      /* decode the header / body */      memset (&s, 0, sizeof (s));      s.fpin = msg->fp;      s.flags = M_CHARCONV;      mutt_mktemp (tempfile);      if ((s.fpout = safe_fopen (tempfile, "w+")) == NULL)      {	mutt_perror (tempfile);	return (0);      }      if (pat->op != M_BODY)	mutt_copy_header (msg->fp, h, s.fpout, CH_FROM | CH_DECODE, NULL);      if (pat->op != M_HEADER)      {	mutt_parse_mime_message (ctx, h);	if (WithCrypto && (h->security & ENCRYPT)            && !crypt_valid_passphrase(h->security))	{	  mx_close_message (&msg);	  if (fp)	  {	    fclose (fp);	    unlink (tempfile);	  }	  return (0);	}	fseeko (msg->fp, h->offset, 0);	mutt_body_handler (h->content, &s);      }      fp = s.fpout;      fflush (fp);      fseek (fp, 0, 0);      fstat (fileno (fp), &st);      lng = (long) st.st_size;    }    else    {      /* raw header / body */      fp = msg->fp;      if (pat->op != M_BODY)      {	fseeko (fp, h->offset, 0);	lng = h->content->offset - h->offset;      }      if (pat->op != M_HEADER)      {	if (pat->op == M_BODY)	  fseeko (fp, h->content->offset, 0);	lng += h->content->length;      }    }    blen = STRING;    buf = safe_malloc (blen);    /* search the file "fp" */    while (lng > 0)    {      if (pat->op == M_HEADER)      {	if (*(buf = mutt_read_rfc822_line (fp, buf, &blen)) == '\0')	  break;      }      else if (fgets (buf, blen - 1, fp) == NULL)	break; /* don't loop forever */      if (patmatch (pat, buf) == 0)      {	match = 1;	break;      }      lng -= mutt_strlen (buf);    }    FREE (&buf);        mx_close_message (&msg);    if (option (OPTTHOROUGHSRC))    {      fclose (fp);      unlink (tempfile);    }  }  return match;}int eat_regexp (pattern_t *pat, BUFFER *s, BUFFER *err){  BUFFER buf;  int r;  memset (&buf, 0, sizeof (buf));  if (mutt_extract_token (&buf, s, M_TOKEN_PATTERN | M_TOKEN_COMMENT) != 0 ||      !buf.data)  {    snprintf (err->data, err->dsize, _("Error in expression: %s"), s->dptr);    return (-1);  }  if (!*buf.data)  {    snprintf (err->data, err->dsize, _("Empty expression"));    return (-1);  }#if 0  /* If there are no RE metacharacters, use simple search anyway */  if (!pat->stringmatch && !strpbrk (buf.data, "|[{.*+?^$"))    pat->stringmatch = 1;#endif  if (pat->stringmatch)  {    pat->p.str = safe_strdup (buf.data);    FREE (&buf.data);  }  else if (pat->groupmatch)  {    pat->p.g = mutt_pattern_group (buf.data);    FREE (&buf.data);  }  else  {    pat->p.rx = safe_malloc (sizeof (regex_t));    r = REGCOMP (pat->p.rx, buf.data, REG_NEWLINE | REG_NOSUB | mutt_which_case (buf.data));    FREE (&buf.data);    if (r)    {      regerror (r, pat->p.rx, err->data, err->dsize);      regfree (pat->p.rx);      FREE (&pat->p.rx);      return (-1);    }  }  return 0;}int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err){  char *tmp;  int do_exclusive = 0;  int skip_quote = 0;    /*   * If simple_search is set to "~m %s", the range will have double quotes    * around it...   */  if (*s->dptr == '"')  {    s->dptr++;    skip_quote = 1;  }  if (*s->dptr == '<')    do_exclusive = 1;  if ((*s->dptr != '-') && (*s->dptr != '<'))  {    /* range minimum */    if (*s->dptr == '>')    {      pat->max = M_MAXRANGE;      pat->min = strtol (s->dptr + 1, &tmp, 0) + 1; /* exclusive range */    }    else      pat->min = strtol (s->dptr, &tmp, 0);    if (toupper ((unsigned char) *tmp) == 'K') /* is there a prefix? */    {      pat->min *= 1024;      tmp++;    }    else if (toupper ((unsigned char) *tmp) == 'M')    {      pat->min *= 1048576;      tmp++;    }    if (*s->dptr == '>')    {      s->dptr = tmp;      return 0;    }    if (*tmp != '-')    {      /* exact value */      pat->max = pat->min;      s->dptr = tmp;      return 0;    }    tmp++;  }  else  {    s->dptr++;    tmp = s->dptr;  }    if (isdigit ((unsigned char) *tmp))  {    /* range maximum */    pat->max = strtol (tmp, &tmp, 0);    if (toupper ((unsigned char) *tmp) == 'K')    {      pat->max *= 1024;      tmp++;    }    else if (toupper ((unsigned char) *tmp) == 'M')    {      pat->max *= 1048576;      tmp++;    }    if (do_exclusive)      (pat->max)--;  }  else    pat->max = M_MAXRANGE;  if (skip_quote && *tmp == '"')    tmp++;  SKIPWS (tmp);  s->dptr = tmp;  return 0;}static const char *getDate (const char *s, struct tm *t, BUFFER *err){  char *p;  time_t now = time (NULL);  struct tm *tm = localtime (&now);  t->tm_mday = strtol (s, &p, 10);  if (t->tm_mday < 1 || t->tm_mday > 31)  {    snprintf (err->data, err->dsize, _("Invalid day of month: %s"), s);    return NULL;  }  if (*p != '/')  {    /* fill in today's month and year */    t->tm_mon = tm->tm_mon;    t->tm_year = tm->tm_year;    return p;  }  p++;  t->tm_mon = strtol (p, &p, 10) - 1;  if (t->tm_mon < 0 || t->tm_mon > 11)  {    snprintf (err->data, err->dsize, _("Invalid month: %s"), p);    return NULL;  }  if (*p != '/')  {    t->tm_year = tm->tm_year;    return p;  }  p++;  t->tm_year = strtol (p, &p, 10);  if (t->tm_year < 70) /* year 2000+ */    t->tm_year += 100;  else if (t->tm_year > 1900)    t->tm_year -= 1900;  return p;}/* Ny	years   Nm	months   Nw	weeks   Nd	days */static const char *get_offset (struct tm *tm, const char *s, int sign){  char *ps;  int offset = strtol (s, &ps, 0);  if ((sign < 0 && offset > 0) || (sign > 0 && offset < 0))    offset = -offset;  switch (*ps)  {    case 'y':      tm->tm_year += offset;      break;    case 'm':      tm->tm_mon += offset;      break;    case 'w':      tm->tm_mday += 7 * offset;      break;    case 'd':      tm->tm_mday += offset;      break;    default:      return s;  }  mutt_normalize_time (tm);  return (ps + 1);}static void adjust_date_range (struct tm *min, struct tm *max){  if (min->tm_year > max->tm_year      || (min->tm_year == max->tm_year && min->tm_mon > max->tm_mon)      || (min->tm_year == max->tm_year && min->tm_mon == max->tm_mon	&& min->tm_mday > max->tm_mday))  {    int tmp;        tmp = min->tm_year;    min->tm_year = max->tm_year;    max->tm_year = tmp;          tmp = min->tm_mon;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -