Blame view

libmailbox/mailbox.c 5.49 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* GNU mailutils - a suite of utilities for electronic mail
   Copyright (C) 1999 Free Software Foundation, Inc.

   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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
Jeff Bailey authored
17

18 19 20 21
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Jeff Bailey authored
22 23 24 25 26 27 28
#include "mailbox.h"
#include "unixmbox.h"

#ifdef _HAVE_ERRNO_H
#include <errno.h>
#endif

Sean 'Shaleh' Perry authored
29
#include <ctype.h>
30 31 32
#include <sys/stat.h>
#include <unistd.h>

Jeff Bailey authored
33
int _mbox_dummy1 (mailbox * mbox);
34
int _mbox_dummy2 (mailbox * mbox, unsigned int num);
Jeff Bailey authored
35
int _mbox_dummy3 (mailbox * mbox, char *c);
36
char *_mbox_dummy4 (mailbox * mbox, unsigned int num);
Jeff Bailey authored
37 38

mailbox *
39
mbox_open (const char *name)
Jeff Bailey authored
40
{
41
  mailbox *mbox;
42
  struct stat st;
43 44 45 46 47 48 49 50

  if ( name == NULL )
    {
      errno = EINVAL;
      return NULL;
    }

  mbox = malloc (sizeof (mailbox));
Jeff Bailey authored
51 52 53 54 55 56 57 58 59 60 61 62 63 64
  if (mbox == NULL)
    {
      errno = ENOMEM;
      return NULL;
    }

  /* Set up with default data and dummy functions */
  mbox->name = strdup (name);
  if (mbox->name == NULL)
    {
      errno = ENOMEM;
      free (mbox);
      return NULL;
    }
65 66 67 68
  /* check if we can look at file, prep for checks later in function */
  if (stat (mbox->name, &st) == -1)
    {
      free (mbox->name);
Sean 'Shaleh' Perry authored
69 70
      free (mbox);
      return NULL; /* errno set by stat() */
71 72
    }

Jeff Bailey authored
73 74 75 76 77 78 79 80
  mbox->messages = 0;
  mbox->num_deleted = 0;
  mbox->sizes = NULL;
  mbox->_data = NULL;
  mbox->_close = _mbox_dummy1;
  mbox->_delete = _mbox_dummy2;
  mbox->_undelete = _mbox_dummy2;
  mbox->_expunge = _mbox_dummy1;
81
  mbox->_scan = _mbox_dummy1;
Jeff Bailey authored
82 83
  mbox->_add_message = _mbox_dummy3;
  mbox->_is_deleted = _mbox_dummy2;
84
  mbox->_is_updated = _mbox_dummy1;
85
  mbox->_lock = _mbox_dummy2;
Jeff Bailey authored
86 87
  mbox->_get_body = _mbox_dummy4;
  mbox->_get_header = _mbox_dummy4;
88 89 90
#ifdef TESTING
  mbox->_tester = _mbox_dummy2;
#endif
Jeff Bailey authored
91

Sean 'Shaleh' Perry authored
92
  if (S_ISREG (st.st_mode))
93 94 95 96 97 98 99 100 101 102 103 104 105 106
    {
      if (unixmbox_open (mbox) == 0)
        return mbox;
      else
        {
          /*
           * Check errno to find out why it failed, if it's simply not a
           * unix mbox format message, then try other mailbox types,
           * otherwise, leave errno set and return NULL
           */
          if (errno == EBADMSG)
            errno = ENOSYS; /* no other mailboxes supported right now */
        }
    }
Sean 'Shaleh' Perry authored
107 108 109 110
  else if (S_ISDIR (st.st_mode))
    {
      /* for example...
         if (maildir_open (mbox, name) == 1)
Sean 'Shaleh' Perry authored
111 112
	 return mbox;
      */
Sean 'Shaleh' Perry authored
113 114
      errno = ENOSYS;
    }
115 116
  else
    errno = EINVAL; /* neither directory nor file, so bomb */
Jeff Bailey authored
117

118 119
  free (mbox->name);
  free (mbox);
Jeff Bailey authored
120 121 122 123
  return NULL;
}

/*
124 125 126
 * Gets the contents of a header field
 */
