Exemple #1
0
static int
parse_color_pair(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err)
{
  if (! MoreArgs (s))
  {
    strfcpy (err->data, _("color: too few arguments"), err->dsize);
    return (-1);
  }

  mutt_extract_token (buf, s, 0);

  if (parse_color_name (buf->data, fg, attr, A_BOLD, err) != 0)
    return (-1);

  if (! MoreArgs (s))
  {
    strfcpy (err->data, _("color: too few arguments"), err->dsize);
    return (-1);
  }
  
  mutt_extract_token (buf, s, 0);

  if (parse_color_name (buf->data, bg, attr, A_BLINK, err) != 0)
    return (-1);
  
  return 0;
}
Exemple #2
0
int mutt_parse_score (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  SCORE *ptr, *last;
  char *pattern, *pc;
  struct pattern_t *pat;

  mutt_extract_token (buf, s, 0);
  if (!MoreArgs (s))
  {
    strfcpy (err->data, _("score: too few arguments"), err->dsize);
    return (-1);
  }
  pattern = buf->data;
  memset (buf, 0, sizeof (BUFFER));
  mutt_extract_token (buf, s, 0);
  if (MoreArgs (s))
  {
    FREE (&pattern);
    strfcpy (err->data, _("score: too many arguments"), err->dsize);
    return (-1);
  }

  /* look for an existing entry and update the value, else add it to the end
     of the list */
  for (ptr = Score, last = NULL; ptr; last = ptr, ptr = ptr->next)
    if (mutt_strcmp (pattern, ptr->str) == 0)
      break;
  if (!ptr)
  {
    if ((pat = mutt_pattern_comp (pattern, 0, err)) == NULL)
    {
      FREE (&pattern);
      return (-1);
    }
    ptr = safe_calloc (1, sizeof (SCORE));
    if (last)
      last->next = ptr;
    else
      Score = ptr;
    ptr->pat = pat;
    ptr->str = pattern;
  } else
    /* 'buf' arg was cleared and 'pattern' holds the only reference;
     * as here 'ptr' != NULL -> update the value only in which case
     * ptr->str already has the string, so pattern should be freed.
     */
    FREE (&pattern);
  pc = buf->data;
  if (*pc == '=')
  {
    ptr->exact = 1;
    pc++;
  }
  ptr->val = atoi (pc);
  set_option (OPTNEEDRESCORE);
  return 0;
}
Exemple #3
0
static int
parse_attr_spec(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err)
{
  
  if(fg) *fg = -1; 
  if(bg) *bg = -1;

  if (! MoreArgs (s))
  {
    strfcpy (err->data, _("mono: too few arguments"), err->dsize);
    return (-1);
  }

  mutt_extract_token (buf, s, 0);

  if (ascii_strcasecmp ("bold", buf->data) == 0)
    *attr |= A_BOLD;
  else if (ascii_strcasecmp ("underline", buf->data) == 0)
    *attr |= A_UNDERLINE;
  else if (ascii_strcasecmp ("none", buf->data) == 0)
    *attr = A_NORMAL;
  else if (ascii_strcasecmp ("reverse", buf->data) == 0)
    *attr |= A_REVERSE;
  else if (ascii_strcasecmp ("standout", buf->data) == 0)
    *attr |= A_STANDOUT;
  else if (ascii_strcasecmp ("normal", buf->data) == 0)
    *attr = A_NORMAL; /* needs use = instead of |= to clear other bits */
  else
  {
    snprintf (err->data, err->dsize, _("%s: no such attribute"), buf->data);
    return (-1);
  }
  
  return 0;
}
Exemple #4
0
static int parse_unlist (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  do
  {
    mutt_extract_token (buf, s, 0);
    remove_from_list ((LIST **) data, buf->data);
  }
  while (MoreArgs (s));

  return 0;
}
Exemple #5
0
static int parse_ignore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  do
  {
    mutt_extract_token (buf, s, 0);
    remove_from_list (&UnIgnore, buf->data);
    add_to_list (&Ignore, buf->data);
  }
  while (MoreArgs (s));

  return 0;
}
Exemple #6
0
static int parse_unignore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  do
  {
    mutt_extract_token (buf, s, 0);

    /* don't add "*" to the unignore list */
    if (strcmp (buf->data, "*")) 
      add_to_list (&UnIgnore, buf->data);

    remove_from_list (&Ignore, buf->data);
  }
  while (MoreArgs (s));

  return 0;
}
Exemple #7
0
static int parse_unalias (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  ALIAS *tmp, *last = NULL;

  do
  {
    mutt_extract_token (buf, s, 0);

    tmp = Aliases;
    for (tmp = Aliases; tmp; tmp = tmp->next)
    {
      if (CurrentMenu == MENU_ALIAS)
      {
	for (tmp = Aliases; tmp ; tmp = tmp->next)
	  tmp->del = 1;
	set_option (OPTFORCEREDRAWINDEX);
      }
      else
	mutt_free_alias (&Aliases);
      break;
    }
    else
      for (tmp = Aliases; tmp; tmp = tmp->next)
      {
	if (mutt_strcasecmp (buf->data, tmp->name) == 0)
	{
	  if (CurrentMenu == MENU_ALIAS)
	  {
	    tmp->del = 1;
	    set_option (OPTFORCEREDRAWINDEX);
	    break;
	  }

	  if (last)
	    last->next = tmp->next;
	  else
	    Aliases = tmp->next;
	  tmp->next = NULL;
	  mutt_free_alias (&tmp);
	  break;
	}
	last = tmp;
      }   
  }
int mutt_parse_unscore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  SCORE *tmp, *last = NULL;

  while (MoreArgs (s))
  {
    mutt_extract_token (buf, s, 0);
    if (!mutt_strcmp ("*", buf->data))
    {
      for (tmp = Score; tmp; )
      {
	last = tmp;
	tmp = tmp->next;
	mutt_pattern_free (&last->pat);
	safe_free ((void **) &last);
      }
      Score = NULL;
    }
    else
    {
      for (tmp = Score; tmp; last = tmp, tmp = tmp->next)
      {
	if (!mutt_strcmp (buf->data, tmp->str))
	{
	  if (last)
	    last->next = tmp->next;
	  else
	    Score = tmp->next;
	  mutt_pattern_free (&tmp->pat);
	  safe_free ((void **) &tmp);
	  /* there should only be one score per pattern, so we can stop here */
	  break;
	}
      }
    }
  }
  set_option (OPTNEEDRESCORE);
  return 0;
}
Exemple #9
0
/**
 * mutt_parse_icommand - Parse an informational command
 * @param line Command to execute
 * @param err  Buffer for error messages
 * @retval #MUTT_CMD_SUCCESS Success
 * @retval #MUTT_CMD_ERROR   Error (no message): command not found
 * @retval #MUTT_CMD_ERROR   Error with message: command failed
 * @retval #MUTT_CMD_WARNING Warning with message: command failed
 */
