mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

src/mn-gmime-stream-vfs.gob (7790B) - raw

      1 /*
      2  * Mail Notification
      3  * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License along
     16  * with this program; if not, write to the Free Software Foundation, Inc.,
     17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     18  */
     19 
     20 %headertop{
     21 #include <libgnomevfs/gnome-vfs.h>
     22 #include <gmime/gmime.h>
     23 %}
     24 
     25 %{
     26 #include <glib/gi18n.h>
     27 #include "mn-vfs.h"
     28 
     29 #define VFS_CALL(stream, expr, fail_format, fail_retval)		\
     30   {									\
     31     GnomeVFSResult result;						\
     32 									\
     33     result = expr;							\
     34     if (result != GNOME_VFS_OK)						\
     35       {									\
     36 	(stream)->_priv->eof = TRUE;					\
     37 	if (result != GNOME_VFS_ERROR_EOF)				\
     38 	  {								\
     39 	    g_warning((fail_format),					\
     40 		      (stream)->_priv->uri,				\
     41 		      gnome_vfs_result_to_string(result));		\
     42 	    return (fail_retval);					\
     43 	  }								\
     44       }									\
     45   }
     46 
     47 #define VFS_READ(stream, buffer, bytes, bytes_read, fail_retval) \
     48   VFS_CALL((stream), gnome_vfs_read((stream)->_priv->handle, (buffer), (bytes), (bytes_read)), _("unable to read %s: %s"), (fail_retval))
     49 #define VFS_WRITE(stream, buffer, bytes, bytes_written, fail_retval) \
     50   VFS_CALL((stream), gnome_vfs_write((stream)->_priv->handle, (buffer), (bytes), (bytes_written)), _("unable to write to %s: %s"), (fail_retval))
     51 #define VFS_SEEK(stream, whence, offset, fail_retval) \
     52   VFS_CALL((stream), gnome_vfs_seek((stream)->_priv->handle, (whence), (offset)), _("unable to seek in %s: %s"), (fail_retval))
     53 #define VFS_TELL(stream, offset_return, fail_retval) \
     54   VFS_CALL((stream), gnome_vfs_tell((stream)->_priv->handle, (offset_return)), _("unable to tell position of %s: %s"), (fail_retval))
     55 #define VFS_CLOSE(stream, fail_retval) \
     56   VFS_CALL((stream), gnome_vfs_close((stream)->_priv->handle), _("unable to close %s: %s"), (fail_retval))
     57 %}
     58 
     59 class MN:GMime:Stream:VFS from GMime:Stream
     60 {
     61   private GnomeVFSHandle *handle;
     62   private gboolean handle_owned;
     63 
     64   private char *uri destroywith g_free; /* used in error messages only */
     65   private gboolean eof;
     66 
     67   finalize (self)
     68   {
     69     if (selfp->handle_owned)
     70       g_mime_stream_close(GMIME_STREAM(self));
     71   }
     72 
     73   override (GMime:Stream) ssize_t
     74     read (GMimeStream *stream, char *buf, size_t len)
     75   {
     76     Self *self = SELF(stream);
     77     GnomeVFSFileSize bytes_read;
     78 
     79     if (stream->bound_end != -1 && stream->position >= stream->bound_end)
     80       return -1;
     81     if (stream->bound_end != -1)
     82       len = MIN(stream->bound_end - stream->position, (off_t) len);
     83 
     84     /* make sure we are at the right position */
     85     VFS_SEEK(self, GNOME_VFS_SEEK_START, stream->position, -1);
     86 
     87     VFS_READ(self, buf, len, &bytes_read, -1);
     88     stream->position += bytes_read;
     89 
     90     return bytes_read;
     91   }
     92 
     93   override (GMime:Stream) ssize_t
     94     write (GMimeStream *stream, const char *buf, size_t len)
     95   {
     96     Self *self = SELF(stream);
     97     GnomeVFSFileSize bytes_written;
     98 
     99     if (stream->bound_end != -1 && stream->position >= stream->bound_end)
    100       return -1;
    101     if (stream->bound_end != -1)
    102       len = MIN(stream->bound_end - stream->position, (off_t) len);
    103 
    104     /* make sure we are at the right position */
    105     VFS_SEEK(self, GNOME_VFS_SEEK_START, stream->position, -1);
    106 
    107     VFS_WRITE(self, buf, len, &bytes_written, -1);
    108     stream->position += bytes_written;
    109 
    110     return bytes_written;
    111   }
    112 
    113   override (GMime:Stream) int
    114     flush (GMimeStream *stream)
    115   {
    116     /* nop */
    117     return 0;			/* success */
    118   }
    119 
    120   override (GMime:Stream) int
    121     close (GMimeStream *stream)
    122   {
    123     Self *self = SELF(stream);
    124 
    125     VFS_CLOSE(self, -1);
    126 
    127     return 0;			/* success */
    128   }
    129 
    130   override (GMime:Stream) gboolean
    131     eos (GMimeStream *stream)
    132   {
    133     Self *self = SELF(stream);
    134 
    135     if (stream->bound_end == -1)
    136       return selfp->eof;
    137     else
    138       return stream->position >= stream->bound_end;
    139   }
    140 
    141   override (GMime:Stream) int
    142     reset (GMimeStream *stream)
    143   {
    144     Self *self = SELF(stream);
    145 
    146     if (stream->position == stream->bound_start)
    147       return 0;
    148 
    149     VFS_SEEK(self, GNOME_VFS_SEEK_START, stream->bound_start, -1);
    150     stream->position = stream->bound_start;
    151 
    152     return 0;
    153   }
    154 
    155   override (GMime:Stream) off_t
    156     seek (GMimeStream *stream, off_t offset, GMimeSeekWhence whence)
    157   {
    158     Self *self = SELF(stream);
    159     off_t real = stream->position;
    160 
    161     switch (whence)
    162       {
    163       case GMIME_STREAM_SEEK_SET:
    164 	real = offset;
    165 	break;
    166 
    167       case GMIME_STREAM_SEEK_CUR:
    168 	real = stream->position + offset;
    169 	break;
    170 
    171       case GMIME_STREAM_SEEK_END:
    172 	if (stream->bound_end == -1)
    173 	  {
    174 	    GnomeVFSFileSize current_position;
    175 
    176 	    VFS_SEEK(self, GNOME_VFS_SEEK_END, offset, -1);
    177 	    VFS_TELL(self, &current_position, -1);
    178 
    179 	    real = current_position;
    180 	    if (real < stream->bound_start)
    181 	      real = stream->bound_start;
    182 	    stream->position = real;
    183 
    184 	    return real;
    185 	  }
    186 	real = stream->bound_end + offset;
    187 	break;
    188       }
    189 
    190     if (stream->bound_end != -1)
    191       real = MIN(real, stream->bound_end);
    192     real = MAX(real, stream->bound_start);
    193 
    194     VFS_SEEK(self, GNOME_VFS_SEEK_START, real, -1);
    195     stream->position = real;
    196 
    197     return real;
    198   }
    199 
    200   override (GMime:Stream) off_t
    201     tell (GMimeStream *stream)
    202   {
    203     return stream->position;
    204   }
    205 
    206   override (GMime:Stream) ssize_t
    207     length (GMimeStream *stream)
    208   {
    209     Self *self = SELF(stream);
    210     GnomeVFSFileSize bound_end;
    211 
    212     if (stream->bound_start != -1 && stream->bound_end != -1)
    213       return stream->bound_end - stream->bound_start;
    214 
    215     VFS_SEEK(self, GNOME_VFS_SEEK_END, 0, -1);
    216     VFS_TELL(self, &bound_end, -1);
    217     VFS_SEEK(self, GNOME_VFS_SEEK_START, stream->position, -1);
    218 
    219     if (bound_end < stream->bound_start)
    220       return -1;
    221 
    222     return bound_end - stream->bound_start;
    223   }
    224 
    225   override (GMime:Stream) GMimeStream *
    226     substream (GMimeStream *stream, off_t start, off_t end)
    227   {
    228     Self *self;
    229 
    230     self = GET_NEW;
    231     selfp->handle = SELF(stream)->_priv->handle;
    232     /* handle of the substream is not owned */
    233 
    234     g_mime_stream_construct(GMIME_STREAM(self), start, end);
    235 
    236     return GMIME_STREAM(self);
    237   }
    238 
    239   /*
    240    * Follows the GMime convention of owning the handle (even on error).
    241    */
    242   public GMimeStream *
    243     new (GnomeVFSHandle *handle (check null),
    244 	 GnomeVFSURI *uri (check null),
    245 	 GnomeVFSResult *result)
    246   {
    247     GMimeStream *stream;
    248     GnomeVFSResult _result;
    249     GnomeVFSFileSize current_position;
    250 
    251     if (gnome_vfs_seek(handle, GNOME_VFS_SEEK_CURRENT, 0) != GNOME_VFS_OK
    252 	|| gnome_vfs_tell(handle, &current_position) != GNOME_VFS_OK)
    253       {
    254 	char *buf;
    255 	int size;
    256 
    257 	/* unseekable or untellable file, use a GMimeStreamMem */
    258 
    259 	_result = mn_vfs_read_entire_file_uri(uri, &size, &buf);
    260 	if (_result == GNOME_VFS_OK)
    261 	  {
    262 	    stream = g_mime_stream_mem_new_with_buffer(buf, size);
    263 	    g_free(buf);
    264 	  }
    265 	else
    266 	  stream = NULL;
    267 
    268 	gnome_vfs_close(handle);
    269       }
    270     else
    271       {
    272 	Self *self;
    273 
    274 	_result = GNOME_VFS_OK;
    275 
    276 	self = GET_NEW;
    277 	selfp->handle = handle;
    278 	selfp->handle_owned = TRUE;
    279 	selfp->uri = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE);
    280 
    281 	stream = GMIME_STREAM(self);
    282 	g_mime_stream_construct(stream, current_position, -1);
    283 
    284 	/* check for EOF */
    285 	if (g_mime_stream_length(stream) <= 0)
    286 	  selfp->eof = TRUE;
    287       }
    288 
    289     if (result)
    290       *result = _result;
    291 
    292     return stream;
    293   }
    294 }