char *
127
mbox_header_line (mailbox *mbox, unsigned int num, const char *header)
128 129
{
  char *full, *tmp, *line;
Sean 'Shaleh' Perry authored
130 131 132
  int try = 1;
  size_t i = 0, j = 0;
  size_t len, lh;
133 134 135 136 137 138 139
  
  if ( mbox == NULL || header == NULL )
    {
      errno = EINVAL;
      return NULL;
    }

140 141 142 143
  full = mbox_get_header (mbox, num);
  if (full == NULL)
    return NULL;
 
144
  lh = strlen (header);
145
  len = strlen (full);
146
  tmp = NULL;
147 148 149 150 151 152 153 154 155

  /* First get the appropriate line at the beginning */
  for (i=0; i < len-(lh+2); i++)
    {
      if (try == 1)
	{
	  if (!strncasecmp(&full[i], header, lh) && full[i+lh] == ':')
	    {
	      tmp = strdup (&full[i+lh+2]);
Sean 'Shaleh' Perry authored
156 157 158 159 160 161
	      if (tmp == NULL)
		{
		  free(full);
		  return NULL;
		}
	      break;
162 163 164 165 166 167 168 169 170 171
	    }
	  else
	    try = 0;
	}
      else if (full[i] == '\n')
	try = 1;
      else
	try = 0;
    }

172 173 174 175 176 177
  /* FIXME: hmm, no valid header found, what should errno be? */
  if (tmp == NULL)
    {
      free(full);
      return NULL;
    }
178 179 180 181
  /* Now trim the fat */
  len = strlen (tmp);
  for (i = 0; i < len; i++)
    {
Sean 'Shaleh' Perry authored
182
      if (tmp[i] == '\n' && i < (len - 1) && isspace (tmp[i+1]))
183 184 185 186 187 188 189 190 191
	{
	  if (tmp[i+1] == '\t')
	    tmp[i + 1] = ' ';
	  for (j = i; j < len; j++)
	    tmp[j] = tmp[j+1];
	}
      else if (tmp[i] == '\n')
	{
	  tmp[i] = '\0';
Sean 'Shaleh' Perry authored
192
	  break;
193 194 195 196 197 198 199 200 201 202 203 204
	}
    }
  line = strdup (tmp);
  free (tmp);
  free (full);
  return line;
}

/*
 * Gets first LINES lines from message body
 */
char *
205
mbox_body_lines (mailbox *mbox, unsigned int num, unsigned int lines)
206 207 208
{
  char *full, *buf = NULL;
  int i=0, line = 0, len;
209 210 211
  if (mbox == NULL)
    {
      errno = EINVAL;
Sean 'Shaleh' Perry authored
212
      return NULL;
213 214
    }
  if (lines == 0)
215 216 217 218 219 220 221 222 223 224 225 226 227 228
    return strdup ("");
  full = mbox_get_body (mbox, num);
  if (full == NULL)
    return NULL;
  len = strlen (full);
  for (i=0; i < len && line < lines; i++)
    {
      if (full[i] == '\n')
	{
	  line++;
	  if (line >= lines)
	    {
	      full[i+1] = '\0';
	      buf = strdup (full);
Sean 'Shaleh' Perry authored
229
	      break;
230 231 232 233 234 235 236 237 238 239
	    }
	}
    }
  if (buf == NULL)
    buf = strdup (full);
  free (full);
  return buf;
}

/*
Jeff Bailey authored
240 241 242 243 244 245 246 247 248 249
 * Bogus functions for unimplemented functions that return int
 */
int
_mbox_dummy1 (mailbox * mbox)
{
  errno = ENOSYS;
  return -1;
}

int 
250
_mbox_dummy2 (mailbox * mbox, unsigned int num)
Jeff Bailey authored
251 252 253 254 255 256 257 258 259 260 261 262 263
{
  return _mbox_dummy1 (mbox);
}
int 
_mbox_dummy3 (mailbox * mbox, char *c)
{
  return _mbox_dummy1 (mbox);
}

/*
 * Bogus function for unimplemented functions that return char *
 */
char *
264
_mbox_dummy4 (mailbox * mbox, unsigned int num)
Jeff Bailey authored
265 266 267 268
{
  errno = ENOSYS;
  return NULL;
}
269