enum CommandResult mutt_parse_icommand(/* const */ char *line, struct Buffer *err)
{
  if (!line || !*line || !err)
    return MUTT_CMD_ERROR;

  enum CommandResult rc = MUTT_CMD_ERROR;

  struct Buffer expn, token;

  mutt_buffer_init(&expn);
  mutt_buffer_init(&token);

  expn.data = expn.dptr = line;
  expn.dsize = mutt_str_strlen(line);

  mutt_buffer_reset(err);

  SKIPWS(expn.dptr);
  while (*expn.dptr)
  {
    mutt_extract_token(&token, &expn, 0);
    for (size_t i = 0; ICommandList[i].name; i++)
    {
      if (mutt_str_strcmp(token.data, ICommandList[i].name) != 0)
        continue;

      rc = ICommandList[i].func(&token, &expn, ICommandList[i].data, err);
      if (rc != 0)
        goto finish;

      break; /* Continue with next command */
    }
  }

finish:
  if (expn.destroy)
    FREE(&expn.data);
  return rc;
}
Exemple #10
0
int mutt_parse_unhook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  while (MoreArgs (s))
  {
    mutt_extract_token (buf, s, 0);
    if (mutt_strcmp ("*", buf->data) == 0)
    {
      if (current_hook_type)
      {
	snprintf (err->data, err->dsize,
		  _("unhook: Can't do unhook * from within a hook."));
	return -1;
      }
      delete_hooks (0);
    }
    else
    {
      int type = mutt_get_hook_type (buf->data);

      if (!type)
      {
	snprintf (err->data, err->dsize,
		 _("unhook: unknown hook type: %s"), buf->data);
	return (-1);
      }
      if (current_hook_type == type)
      {
	snprintf (err->data, err->dsize,
		  _("unhook: Can't delete a %s from within a %s."),
		  buf->data, buf->data);
	return -1;
      }
      delete_hooks (type);
    }
  }
  return 0;
}
Exemple #11
0
static int
parse_object(BUFFER *buf, BUFFER *s, int *o, int *ql, BUFFER *err)
{
  int q_level = 0;
  char *eptr;
  
  if(!MoreArgs(s))
  {
    strfcpy(err->data, _("Missing arguments."), err->dsize);
    return -1;
  }
  
  mutt_extract_token(buf, s, 0);
  if(!mutt_strncmp(buf->data, "quoted", 6))
  {
    if(buf->data[6])
    {
      *ql = strtol(buf->data + 6, &eptr, 10);
      if(*eptr || q_level < 0)
      {
	snprintf(err->data, err->dsize, _("%s: no such object"), buf->data);
	return -1;
      }
    }
    else
      *ql = 0;
    
    *o = MT_COLOR_QUOTED;
  }
  else if ((*o = mutt_getvaluebyname (buf->data, Fields)) == -1)
  {
    snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
    return (-1);
  }

  return 0;
}
Exemple #12
0
int mutt_parse_hook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
  HOOK *ptr;
  BUFFER command, pattern;
  int rc, not = 0;
  regex_t *rx = NULL;
  pattern_t *pat = NULL;
  char path[_POSIX_PATH_MAX];

  mutt_buffer_init (&pattern);
  mutt_buffer_init (&command);

  if (*s->dptr == '!')
  {
    s->dptr++;
    SKIPWS (s->dptr);
    not = 1;
  }

  mutt_extract_token (&pattern, s, 0);

  if (!MoreArgs (s))
  {
    strfcpy (err->data, _("too few arguments"), err->dsize);
    goto error;
  }

  mutt_extract_token (&command, s, (data & (M_FOLDERHOOK | M_SENDHOOK | M_SEND2HOOK | M_ACCOUNTHOOK | M_REPLYHOOK)) ?  M_TOKEN_SPACE : 0);

  if (!command.data)
  {
    strfcpy (err->data, _("too few arguments"), err->dsize);
    goto error;
  }

  if (MoreArgs (s))
  {
    strfcpy (err->data, _("too many arguments"), err->dsize);
    goto error;
  }

  if (data & (M_FOLDERHOOK | M_MBOXHOOK))
  {
    strfcpy (path, pattern.data, sizeof (path));
    _mutt_expand_path (path, sizeof (path), 1);
    FREE (&pattern.data);
    memset (&pattern, 0, sizeof (pattern));
    pattern.data = safe_strdup (path);
  }
  else if (DefaultHook && !(data & (M_CHARSETHOOK | M_ICONVHOOK | M_ACCOUNTHOOK))
           && (!WithCrypto || !(data & M_CRYPTHOOK))
      )
  {
    char tmp[HUGE_STRING];

    /* At this stage remain only message-hooks, reply-hooks, send-hooks,
     * send2-hooks, save-hooks, and fcc-hooks: All those allowing full
     * patterns. If given a simple regexp, we expand $default_hook.
     */
    strfcpy (tmp, pattern.data, sizeof (tmp));
    mutt_check_simple (tmp, sizeof (tmp), DefaultHook);
    FREE (&pattern.data);
    memset (&pattern, 0, sizeof (pattern));
    pattern.data = safe_strdup (tmp);
  }

  if (data & (M_MBOXHOOK | M_SAVEHOOK | M_FCCHOOK))
  {
    strfcpy (path, command.data, sizeof (path));
    mutt_expand_path (path, sizeof (path));
    FREE (&command.data);
    memset (&command, 0, sizeof (command));
    command.data = safe_strdup (path);
  }

  /* check to make sure that a matching hook doesn't already exist */
  for (ptr = Hooks; ptr; ptr = ptr->next)
  {
    if (ptr->type == data &&
	ptr->rx.not == not &&
	!mutt_strcmp (pattern.data, ptr->rx.pattern))
    {
      if (data & (M_FOLDERHOOK | M_SENDHOOK | M_SEND2HOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK))
      {
	/* these hooks allow multiple commands with the same
	 * pattern, so if we've already seen this pattern/command pair, just
	 * ignore it instead of creating a duplicate */
	if (!mutt_strcmp (ptr->command, command.data))
	{
	  FREE (&command.data);
	  FREE (&pattern.data);
	  return 0;
	}
      }
      else
      {
	/* other hooks only allow one command per pattern, so update the
	 * entry with the new command.  this currently does not change the
	 * order of execution of the hooks, which i think is desirable since
	 * a common action to perform is to change the default (.) entry
	 * based upon some other information. */
	FREE (&ptr->command);
	ptr->command = command.data;
	FREE (&pattern.data);
	return 0;
      }
    }
    if (!ptr->next)
      break;
  }

  if (data & (M_SENDHOOK | M_SEND2HOOK | M_SAVEHOOK | M_FCCHOOK | M_MESSAGEHOOK | M_REPLYHOOK))
  {
    if ((pat = mutt_pattern_comp (pattern.data,
	   (data & (M_SENDHOOK | M_SEND2HOOK | M_FCCHOOK)) ? 0 : M_FULL_MSG,
				  err)) == NULL)
      goto error;
  }
  else
  {
    /* Hooks not allowing full patterns: Check syntax of regexp */
    rx = safe_malloc (sizeof (regex_t));
#ifdef M_CRYPTHOOK
    if ((rc = REGCOMP (rx, NONULL(pattern.data), ((data & (M_CRYPTHOOK|M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0))) != 0)
#else
    if ((rc = REGCOMP (rx, NONULL(pattern.data), (data & (M_CHARSETHOOK|M_ICONVHOOK)) ? REG_ICASE : 0)) != 0)
#endif /* M_CRYPTHOOK */
    {
      regerror (rc, rx, err->data, err->dsize);
      FREE (&rx);
      goto error;
    }
  }

  if (ptr)
  {
    ptr->next = safe_calloc (1, sizeof (HOOK));
    ptr = ptr->next;
  }
  else
    Hooks = ptr = safe_calloc (1, sizeof (HOOK));
  ptr->type = data;
  ptr->command = command.data;
  ptr->pattern = pat;
  ptr->rx.pattern = pattern.data;
  ptr->rx.rx = rx;
  ptr->rx.not = not;
  return 0;

error:
  FREE (&pattern.data);
  FREE (&command.data);
  return (-1);
}
Exemple #13
0
static int 
_mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err, 
		   parser_callback_t callback, short dry_run)
{
  int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0;
  int r = 0;

  if(parse_object(buf, s, &object, &q_level, err) == -1)
    return -1;

  if(callback(buf, s, &fg, &bg, &attr, err) == -1)
    return -1;

  /* extract a regular expression if needed */
  
  if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == MT_COLOR_INDEX)
  {
    if (!MoreArgs (s))
    {
      strfcpy (err->data, _("too few arguments"), err->dsize);
      return (-1);
    }

    mutt_extract_token (buf, s, 0);
  }
   
  if (MoreArgs (s))
  {
    strfcpy (err->data, _("too many arguments"), err->dsize);
    return (-1);
  }
  
  /* dry run? */
  
  if(dry_run) return 0;

  
