Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
b703078d
...
b703078dbb367e560ab2940d7991045473fb3a3e
authored
2006-02-06 11:49:47 +0000
by
Sergey Poznyakoff
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
New file. Derived from mh/mh_stream.c
1 parent
ca5f00a6
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
448 additions
and
0 deletions
mailbox/message_stream.c
mailbox/message_stream.c
0 → 100644
View file @
b703078
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2006 Free Software Foundation, Inc.
GNU Mailutils 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.
GNU Mailutils 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 GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA */
/* This file implements an MH draftfile stream: a read-only stream used
to transparently pass MH draftfiles to mailers. The only difference
between the usual RFC822 and MH draft is that the latter allows to use
a string of dashes to separate the headers from the body. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/address.h>
#include <mailutils/envelope.h>
#include <mailutils/message.h>
#include <mailutils/header.h>
#include <mailutils/body.h>
#include <mailutils/stream.h>
#include <mailutils/mutil.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
struct
_mu_rfc822_stream
{
mu_stream_t
stream
;
/* Actual stream */
size_t
mark_offset
;
/* Offset of the header separator */
size_t
mark_length
;
/* Length of the header separator (not counting the
newline) */
};
static
int
_mu_rfc822_read
(
mu_stream_t
stream
,
char
*
optr
,
size_t
osize
,
mu_off_t
offset
,
size_t
*
nbytes
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
if
(
offset
<
s
->
mark_offset
)
{
if
(
offset
+
osize
>=
s
->
mark_offset
)
osize
=
s
->
mark_offset
-
offset
;
}
else
offset
+=
s
->
mark_length
;
return
mu_stream_read
(
s
->
stream
,
optr
,
osize
,
offset
,
nbytes
);
}
static
int
_mu_rfc822_readline
(
mu_stream_t
stream
,
char
*
optr
,
size_t
osize
,
mu_off_t
offset
,
size_t
*
nbytes
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
if
(
offset
<
s
->
mark_offset
)
{
if
(
offset
+
osize
>=
s
->
mark_offset
)
{
int
rc
;
size_t
n
;
size_t
rdsize
=
s
->
mark_offset
-
offset
+
1
;
rc
=
mu_stream_readline
(
s
->
stream
,
optr
,
rdsize
,
offset
,
&
n
);
if
(
rc
==
0
)
{
if
(
nbytes
)
*
nbytes
=
n
;
}
return
rc
;
}
}
else
offset
+=
s
->
mark_length
;
return
mu_stream_readline
(
s
->
stream
,
optr
,
osize
,
offset
,
nbytes
);
}
static
int
_mu_rfc822_size
(
mu_stream_t
stream
,
mu_off_t
*
psize
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
int
rc
=
mu_stream_size
(
s
->
stream
,
psize
);
if
(
rc
==
0
)
*
psize
-=
s
->
mark_length
;
return
rc
;
}
static
int
_mu_rfc822_open
(
mu_stream_t
stream
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
size_t
offset
,
len
;
char
buffer
[
256
];
int
rc
;
offset
=
0
;
while
((
rc
=
mu_stream_readline
(
s
->
stream
,
buffer
,
sizeof
buffer
,
offset
,
&
len
))
==
0
&&
len
>
0
)
{
if
(
mu_mh_delim
(
buffer
))
{
s
->
mark_offset
=
offset
;
s
->
mark_length
=
len
-
1
;
/* do not count the terminating newline */
break
;
}
offset
+=
len
;
}
return
0
;
}
static
int
_mu_rfc822_close
(
mu_stream_t
stream
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
return
mu_stream_close
(
s
->
stream
);
}
static
void
_mu_rfc822_destroy
(
mu_stream_t
stream
)
{
struct
_mu_rfc822_stream
*
s
=
mu_stream_get_owner
(
stream
);
if
(
s
->
stream
)
mu_stream_destroy
(
&
s
->
stream
,
mu_stream_get_owner
(
s
->
stream
));
free
(
s
);
}
int
mu_rfc822_stream_create
(
mu_stream_t
*
stream
,
mu_stream_t
src
,
int
flags
)
{
struct
_mu_rfc822_stream
*
s
;
int
rc
;
if
(
!
flags
)
flags
=
MU_STREAM_READ
;
if
(
flags
!=
MU_STREAM_READ
)
return
EINVAL
;
s
=
calloc
(
1
,
sizeof
(
*
s
));
if
(
s
==
NULL
)
return
ENOMEM
;
s
->
stream
=
src
;
rc
=
mu_stream_create
(
stream
,
flags
|
MU_STREAM_NO_CHECK
,
s
);
if
(
rc
)
{
free
(
s
);
return
rc
;
}
mu_stream_set_open
(
*
stream
,
_mu_rfc822_open
,
s
);
mu_stream_set_close
(
*
stream
,
_mu_rfc822_close
,
s
);
mu_stream_set_destroy
(
*
stream
,
_mu_rfc822_destroy
,
s
);
mu_stream_set_readline
(
*
stream
,
_mu_rfc822_readline
,
s
);
mu_stream_set_read
(
*
stream
,
_mu_rfc822_read
,
s
);
mu_stream_set_size
(
*
stream
,
_mu_rfc822_size
,
s
);
return
0
;
}
/* *************************** MH draft message **************************** */
static
char
*
skipws
(
char
*
p
,
size_t
off
)
{
int
len
;
for
(
p
+=
off
;
*
p
&&
isspace
(
*
p
);
p
++
)
;
len
=
strlen
(
p
);
if
(
len
>
0
&&
p
[
len
-
1
]
==
'\n'
)
p
[
len
-
1
]
=
0
;
return
p
;
}
struct
_mu_rfc822_message
{
char
*
from
;
char
*
date
;
mu_off_t
body_start
;
mu_off_t
body_end
;
};
static
int
restore_envelope
(
mu_stream_t
str
,
struct
_mu_rfc822_message
**
pmenv
)
{
size_t
offset
=
0
;
char
*
from
=
NULL
;
char
*
env_from
=
NULL
;
char
*
env_date
=
NULL
;
int
rc
;
char
buffer
[
128
];
size_t
len
;
mu_off_t
body_start
,
body_end
;
while
((
rc
=
mu_stream_readline
(
str
,
buffer
,
sizeof
buffer
,
offset
,
&
len
))
==
0
&&
len
>
0
)
{
if
(
buffer
[
0
]
==
'\n'
)
break
;
buffer
[
len
]
=
0
;
offset
+=
len
;
if
(
strncasecmp
(
buffer
,
MU_HEADER_FROM
,
sizeof
(
MU_HEADER_FROM
)
-
1
)
==
0
)
from
=
strdup
(
skipws
(
buffer
,
sizeof
(
MU_HEADER_FROM
)));
else
if
(
strncasecmp
(
buffer
,
MU_HEADER_ENV_SENDER
,
sizeof
(
MU_HEADER_ENV_SENDER
)
-
1
)
==
0
)
env_from
=
strdup
(
skipws
(
buffer
,
sizeof
(
MU_HEADER_ENV_SENDER
)));
else
if
(
strncasecmp
(
buffer
,
MU_HEADER_ENV_DATE
,
sizeof
(
MU_HEADER_ENV_DATE
)
-
1
)
==
0
)
env_date
=
strdup
(
skipws
(
buffer
,
sizeof
(
MU_HEADER_ENV_DATE
)));
}
body_start
=
offset
+
1
;
mu_stream_size
(
str
,
&
body_end
);
if
(
!
env_from
)
{
if
(
from
)
{
mu_address_t
addr
;
mu_address_create
(
&
addr
,
from
);
if
(
!
addr
||
mu_address_aget_email
(
addr
,
1
,
&
env_from
))
env_from
=
strdup
(
"GNU Mailutils"
);
mu_address_destroy
(
&
addr
);
}
else
env_from
=
strdup
(
"GNU-MH"
);
}
if
(
!
env_date
)
{
struct
tm
*
tm
;
time_t
t
;
char
date
[
80
];
time
(
&
t
);
tm
=
gmtime
(
&
t
);
strftime
(
date
,
sizeof
(
date
),
"%a %b %e %H:%M:%S %Y"
,
tm
);
env_date
=
strdup
(
date
);
}
*
pmenv
=
malloc
(
sizeof
(
**
pmenv
)
+
strlen
(
env_from
)
+
strlen
(
env_date
)
+
2
);
if
(
!*
pmenv
)
{
free
(
env_from
);
free
(
env_date
);
return
ENOMEM
;
}
(
*
pmenv
)
->
from
=
(
char
*
)
(
*
pmenv
+
1
);
(
*
pmenv
)
->
date
=
(
char
*
)
((
*
pmenv
)
->
from
+
strlen
(
env_from
)
+
1
);
strcpy
((
*
pmenv
)
->
from
,
env_from
);
strcpy
((
*
pmenv
)
->
date
,
env_date
);
(
*
pmenv
)
->
body_start
=
body_start
;
(
*
pmenv
)
->
body_end
=
body_end
;
free
(
env_from
);
free
(
env_date
);
free
(
from
);
return
0
;
}
static
int
_env_msg_date
(
mu_envelope_t
envelope
,
char
*
buf
,
size_t
len
,
size_t
*
pnwrite
)
{
mu_message_t
msg
=
mu_envelope_get_owner
(
envelope
);
struct
_mu_rfc822_message
*
env
=
mu_message_get_owner
(
msg
);
if
(
!
env
||
!
env
->
date
)
return
EINVAL
;
if
(
buf
)
{
strncpy
(
buf
,
env
->
date
,
len
);
buf
[
len
-
1
]
=
0
;
if
(
pnwrite
)
*
pnwrite
=
len
;
}
else
if
(
!
pnwrite
)
return
EINVAL
;
else
*
pnwrite
=
strlen
(
env
->
date
);
return
0
;
}
static
int
_env_msg_sender
(
mu_envelope_t
envelope
,
char
*
buf
,
size_t
len
,
size_t
*
pnwrite
)
{
mu_message_t
msg
=
mu_envelope_get_owner
(
envelope
);
struct
_mu_rfc822_message
*
env
=
mu_message_get_owner
(
msg
);
if
(
!
env
||
!
env
->
from
)
return
EINVAL
;
if
(
buf
)
{
strncpy
(
buf
,
env
->
from
,
len
);
buf
[
len
-
1
]
=
0
;
if
(
pnwrite
)
*
pnwrite
=
len
;
}
else
if
(
!
pnwrite
)
return
EINVAL
;
else
*
pnwrite
=
strlen
(
env
->
from
);
return
0
;
}
static
int
_body_size
(
mu_body_t
body
,
size_t
*
size
)
{
mu_message_t
msg
=
mu_body_get_owner
(
body
);
struct
_mu_rfc822_message
*
mp
=
mu_message_get_owner
(
msg
);
if
(
size
)
*
size
=
mp
->
body_end
-
mp
->
body_start
;
return
0
;
}
static
int
_body_read
(
mu_stream_t
stream
,
char
*
optr
,
size_t
osize
,
mu_off_t
offset
,
size_t
*
nbytes
)
{
mu_body_t
body
=
mu_stream_get_owner
(
stream
);
mu_message_t
msg
=
mu_body_get_owner
(
body
);
struct
_mu_rfc822_message
*
mp
=
mu_message_get_owner
(
msg
);
mu_stream_t
str
;
mu_message_get_stream
(
msg
,
&
str
);
return
mu_stream_read
(
str
,
optr
,
osize
,
mp
->
body_start
+
offset
,
nbytes
);
}
static
int
_body_readline
(
mu_stream_t
stream
,
char
*
optr
,
size_t
osize
,
mu_off_t
offset
,
size_t
*
nbytes
)
{
mu_body_t
body
=
mu_stream_get_owner
(
stream
);
mu_message_t
msg
=
mu_body_get_owner
(
body
);
struct
_mu_rfc822_message
*
mp
=
mu_message_get_owner
(
msg
);
mu_stream_t
str
;
mu_message_get_stream
(
msg
,
&
str
);
return
mu_stream_readline
(
str
,
optr
,
osize
,
mp
->
body_start
+
offset
,
nbytes
);
}
static
int
_body_stream_size
(
mu_stream_t
stream
,
mu_off_t
*
psize
)
{
mu_body_t
body
=
mu_stream_get_owner
(
stream
);
mu_message_t
msg
=
mu_body_get_owner
(
body
);
struct
_mu_rfc822_message
*
mp
=
mu_message_get_owner
(
msg
);
if
(
psize
)
*
psize
=
mp
->
body_end
-
mp
->
body_start
;
return
0
;
}
static
int
_body_stream_flush
(
mu_stream_t
str
ARG_UNUSED
)
{
return
0
;
}
int
mu_stream_to_message
(
mu_stream_t
instream
,
mu_message_t
*
pmsg
)
{
struct
_mu_rfc822_message
*
mp
;
mu_envelope_t
env
;
mu_message_t
msg
;
mu_body_t
body
;
mu_stream_t
bstream
;
mu_stream_t
draftstream
;
int
rc
;
if
((
rc
=
mu_rfc822_stream_create
(
&
draftstream
,
instream
,
0
)))
return
rc
;
if
((
rc
=
mu_stream_open
(
draftstream
)))
{
mu_stream_destroy
(
&
draftstream
,
mu_stream_get_owner
(
draftstream
));
return
rc
;
}
if
((
rc
=
restore_envelope
(
draftstream
,
&
mp
)
||
(
rc
=
mu_message_create
(
&
msg
,
mp
))))
{
mu_stream_destroy
(
&
draftstream
,
mu_stream_get_owner
(
draftstream
));
return
rc
;
}
mu_message_set_stream
(
msg
,
draftstream
,
mp
);
if
((
rc
=
mu_envelope_create
(
&
env
,
msg
)))
{
mu_stream_destroy
(
&
draftstream
,
mu_stream_get_owner
(
draftstream
));
return
rc
;
}
mu_envelope_set_date
(
env
,
_env_msg_date
,
msg
);
mu_envelope_set_sender
(
env
,
_env_msg_sender
,
msg
);
mu_message_set_envelope
(
msg
,
env
,
mp
);
mu_body_create
(
&
body
,
msg
);
mu_stream_create
(
&
bstream
,
MU_STREAM_RDWR
|
MU_STREAM_SEEKABLE
,
body
);
mu_stream_set_read
(
bstream
,
_body_read
,
body
);
mu_stream_set_readline
(
bstream
,
_body_readline
,
body
);
mu_stream_set_size
(
bstream
,
_body_stream_size
,
body
);
mu_stream_set_flush
(
bstream
,
_body_stream_flush
,
body
);
mu_body_set_stream
(
body
,
bstream
,
msg
);
mu_body_set_size
(
body
,
_body_size
,
msg
);
mu_message_set_body
(
msg
,
body
,
mp
);
*
pmsg
=
msg
;
return
0
;
}
Please
register
or
sign in
to post a comment