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

📄 browser.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org> *  *     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 "mutt_curses.h"#include "mutt_menu.h"#include "attach.h"#include "buffy.h"#include "mapping.h"#include "sort.h"#include "mailbox.h"#include "browser.h"#ifdef USE_IMAP#include "imap.h"#endif#include <stdlib.h>#include <dirent.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <sys/stat.h>#include <errno.h>static struct mapping_t FolderHelp[] = {  { N_("Exit"),  OP_EXIT },  { N_("Chdir"), OP_CHANGE_DIRECTORY },  { N_("Mask"),  OP_ENTER_MASK },  { N_("Help"),  OP_HELP },  { NULL }};typedef struct folder_t{  struct folder_file *ff;  int num;} FOLDER;static char LastDir[_POSIX_PATH_MAX] = "";static char LastDirBackup[_POSIX_PATH_MAX] = "";/* Frees up the memory allocated for the local-global variables.  */static void destroy_state (struct browser_state *state){  int c;  for (c = 0; c < state->entrylen; c++)  {    FREE (&((state->entry)[c].name));    FREE (&((state->entry)[c].desc));    FREE (&((state->entry)[c].st));  }#ifdef USE_IMAP  FREE (&state->folder);#endif  FREE (&state->entry);}static int browser_compare_subject (const void *a, const void *b){  struct folder_file *pa = (struct folder_file *) a;  struct folder_file *pb = (struct folder_file *) b;  int r = mutt_strcoll (pa->name, pb->name);  return ((BrowserSort & SORT_REVERSE) ? -r : r);}static int browser_compare_date (const void *a, const void *b){  struct folder_file *pa = (struct folder_file *) a;  struct folder_file *pb = (struct folder_file *) b;  int r = pa->mtime - pb->mtime;  return ((BrowserSort & SORT_REVERSE) ? -r : r);}static int browser_compare_size (const void *a, const void *b){  struct folder_file *pa = (struct folder_file *) a;  struct folder_file *pb = (struct folder_file *) b;  int r = pa->size - pb->size;  return ((BrowserSort & SORT_REVERSE) ? -r : r);}static void browser_sort (struct browser_state *state){  int (*f) (const void *, const void *);  switch (BrowserSort & SORT_MASK)  {    case SORT_ORDER:      return;    case SORT_DATE:      f = browser_compare_date;      break;    case SORT_SIZE:      f = browser_compare_size;      break;    case SORT_SUBJECT:    default:      f = browser_compare_subject;      break;  }  qsort (state->entry, state->entrylen, sizeof (struct folder_file), f);}static int link_is_dir (const char *folder, const char *path){  struct stat st;  char fullpath[_POSIX_PATH_MAX];    mutt_concat_path (fullpath, folder, path, sizeof (fullpath));    if (stat (fullpath, &st) == 0)    return (S_ISDIR (st.st_mode));  else    return 0;}static const char *folder_format_str (char *dest, size_t destlen, char op, const char *src,		   const char *fmt, const char *ifstring, const char *elsestring,		   unsigned long data, format_flag flags){  char fn[SHORT_STRING], tmp[SHORT_STRING], permission[11];  char date[16], *t_fmt;  time_t tnow;  FOLDER *folder = (FOLDER *) data;  struct passwd *pw;  struct group *gr;  int optional = (flags & M_FORMAT_OPTIONAL);  switch (op)  {    case 'C':      snprintf (tmp, sizeof (tmp), "%%%sd", fmt);      snprintf (dest, destlen, tmp, folder->num + 1);      break;          case 'd':      if (folder->ff->st != NULL)      {	tnow = time (NULL);	t_fmt = tnow - folder->ff->st->st_mtime < 31536000 ? "%b %d %H:%M" : "%b %d  %Y";	strftime (date, sizeof (date), t_fmt, localtime (&folder->ff->st->st_mtime));	mutt_format_s (dest, destlen, fmt, date);      }      else	mutt_format_s (dest, destlen, fmt, "");      break;          case 'f':    {      char *s;#ifdef USE_IMAP      if (folder->ff->imap)	s = NONULL (folder->ff->desc);      else#endif	s = NONULL (folder->ff->name);      snprintf (fn, sizeof (fn), "%s%s", s,		folder->ff->st ? (S_ISLNK (folder->ff->st->st_mode) ? "@" :						  (S_ISDIR (folder->ff->st->st_mode) ? "/" : 				   ((folder->ff->st->st_mode & S_IXUSR) != 0 ? "*" : ""))) : "");            mutt_format_s (dest, destlen, fmt, fn);      break;    }    case 'F':      if (folder->ff->st != NULL)      {	snprintf (permission, sizeof (permission), "%c%c%c%c%c%c%c%c%c%c",		  S_ISDIR(folder->ff->st->st_mode) ? 'd' : (S_ISLNK(folder->ff->st->st_mode) ? 'l' : '-'),		  (folder->ff->st->st_mode & S_IRUSR) != 0 ? 'r': '-',		  (folder->ff->st->st_mode & S_IWUSR) != 0 ? 'w' : '-',		  (folder->ff->st->st_mode & S_ISUID) != 0 ? 's' : (folder->ff->st->st_mode & S_IXUSR) != 0 ? 'x': '-',		  (folder->ff->st->st_mode & S_IRGRP) != 0 ? 'r' : '-',		  (folder->ff->st->st_mode & S_IWGRP) != 0 ? 'w' : '-',		  (folder->ff->st->st_mode & S_ISGID) != 0 ? 's' : (folder->ff->st->st_mode & S_IXGRP) != 0 ? 'x': '-',		  (folder->ff->st->st_mode & S_IROTH) != 0 ? 'r' : '-',		  (folder->ff->st->st_mode & S_IWOTH) != 0 ? 'w' : '-',		  (folder->ff->st->st_mode & S_ISVTX) != 0 ? 't' : (folder->ff->st->st_mode & S_IXOTH) != 0 ? 'x': '-');	mutt_format_s (dest, destlen, fmt, permission);      }#ifdef USE_IMAP      else if (folder->ff->imap)      {	/* mark folders with subfolders AND mail */	snprintf (permission, sizeof (permission), "IMAP %c",		  (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');	mutt_format_s (dest, destlen, fmt, permission);      }                                        #endif      else	mutt_format_s (dest, destlen, fmt, "");      break;          case 'g':      if (folder->ff->st != NULL)      {	if ((gr = getgrgid (folder->ff->st->st_gid)))	  mutt_format_s (dest, destlen, fmt, gr->gr_name);	else	{	  snprintf (tmp, sizeof (tmp), "%%%sld", fmt);	  snprintf (dest, destlen, tmp, folder->ff->st->st_gid);	}      }      else	mutt_format_s (dest, destlen, fmt, "");      break;          case 'l':      if (folder->ff->st != NULL)      {	snprintf (tmp, sizeof (tmp), "%%%sd", fmt);	snprintf (dest, destlen, tmp, folder->ff->st->st_nlink);      }      else	mutt_format_s (dest, destlen, fmt, "");      break;          case 'N':#ifdef USE_IMAP      if (mx_is_imap (folder->ff->desc))      {	if (!optional)	{	  snprintf (tmp, sizeof (tmp), "%%%sd", fmt);	  snprintf (dest, destlen, tmp, folder->ff->new);	}	else if (!folder->ff->new)	  optional = 0;	break;      }#endif      snprintf (tmp, sizeof (tmp), "%%%sc", fmt);      snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : ' ');      break;          case 's':      if (folder->ff->st != NULL)      {	snprintf (tmp, sizeof (tmp), "%%%sld", fmt);	snprintf (dest, destlen, tmp, (long) folder->ff->st->st_size);      }      else	mutt_format_s (dest, destlen, fmt, "");      break;          case 't':      snprintf (tmp, sizeof (tmp), "%%%sc", fmt);      snprintf (dest, destlen, tmp, folder->ff->tagged ? '*' : ' ');      break;          case 'u':      if (folder->ff->st != NULL)      {	if ((pw = getpwuid (folder->ff->st->st_uid)))	  mutt_format_s (dest, destlen, fmt, pw->pw_name);	else	{	  snprintf (tmp, sizeof (tmp), "%%%sld", fmt);	  snprintf (dest, destlen, tmp, folder->ff->st->st_uid);	}      }      else	mutt_format_s (dest, destlen, fmt, "");      break;          default:      snprintf (tmp, sizeof (tmp), "%%%sc", fmt);      snprintf (dest, destlen, tmp, op);      break;  }  if (optional)    mutt_FormatString (dest, destlen, ifstring, folder_format_str, data, 0);  else if (flags & M_FORMAT_OPTIONAL)    mutt_FormatString (dest, destlen, elsestring, folder_format_str, data, 0);  return (src);}static void add_folder (MUTTMENU *m, struct browser_state *state,			const char *name, const struct stat *s, int new){  if (state->entrylen == state->entrymax)  {    /* need to allocate more space */    safe_realloc (&state->entry,		  sizeof (struct folder_file) * (state->entrymax += 256));    memset (&state->entry[state->entrylen], 0,	    sizeof (struct folder_file) * 256);    if (m)      m->data = state->entry;  }  if (s != NULL)  {    (state->entry)[state->entrylen].mode = s->st_mode;    (state->entry)[state->entrylen].mtime = s->st_mtime;    (state->entry)[state->entrylen].size = s->st_size;        (state->entry)[state->entrylen].st = safe_malloc (sizeof (struct stat));    memcpy ((state->entry)[state->entrylen].st, s, sizeof (struct stat));  }  (state->entry)[state->entrylen].new = new;  (state->entry)[state->entrylen].name = safe_strdup (name);  (state->entry)[state->entrylen].desc = safe_strdup (name);#ifdef USE_IMAP  (state->entry)[state->entrylen].imap = 0;#endif  (state->entrylen)++;}static void init_state (struct browser_state *state, MUTTMENU *menu){  state->entrylen = 0;  state->entrymax = 256;  state->entry = (struct folder_file *) safe_calloc (state->entrymax, sizeof (struct folder_file));#ifdef USE_IMAP  state->imap_browse = 0;#endif  if (menu)    menu->data = state->entry;}static int examine_directory (MUTTMENU *menu, struct browser_state *state,			      char *d, const char *prefix){  struct stat s;  DIR *dp;  struct dirent *de;  char buffer[_POSIX_PATH_MAX + SHORT_STRING];  BUFFY *tmp;  while (stat (d, &s) == -1)  {    if (errno == ENOENT)    {      /* The last used directory is deleted, try to use the parent dir. */      char *c = strrchr (d, '/');      if (c && (c > d))      {	*c = 0;	continue;      }    }    mutt_perror (d);    return (-1);  }  if (!S_ISDIR (s.st_mode))  {    mutt_error (_("%s is not a directory."), d);    return (-1);  }  mutt_buffy_check (0);  if ((dp = opendir (d)) == NULL)  {    mutt_perror (d);    return (-1);  }  init_state (state, menu);  while ((de = readdir (dp)) != NULL)  {    if (mutt_strcmp (de->d_name, ".") == 0)      continue;    /* we don't need . */        if (prefix && *prefix && mutt_strncmp (prefix, de->d_name, mutt_strlen (prefix)) != 0)      continue;    if (!((regexec (Mask.rx, de->d_name, 0, NULL, 0) == 0) ^ Mask.not))      continue;    mutt_concat_path (buffer, d, de->d_name, sizeof (buffer));    if (lstat (buffer, &s) == -1)      continue;        if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&	(! S_ISLNK (s.st_mode)))      continue;        tmp = Incoming;    while (tmp && mutt_strcmp (buffer, tmp->path))      tmp = tmp->next;    add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0);  }  closedir (dp);    browser_sort (state);  return 0;}static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state){  struct stat s;  char buffer[LONG_STRING];  BUFFY *tmp = Incoming;  if (!Incoming)    return (-1);  mutt_buffy_check (0);  init_state (state, menu);  do  {#ifdef USE_IMAP    if (mx_is_imap (tmp->path))    {      add_folder (menu, state, tmp->path, NULL, tmp->new);      continue;    }#endif#ifdef USE_POP    if (mx_is_pop (tmp->path))    {      add_folder (menu, state, tmp->path, NULL, tmp->new);      continue;    }#endif    if (lstat (tmp->path, &s) == -1)      continue;    if ((! S_ISREG (s.st_mode)) && (! S_ISDIR (s.st_mode)) &&	(! S_ISLNK (s.st_mode)))      continue;        strfcpy (buffer, NONULL(tmp->path), sizeof (buffer));    mutt_pretty_mailbox (buffer);    add_folder (menu, state, buffer, &s, tmp->new);  }  while ((tmp = tmp->next));  browser_sort (state);  return 0;}static int select_file_search (MUTTMENU *menu, regex_t *re, int n){  return (regexec (re, ((struct folder_file *) menu->data)[n].name, 0, NULL, 0));}static void folder_entry (char *s, size_t slen, MUTTMENU *menu, int num){  FOLDER folder;  folder.ff = &((struct folder_file *) menu->data)[num];  folder.num = num;    mutt_FormatString (s, slen, NONULL(FolderFormat), folder_format_str,       (unsigned long) &folder, M_FORMAT_ARROWCURSOR);}static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title,		       size_t titlelen, int buffy){  char path[_POSIX_PATH_MAX];  menu->max = state->entrylen;  if(menu->current >= menu->max)    menu->current = menu->max - 1;  if (menu->current < 0)    menu->current = 0;  if (menu->top > menu->current)    menu->top = 0;  menu->tagged = 0;    if (buffy)    snprintf (title, titlelen, _("Mailboxes [%d]"), mutt_buffy_check (0));  else  {    strfcpy (path, LastDir, sizeof (path));    mutt_pretty_mailbox (path);#ifdef USE_IMAP  if (state->imap_browse && option (OPTIMAPLSUB))    snprintf (title, titlelen, _("Subscribed [%s], File mask: %s"),	      path, NONULL (Mask.pattern));  else#endif    snprintf (title, titlelen, _("Directory [%s], File mask: %s"),	      path, NONULL(Mask.pattern));  }  menu->redraw = REDRAW_FULL;}static int file_tag (MUTTMENU *menu, int n, int m){  struct folder_file *ff = &(((struct folder_file *)menu->data)[n]);  int ot;  if (S_ISDIR (ff->mode) || (S_ISLNK (ff->mode) && link_is_dir (LastDir, ff->name)))  {    mutt_error _("Can't attach a directory!");    return 0;  }    ot = ff->tagged;  ff->tagged = (m >= 0 ? m : !ff->tagged);    return ff->tagged - ot;}void _mutt_select_file (char *f, size_t flen, int flags, char ***files, int *numfiles){  char buf[_POSIX_PATH_MAX];  char prefix[_POSIX_PATH_MAX] = "";  char helpstr[SHORT_STRING];  char title[STRING];  struct browser_state state;  MUTTMENU *menu;  struct stat st;  int i, killPrefix = 0;  int multiple = (flags & M_SEL_MULTI)  ? 1 : 0;  int folder   = (flags & M_SEL_FOLDER) ? 1 : 0;  int buffy    = (flags & M_SEL_BUFFY)  ? 1 : 0;  buffy = buffy && folder;    memset (&state, 0, sizeof (struct browser_state));  if (!folder)    strfcpy (LastDirBackup, LastDir, sizeof (LastDirBackup));  if (*f)  {    mutt_expand_path (f, flen);#ifdef USE_IMAP    if (mx_is_imap (f))    {      init_state (&state, NULL);      state.imap_browse = 1;      if (!imap_browse (f, &state))        strfcpy (LastDir, state.folder, sizeof (LastDir));    }    else    {#endif    for (i = mutt_strlen (f) - 1; i > 0 && f[i] != '/' ; i--);    if (i > 0)    {      if (f[0] == '/')      {	if (i > sizeof (LastDir) - 1) i = sizeof (LastDir) - 1;	strncpy (LastDir, f, i);	LastDir[i] = 0;      }      else      {	getcwd (LastDir, sizeof (LastDir));	safe_strcat (LastDir, sizeof (LastDir), "/");	safe_strncat (LastDir, sizeof (LastDir), f, i);      }    }    else    {      if (f[0] == '/')	strcpy (LastDir, "/");		/* __STRCPY_CHECKED__ */      else	getcwd (LastDir, sizeof (LastDir));    }    if (i <= 0 && f[0] != '/')      strfcpy (prefix, f, sizeof (prefix));    else      strfcpy (prefix, f + i + 1, sizeof (prefix));    killPrefix = 1;#ifdef USE_IMAP    }#endif  }  else   {

⌨️ 快捷键说明

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