#ifdef HAVE_COLOR
# ifdef HAVE_USE_DEFAULT_COLORS
  if (!option (OPTNOCURSES) && has_colors()
    /* delay use_default_colors() until needed, since it initializes things */
    && (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT)
    && use_default_colors () != OK)
  {
    strfcpy (err->data, _("default colors not supported"), err->dsize);
    return (-1);
  }
# endif /* HAVE_USE_DEFAULT_COLORS */
#endif
  
  if (object == MT_COLOR_HEADER)
    r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err,0);
  else if (object == MT_COLOR_BODY)
    r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0);
  else if (object == MT_COLOR_INDEX)
  {
    r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1);
    set_option (OPTFORCEREDRAWINDEX);
  }
  else if (object == MT_COLOR_QUOTED)
  {
    if (q_level >= ColorQuoteSize)
    {
      safe_realloc (&ColorQuote, (ColorQuoteSize += 2) * sizeof (int));
      ColorQuote[ColorQuoteSize-2] = ColorDefs[MT_COLOR_QUOTED];
      ColorQuote[ColorQuoteSize-1] = ColorDefs[MT_COLOR_QUOTED];
    }
    if (q_level >= ColorQuoteUsed)
      ColorQuoteUsed = q_level + 1;
    if (q_level == 0)
    {
      ColorDefs[MT_COLOR_QUOTED] = fgbgattr_to_color(fg, bg, attr);
      
      ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED];
      for (q_level = 1; q_level < ColorQuoteUsed; q_level++)
      {
	if (ColorQuote[q_level] == A_NORMAL)
	  ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED];
      }
    }
    else
      ColorQuote[q_level] = fgbgattr_to_color(fg, bg, attr);
  }
  else
    ColorDefs[object] = fgbgattr_to_color(fg, bg, attr);

#ifdef HAVE_COLOR
# ifdef HAVE_BKGDSET
  if (object == MT_COLOR_NORMAL && !option (OPTNOCURSES) && has_colors())
    BKGDSET (MT_COLOR_NORMAL);
# endif
#endif

  return (r);
}
Exemple #14
0
static int _mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data,
				BUFFER *err, short parse_uncolor)
{
  int object = 0, do_cache = 0;
  COLOR_LINE *tmp, *last = NULL;
  COLOR_LINE **list;

  mutt_extract_token (buf, s, 0);

  if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1)
  {
    snprintf (err->data, err->dsize, _("%s: no such object"), buf->data);
    return (-1);
  }

  if (mutt_strncmp (buf->data, "index", 5) == 0)
    list = &ColorIndexList;
  else if (mutt_strncmp (buf->data, "body", 4) == 0)
    list = &ColorBodyList;
  else if (mutt_strncmp (buf->data, "header", 7) == 0)
    list = &ColorHdrList;
  else
  {
    snprintf (err->data, err->dsize,
	      _("%s: command valid only for index, body, header objects"),
	      parse_uncolor ? "uncolor" : "unmono");
    return (-1);
  }

  if (!MoreArgs (s))
  {
    snprintf (err->data, err->dsize,
	      _("%s: too few arguments"), parse_uncolor ? "uncolor" : "unmono");
    return (-1);
  }

  if(
#ifdef HAVE_COLOR
     /* we're running without curses */
     option (OPTNOCURSES) 
     || /* we're parsing an uncolor command, and have no colors */
     (parse_uncolor && !has_colors())
     /* we're parsing an unmono command, and have colors */
     || (!parse_uncolor && has_colors())
#else
     /* We don't even have colors compiled in */
     parse_uncolor
#endif
     )
  {
    /* just eat the command, but don't do anything real about it */
    do
      mutt_extract_token (buf, s, 0);
    while (MoreArgs (s));

    return 0;
  }

  do
  {
    mutt_extract_token (buf, s, 0);
    if (!mutt_strcmp ("*", buf->data))
    {
      for (tmp = *list; tmp; )
      {
        if (!do_cache)
	  do_cache = 1;
	last = tmp;
	tmp = tmp->next;
	mutt_free_color_line(&last, parse_uncolor);
      }
      *list = NULL;
    }
    else
    {
      for (last = NULL, tmp = *list; tmp; last = tmp, tmp = tmp->next)
      {
	if (!mutt_strcmp (buf->data, tmp->pattern))
	{
          if (!do_cache)
	    do_cache = 1;
	  dprint(1,(debugfile,"Freeing pattern \"%s\" from color list\n",
	                       tmp->pattern));
	  if (last)
	    last->next = tmp->next;
	  else
	    *list = tmp->next;
	  mutt_free_color_line(&tmp, parse_uncolor);
	  break;
	}
      }
    }
  }
  while (MoreArgs (s));


  if (do_cache && !option (OPTNOCURSES))
  {
    int i;
    set_option (OPTFORCEREDRAWINDEX);
    /* force re-caching of index colors */
    for (i = 0; Context && i < Context->msgcount; i++)
      Context->hdrs[i]->pair = 0;
  }
  return (0);
}
Exemple #15
0
/**
 * icmd_bind - Parse 'bind' and 'macro' commands - Implements ::icommand_t
 */
static enum CommandResult icmd_bind(struct Buffer *buf, struct Buffer *s,
                                    unsigned long data, struct Buffer *err)
{
  FILE *fp_out = NULL;
  char tempfile[PATH_MAX];
  bool dump_all = false, bind = (data == 0);

  if (!MoreArgs(s))
    dump_all = true;
  else
    mutt_extract_token(buf, s, 0);

  if (MoreArgs(s))
  {
    /* More arguments potentially means the user is using the
     * ::command_t :bind command thus we delegate the task. */
    return MUTT_CMD_ERROR;
  }

  struct Buffer *filebuf = mutt_buffer_alloc(4096);
  if (dump_all || (mutt_str_strcasecmp(buf->data, "all") == 0))
  {
    dump_all_menus(filebuf, bind);
  }
  else
  {
    const int menu_index = mutt_map_get_value(buf->data, Menus);
    if (menu_index == -1)
    {
      mutt_buffer_printf(err, _("%s: no such menu"), buf->data);
      mutt_buffer_free(&filebuf);
      return MUTT_CMD_ERROR;
    }

    struct Mapping menu = { buf->data, menu_index };
    dump_menu(filebuf, &menu, bind);
  }

  if (mutt_buffer_is_empty(filebuf))
  {
    mutt_buffer_printf(err, _("%s: no %s for this menu"),
                       dump_all ? "all" : buf->data, bind ? "binds" : "macros");
    mutt_buffer_free(&filebuf);
    return MUTT_CMD_ERROR;
  }

  mutt_mktemp(tempfile, sizeof(tempfile));
  fp_out = mutt_file_fopen(tempfile, "w");
  if (!fp_out)
  {
    mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
    mutt_buffer_free(&filebuf);
    return MUTT_CMD_ERROR;
  }
  fputs(filebuf->data, fp_out);

  mutt_file_fclose(&fp_out);
  mutt_buffer_free(&filebuf);

  struct Pager info = { 0 };
  if (mutt_pager((bind) ? "bind" : "macro", tempfile, 0, &info) == -1)
  {
    mutt_buffer_printf(err, _("Could not create temporary file %s"), tempfile);
    return MUTT_CMD_ERROR;
  }

  return MUTT_CMD_SUCCESS;
}