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
43ba0c68
...
43ba0c68726d41135916aaaf9f4dfffdb56af872
authored
2001-05-07 04:36:40 +0000
by
Alain Magloire
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Implemented UID fetch BODYSTRUCTURE and multiple access to mailbox via IMAP
1 parent
33825193
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1145 additions
and
405 deletions
ChangeLog
doc/Makefile.am
doc/address.texi
examples/Addrs.good
examples/addr.c
imap4d/copy.c
imap4d/fetch.c
imap4d/imap4d.c
imap4d/imap4d.h
imap4d/login.c
imap4d/select.c
imap4d/status.c
imap4d/store.c
imap4d/sync.c
imap4d/uid.c
imap4d/util.c
include/mailutils/header.h
include/mailutils/parse822.h
mailbox/attribute.c
mailbox/file_stream.c
mailbox/mailbox.c
mailbox/parse822.c
ChangeLog
View file @
43ba0c6
2001-05-07 Alain Magloire
Now we can have multiple access to the mailbox and the server
will update the mailbox and send the unsollicited responses.
This is implemented in imap4d/sync.c.
* imap4d/copy.c: Move the code into imap4d_copy0() to allow
the use of UID COPY.
(imaprd_copy0): New function.
* imap4d/fetch.c: Define a new structure command for FETCH.
(fetch_getcommand): New function.
(imap4d_fetch0): New function to allow the use of UID COPY.
(fetch_envelope0): New function to permit to reuse the function
in bodystructure.
(fetch_bodystructure): Implemented.
(fetch_bodystructure0): The implementation.
(bodystructure): The helper function for fetch_bodystructure.
* imap4d/imap4d.c (imap4d_mainloop): call imap4d_sync() in the
mainloop. Now use FILE *ifile.
* imap4d/imap4d.h: Update prototypes. Define ERR_NO_MEM and
ERR_NO_OFILE.
* imap4d/select.c (imap4d_select0): Call imap4d_sync() to update.
* imap4d/store.c (ima4d_store): Cal imap4d_sync_flags() to
update the flags in the uid_table.
* imap4d/uid.c: Implemented.
* imap4d/util.c (imap4d_readline): Use fgets() and deal
with literals send from the client.
* imap4d/sync.c: New file.
* include/mailutils/header.c: Added some new headers.
* mailbox/attribute.c (attribute_copy): Do a shalow copy.
* mailbox/file_stream.c: Check if FILE * is null in all functions.
* mailbox/mailbox.c (mailbox_is_updated): Should not return ENOSYS
but rather 1.
2001-05-07 Sam Roberts
* mailbox/parse822.c: Now allow a unix mailbox in an address.
* include/mailutils/parse822.h: Declare the function to parse them.
* doc/address.texi: Document the fact.
* doc/Makefile.am: Automatically build the example code from addr.c.
* examples/addr.c: And update the parser test.
* examples/Addrs.good: Update the parser test.
2001-05-03 Sam Roberts
* mail/mail.c: Typo
...
...
doc/Makefile.am
View file @
43ba0c6
...
...
@@ -23,3 +23,6 @@ EXTRA_DIST = \
url.texi
\
version.texi
ex-address.texi
:
../examples/addr.c
sed -es/
{
/@
{
/g -e s/
}
/@
}
/g <
$<
>
$@
...
...
doc/address.texi
View file @
43ba0c6
@code
{
#
include
<
mailutils
/
mailbox
.
h
>
}
@code
{
#
include
<
mailutils
/
address
.
h
>
}
The
internet
address
format
is
defined
in
RFC
822
.
RFC
822
is
in
the
process
of
being
updated
,
and
will
soon
be
superceeded
by
a
new
RFC
that
makes
some
corrections
and
clarifications
.
References
to
RFC
822
here
apply
equally
to
the
new
RFC
.
The
internet
address
format
is
defined
in
RFC
822
.
RFC
822
has
been
updated
,
and
is
now
superceeded
by
RFC
2822
,
which
makes
some
corrections
and
clarifications
.
References
to
RFC
822
here
apply
equally
to
RFC
2822
.
The
RFC
822
format
is
more
flexible
than
many
people
realize
,
here
is
a
quick
summary
of
the
syntax
this
parser
implements
,
see
...
...
@@ -16,10 +16,15 @@ mailbox = addr-spec ["(" display-name ")"] /
[
display
-
name
]
"<"
[
route
]
addr
-
spec
">"
mailbox
-
list
=
mailbox
[
","
mailbox
-
list
]
group
=
display
-
name
":"
[
mailbox
-
list
]
";"
address
=
mailbox
/
group
address
=
mailbox
/
group
/
unix
-
mbox
address
-
list
=
address
[
","
address
-
list
]
@end
example
unix
-
mbox
is
a
non
-
standard
extention
meant
to
deal
with
the
common
practice
of
using
user
names
as
addresses
in
mail
utilities
.
It
allows
addresses
such
as
"root"
to
be
parsed
correctly
.
These
are
NOT
valid
internet
email
addresses
,
they
must
be
qualified
before
use
.
Several
address
functions
have
a
set
of
common
arguments
with
consistent
semantics
,
these
are
described
here
to
avoid
repetition
.
...
...
@@ -133,7 +138,8 @@ The return value is @code{0} on success and a code number on error conditions:
@deftypefun
int
address_get_email
(
address_t
*
@var
{
addr
},
size_t
@var
{
no
},
char
*
@var
{
buf
},
size_t
@var
{
len
},
size_t
*
@var
{
n
})
Acesses
the
email
addr
-
spec
extracted
while
parsing
the
@var
{
no
}
th
email
address
.
parsing
the
@var
{
no
}
th
email
address
.
This
will
be
@code
{
0
}
length
for
a
unix
-
mbox
.
The
return
value
is
@code
{
0
}
on
success
and
a
code
number
on
error
conditions
:
@table
@code
...
...
@@ -157,7 +163,8 @@ The return value is @code{0} on success and a code number on error conditions:
@deftypefun
int
address_get_domain
(
address_t
*
@var
{
addr
},
size_t
@var
{
no
},
char
*
@var
{
buf
},
size_t
@var
{
len
},
size_t
*
@var
{
n
})
Acesses
the
domain
of
an
email
addr
-
spec
extracted
while
parsing
the
@var
{
no
}
th
email
address
.
parsing
the
@var
{
no
}
th
email
address
.
This
will
be
@code
{
0
}
length
for
a
unix
-
mbox
.
The
return
value
is
@code
{
0
}
on
success
and
a
code
number
on
error
conditions
:
@table
@code
...
...
@@ -223,54 +230,6 @@ The return value is @code{0}.
@section
Example
@example
#include <stdio.h>
#include <mailutils/address.h>
int
main
(
int
argc
,
const
char
*
argv
[])
@{
for
(
argc
=
1
;
argv
[
argc
]
;
argc
++
)
@{
const
char
*
str
=
argv
[
argc
]
;
address_t
address
=
NULL
;
address_create
(
&
address
,
str
)
;
printf
(
"'%s' ->
\n
"
,
str
)
;
@{
size_t
no
=
0
;
size_t
pcount
;
address_get_count
(
address
,
&
pcount
)
;
printf
(
" pcount %d
\n
"
,
pcount
)
;
for
(
no
=
1
;
no
<=
pcount
;
no
++
)
@{
char
buf
[
BUFSIZ
]
;
address_get_personal
(
address
,
no
,
buf
,
sizeof
(
buf
),
0
)
;
printf
(
" personal '%s'
\n
"
,
buf
)
;
address_get_local_part
(
address
,
no
,
buf
,
sizeof
(
buf
),
0
)
;
printf
(
" local_part '%s'
\n
"
,
buf
)
;
address_get_domain
(
address
,
no
,
buf
,
sizeof
(
buf
),
0
)
;
printf
(
" domain '%s'
\n
"
,
buf
)
;
address_get_email
(
address
,
no
,
buf
,
sizeof
(
buf
),
0
)
;
printf
(
" email '%s'
\n
"
,
buf
)
;
@
}
@
}
address_destroy
(
&
address
)
;
@
}
return
0
;
@
}
@include
ex
-
address
.
texi
@end
example
...
...
examples/Addrs.good
View file @
43ba0c6
...
...
@@ -228,7 +228,7 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=)=> pcoun
personal <'sroberts@certicom.ca'>
local-part <sroberts> domain <certicom.ca>
"=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoicees>=> pcount 1
"=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoice
.
es>=> pcount 1
1 email <jcmarcos@datavoice.es>
personal <=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=>
local-part <jcmarcos> domain <datavoice.es>
...
...
@@ -432,17 +432,17 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=)=> pcoun
personal <=?US-ASCII?Q?gary=5Fc?=>
local-part <gary_c> domain <cunningham-lee.com>
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet>=> pcount 1
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus
.
net>=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier>
local-part <0> domain <pervalidus.net>
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet>,=> pcount 1
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus
.
net>,=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier>
local-part <0> domain <pervalidus.net>
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidusnet>=> pcount 1
=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidus
.
net>=> pcount 1
1 email <0@pervalidus.net>
personal <=?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?=>
local-part <0> domain <pervalidus.net>
...
...
@@ -554,14 +554,22 @@ No_Reply-To@mapquest.com=> pcount 1
1 email <No_Reply-To@mapquest.com>
local-part <No_Reply-To> domain <mapquest.com>
OSULLIE@rte.ie, skidswam@hotmail.com, boot=> error ENOENT
OSULLIE@rte.ie, skidswam@hotmail.com, boot=> pcount 3
1 email <OSULLIE@rte.ie>
local-part <OSULLIE> domain <rte.ie>
2 email <skidswam@hotmail.com>
local-part <skidswam> domain <hotmail.com>
3 email <>
local-part <boot>
Paul Hoffman / IMC <phoffman@imc.org>=> pcount 1
1 email <phoffman@imc.org>
personal <Paul Hoffman / IMC>
local-part <phoffman> domain <imc.org>
Sam=> error ENOENT
Sam=> pcount 1
1 email <>
local-part <Sam>
Sam Roberts <sam@cogent.ca>=> pcount 1
1 email <sam@cogent.ca>
...
...
@@ -605,7 +613,9 @@ mcaustin@eudoramail.com, aposner@usaid.gov, Kieran.O'Leary@anpost.ie,=> pcount 3
rfunk@wks.uts.ohio-state.eduofflinemailer-bounce@dikke.penguin.nl=> error ENOENT
root=> error ENOENT
root=> pcount 1
1 email <>
local-part <root>
srr <sam@localhost>=> error ENOENT
...
...
examples/addr.c
View file @
43ba0c6
...
...
@@ -78,11 +78,15 @@ static int parse(const char* str)
address_get_local_part
(
address
,
no
,
buf
,
sizeof
(
buf
),
&
got
);
if
(
got
)
printf
(
" local-part <%s>"
,
buf
);
if
(
got
)
{
printf
(
" local-part <%s>"
,
buf
);
address_get_domain
(
address
,
no
,
buf
,
sizeof
(
buf
),
&
got
);
address_get_domain
(
address
,
no
,
buf
,
sizeof
(
buf
),
&
got
);
if
(
got
)
printf
(
" domain <%s>
\n
"
,
buf
);
if
(
got
)
printf
(
" domain <%s>"
,
buf
);
printf
(
"
\n
"
);
}
address_get_route
(
address
,
no
,
buf
,
sizeof
(
buf
),
&
got
);
...
...
imap4d/copy.c
View file @
43ba0c6
...
...
@@ -21,34 +21,57 @@
* copy messages in argv[2] to mailbox in argv[3]
*/
/* FIXME if the mailbox is the one selecte we should send notif. */
int
imap4d_copy
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
int
rc
;
char
buffer
[
64
];
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
rc
=
imap4d_copy0
(
arg
,
0
,
buffer
,
sizeof
buffer
);
if
(
rc
==
RESP_NONE
)
{
/* Reset the state ourself. */
int
new_state
=
(
rc
==
RESP_OK
)
?
command
->
success
:
command
->
failure
;
if
(
new_state
!=
STATE_NONE
)
state
=
new_state
;
return
util_send
(
"%s %s
\r\n
"
,
command
->
tag
,
buffer
);
}
return
util_finish
(
command
,
rc
,
buffer
);
}
int
imap4d_copy0
(
char
*
arg
,
int
isuid
,
char
*
resp
,
size_t
resplen
)
{
int
status
;
char
*
msgset
;
char
*
name
;
char
*
mailbox_name
;
const
char
*
delim
=
"/"
;
char
*
sp
=
NULL
;
in
t
*
set
=
NULL
;
size_
t
*
set
=
NULL
;
size_t
n
=
0
;
mailbox_t
cmbox
=
NULL
;
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
msgset
=
util_getword
(
arg
,
&
sp
);
name
=
util_getword
(
NULL
,
&
sp
);
util_unquote
(
&
name
);
if
(
!
msgset
||
!
name
||
*
name
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few args"
);
{
snprintf
(
resp
,
resplen
,
"Too few args"
);
return
RESP_BAD
;
}
/* Get the message numbers in set[]. */
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
0
);
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
isuid
);
if
(
status
!=
0
)
return
util_finish
(
command
,
RESP_BAD
,
"Bogus number set"
);
{
snprintf
(
resp
,
resplen
,
"Bogus number set"
);
return
RESP_BAD
;
}
if
(
strcasecmp
(
name
,
"INBOX"
)
==
0
)
{
...
...
@@ -71,7 +94,8 @@ imap4d_copy (struct imap4d_command *command, char *arg)
for
(
i
=
0
;
i
<
n
;
i
++
)
{
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
set
[
i
],
&
msg
);
size_t
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
mailbox_get_message
(
mbox
,
msgno
,
&
msg
);
mailbox_append_message
(
cmbox
,
msg
);
}
mailbox_close
(
cmbox
);
...
...
@@ -82,16 +106,16 @@ imap4d_copy (struct imap4d_command *command, char *arg)
free
(
mailbox_name
);
if
(
status
==
0
)
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
/* Since we do not call util_finish, reset the state ourself. */
if
(
command
->
failure
!=
STATE_NONE
)
state
=
command
->
failure
;
{
snprintf
(
resp
,
resplen
,
"Completed"
);
return
RESP_OK
;
}
/* Unless it is certain that the destination mailbix can not be created,
the server MUST send the response code "[TRYCREATE]" as the prefix
of the text of the tagged NO response. This gives a hint to the
client that it can attempt a CREATE command and retry the copy if
the CREATE is successful. */
return
util_send
(
"%s NO [TRYCREATE] failed
\r\n
"
,
command
->
tag
);
snprintf
(
resp
,
resplen
,
"NO [TRYCREATE] failed"
);
return
RESP_NONE
;
}
...
...
imap4d/fetch.c
View file @
43ba0c6
...
...
@@ -32,176 +32,244 @@
["<" number "." nz_number ">"]
*/
static
int
fetch_all
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_full
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_fast
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_envelope
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_flags
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_internaldate
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_rfc822_header
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_rfc822_size
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_rfc822_text
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_rfc822
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_bodystructure
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_body_peek
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_body
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_uid
__P
((
struct
imap4d_command
*
,
char
*
));
static
int
fetch_operation
__P
((
size_t
,
char
*
,
int
));
static
int
fetch_message
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_content
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_io
__P
((
stream_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header_fields
__P
((
message_t
,
char
*
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header_fields_not
__P
((
message_t
,
char
*
,
unsigned
long
,
unsigned
long
));
static
int
fetch_send_address
__P
((
char
*
));
struct
imap4d_command
fetch_command_table
[]
=
struct
fetch_command
;
static
int
fetch_all
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_full
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_fast
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_envelope
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_envelope0
__P
((
message_t
));
static
int
fetch_flags
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_internaldate
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_rfc822_header
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_rfc822_size
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_rfc822_text
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_rfc822
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_bodystructure
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_bodystructure0
__P
((
message_t
,
int
));
static
int
bodystructure
__P
((
message_t
,
int
));
static
int
fetch_body_peek
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_body
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_uid
__P
((
struct
fetch_command
*
,
char
*
));
static
int
fetch_operation
__P
((
size_t
,
char
*
,
int
));
static
int
fetch_message
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_content
__P
((
message_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_io
__P
((
stream_t
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header_fields
__P
((
message_t
,
char
*
,
unsigned
long
,
unsigned
long
));
static
int
fetch_header_fields_not
__P
((
message_t
,
char
*
,
unsigned
long
,
unsigned
long
));
static
int
fetch_send_address
__P
((
char
*
));
static
struct
fetch_command
*
fetch_getcommand
__P
((
char
*
,
struct
fetch_command
[]));
struct
fetch_command
{
const
char
*
name
;
int
(
*
func
)
__P
((
struct
fetch_command
*
,
char
*
));
size_t
msgno
;
}
fetch_command_table
[]
=
{
#define F_ALL 0
{
"ALL"
,
fetch_all
,
0
,
0
,
0
,
NULL
},
{
"ALL"
,
fetch_all
,
0
},
#define F_FULL 1
{
"FULL"
,
fetch_full
,
0
,
0
,
0
,
NULL
},
{
"FULL"
,
fetch_full
,
0
},
#define F_FAST 2
{
"FAST"
,
fetch_fast
,
0
,
0
,
0
,
NULL
},
{
"FAST"
,
fetch_fast
,
0
},
#define F_ENVELOPE 3
{
"ENVELOPE"
,
fetch_envelope
,
0
,
0
,
0
,
NULL
},
{
"ENVELOPE"
,
fetch_envelope
,
0
},
#define F_FLAGS 4
{
"FLAGS"
,
fetch_flags
,
0
,
0
,
0
,
NULL
},
{
"FLAGS"
,
fetch_flags
,
0
},
#define F_INTERNALDATE 5
{
"INTERNALDATE"
,
fetch_internaldate
,
0
,
0
,
0
,
NULL
},
{
"INTERNALDATE"
,
fetch_internaldate
,
0
},
#define F_RFC822_HEADER 6
{
"RFC822.HEADER"
,
fetch_rfc822_header
,
0
,
0
,
0
,
NULL
},
{
"RFC822.HEADER"
,
fetch_rfc822_header
,
0
},
#define F_RFC822_SIZE 7
{
"RFC822.SIZE"
,
fetch_rfc822_size
,
0
,
0
,
0
,
NULL
},
{
"RFC822.SIZE"
,
fetch_rfc822_size
,
0
},
#define F_RFC822_TEXT 8
{
"RFC822.TEXT"
,
fetch_rfc822_text
,
0
,
0
,
0
,
NULL
},
{
"RFC822.TEXT"
,
fetch_rfc822_text
,
0
},
#define F_RFC822 9
{
"RFC822"
,
fetch_rfc822
,
0
,
0
,
0
,
NULL
},
{
"RFC822"
,
fetch_rfc822
,
0
},
#define F_BODYSTRUCTURE 10
{
"BODYSTRUCTURE"
,
fetch_bodystructure
,
0
,
0
,
0
,
NULL
},
{
"BODYSTRUCTURE"
,
fetch_bodystructure
,
0
},
#define F_BODY_PEEK 11
{
"BODY.PEEK"
,
fetch_body_peek
,
0
,
0
,
0
,
NULL
},
{
"BODY.PEEK"
,
fetch_body_peek
,
0
},
#define F_BODY 12
{
"BODY"
,
fetch_body
,
0
,
0
,
0
,
NULL
},
{
"BODY"
,
fetch_body
,
0
},
#define F_UID 13
{
"UID"
,
fetch_uid
,
0
,
0
,
0
,
NULL
},
{
NULL
,
0
,
0
,
0
,
0
,
NULL
}
{
"UID"
,
fetch_uid
,
0
},
{
NULL
,
0
,
0
}
};
/* NOTE: the state field in the command structure is use as a place
holder for the message number. This save us from redifining another
data structure. */
int
imap4d_fetch
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
char
*
sp
=
NULL
;
char
*
msgset
;
int
*
set
=
NULL
;
int
i
,
n
=
0
;
int
rc
=
RESP_OK
;
int
status
;
const
char
*
errmsg
=
"Completed"
;
struct
imap4d_command
*
fcmd
;
int
rc
;
char
buffer
[
64
];
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
rc
=
imap4d_fetch0
(
arg
,
0
,
buffer
,
sizeof
buffer
);
return
util_finish
(
command
,
rc
,
buffer
);
}
static
struct
fetch_command
*
fetch_getcommand
(
char
*
cmd
,
struct
fetch_command
command_table
[])
{
size_t
i
,
len
=
strlen
(
cmd
);
for
(
i
=
0
;
command_table
[
i
].
name
!=
0
;
i
++
)
{
if
(
strlen
(
command_table
[
i
].
name
)
==
len
&&
!
strcasecmp
(
command_table
[
i
].
name
,
cmd
))
return
&
command_table
[
i
];
}
return
NULL
;
}
int
imap4d_fetch0
(
char
*
arg
,
int
isuid
,
char
*
resp
,
size_t
resplen
)
{
struct
fetch_command
*
fcmd
=
NULL
;
int
rc
=
RESP_NO
;
char
*
sp
=
NULL
;
char
*
msgset
;
size_t
*
set
=
NULL
;
int
n
=
0
;
int
i
;
int
status
;
msgset
=
util_getword
(
arg
,
&
sp
);
if
(
!
msgset
||
!
sp
||
*
sp
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few args"
);
{
snprintf
(
resp
,
resplen
,
"Too few args"
);
return
RESP_BAD
;
}
/* Get the message numbers in set[]. */
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
0
);
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
isuid
);
if
(
status
!=
0
)
return
util_finish
(
command
,
RESP_BAD
,
"Bogus number set"
);
{
snprintf
(
resp
,
resplen
,
"Bogus number set"
);
return
RESP_BAD
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
char
item
[
32
];
char
*
items
=
strdup
(
sp
);
char
*
p
=
items
;
util_send
(
"* FETCH %d ("
,
set
[
i
]);
int
uid_sent
=
!
isuid
;
/* Pretend we sent the uid if via fetch. */
util_send
(
"* %d FETCH ("
,
set
[
i
]);
item
[
0
]
=
'\0'
;
/* Get the fetch command names. */
while
(
*
items
&&
*
items
!=
')'
)
{
util_token
(
item
,
sizeof
(
item
),
&
items
);
if
(
fcmd
)
util_send
(
" "
);
/* Search in the table. */
fcmd
=
util
_getcommand
(
item
,
fetch_command_table
);
fcmd
=
fetch
_getcommand
(
item
,
fetch_command_table
);
if
(
fcmd
)
{
/* We use the states field to hold the msgno/uid. */
fcmd
->
states
=
set
[
i
];
fcmd
->
func
(
fcmd
,
items
);
util_send
(
" "
);
fcmd
->
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
if
(
fcmd
->
msgno
!=
0
)
{
rc
=
fcmd
->
func
(
fcmd
,
items
);
}
}
if
(
!
uid_sent
)
uid_sent
=
((
strstr
(
item
,
"UID"
)
!=
NULL
)
||
(
strstr
(
item
,
"uid"
)
!=
NULL
));
}
/* Always send the UID when fetch was done via the uid command. */
if
(
!
uid_sent
)
{
struct
fetch_command
c_uid
=
fetch_command_table
[
F_UID
];
c_uid
.
msgno
=
set
[
i
];
if
(
fcmd
)
util_send
(
" "
);
rc
=
fetch_uid
(
&
c_uid
,
items
);
}
free
(
p
);
util_send
(
")
\r\n
"
);
}
free
(
set
);
return
util_finish
(
command
,
rc
,
errmsg
);
snprintf
(
resp
,
resplen
,
"Completed"
);
return
rc
;
}
/* Combination of (FAST ENVELOPE). */
/* The Fetch comand retireves data associated with a message in the
mailbox, The data items to be fetched can be either a single atom
or a parenthesized list. */
/* Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE)
or (FAST ENVELOPE) */
static
int
fetch_all
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_all
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
struct
imap4d
_command
c_env
=
fetch_command_table
[
F_ENVELOPE
];
struct
fetch
_command
c_env
=
fetch_command_table
[
F_ENVELOPE
];
fetch_fast
(
command
,
arg
);
util_send
(
" "
);
c_env
.
states
=
command
->
states
;
c_env
.
msgno
=
command
->
msgno
;
fetch_envelope
(
&
c_env
,
arg
);
return
0
;
return
RESP_OK
;
}
/* Combination of (ALL BODY). */
static
int
fetch_full
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_full
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
struct
imap4d
_command
c_body
=
fetch_command_table
[
F_BODY
];
struct
fetch
_command
c_body
=
fetch_command_table
[
F_BODY
];
fetch_all
(
command
,
arg
);
util_send
(
" "
);
c_body
.
states
=
command
->
states
;
c_body
.
msgno
=
command
->
msgno
;
fetch_body
(
&
c_body
,
arg
);
return
0
;
return
RESP_OK
;
}
/* Combination of (FLAGS INTERNALDATE RFC822.SIZE). */
static
int
fetch_fast
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_fast
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
struct
imap4d
_command
c_idate
=
fetch_command_table
[
F_INTERNALDATE
];
struct
imap4d
_command
c_rfc
=
fetch_command_table
[
F_RFC822_SIZE
];
struct
imap4d
_command
c_flags
=
fetch_command_table
[
F_FLAGS
];
c_flags
.
states
=
command
->
states
;
struct
fetch
_command
c_idate
=
fetch_command_table
[
F_INTERNALDATE
];
struct
fetch
_command
c_rfc
=
fetch_command_table
[
F_RFC822_SIZE
];
struct
fetch
_command
c_flags
=
fetch_command_table
[
F_FLAGS
];
c_flags
.
msgno
=
command
->
msgno
;
fetch_flags
(
&
c_flags
,
arg
);
util_send
(
" "
);
c_idate
.
states
=
command
->
states
;
c_idate
.
msgno
=
command
->
msgno
;
fetch_internaldate
(
&
c_idate
,
arg
);
util_send
(
" "
);
c_rfc
.
states
=
command
->
states
;
c_rfc
.
msgno
=
command
->
msgno
;
fetch_rfc822_size
(
&
c_rfc
,
arg
);
return
0
;
return
RESP_OK
;
}
/* Header: Date, Subject, From, Sender, Reply-To, To, Cc, Bcc, In-Reply-To,
and Message-Id. */
static
int
fetch_envelope
(
struct
fetch_command
*
command
,
char
*
arg
)
{
message_t
msg
=
NULL
;
int
status
;
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
util_send
(
"%s ("
,
command
->
name
);
status
=
fetch_envelope0
(
msg
);
util_send
(
")"
);
return
status
;
}
/* FIXME: - strings change to literals when detecting '"' */
static
int
fetch_envelope
(
struct
imap4d_command
*
command
,
char
*
ar
g
)
fetch_envelope
0
(
message_t
ms
g
)
{
char
*
buffer
;
char
*
from
;
char
*
buffer
=
NULL
;
char
*
from
=
NULL
;
header_t
header
=
NULL
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
message_get_header
(
msg
,
&
header
);
util_send
(
"%s("
,
command
->
name
);
/* FIXME: Incorrect Date. */
header_aget_value
(
header
,
"Date"
,
&
buffer
);
...
...
@@ -266,18 +334,18 @@ fetch_envelope (struct imap4d_command *command, char *arg)
free
(
buffer
);
free
(
from
);
util_send
(
")"
);
return
0
;
return
RESP_OK
;
}
/* The flags that are set for this message. */
/* FIXME: User flags not done. */
static
int
fetch_flags
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_flags
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
attribute_t
attr
=
NULL
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
(
void
)
arg
;
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
util_send
(
"%s ("
,
command
->
name
);
if
(
attribute_is_deleted
(
attr
))
...
...
@@ -286,23 +354,23 @@ fetch_flags (struct imap4d_command *command, char *arg)
util_send
(
"
\\
Answered"
);
if
(
attribute_is_flagged
(
attr
))
util_send
(
"
\\
Flagged"
);
if
(
attribute_is_seen
(
attr
))
if
(
attribute_is_seen
(
attr
)
&&
attribute_is_read
(
attr
)
)
util_send
(
"
\\
Seen"
);
if
(
attribute_is_draft
(
attr
))
util_send
(
"
\\
Draft"
);
util_send
(
" )"
);
return
0
;
return
RESP_OK
;
}
/* The internal date of the message. */
/* FIXME: Wrong format? */
static
int
fetch_internaldate
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_internaldate
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
char
date
[
512
];
envelope_t
env
=
NULL
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_envelope
(
msg
,
&
env
);
date
[
0
]
=
'\0'
;
envelope_date
(
env
,
date
,
sizeof
(
date
),
NULL
);
...
...
@@ -310,76 +378,80 @@ fetch_internaldate (struct imap4d_command *command, char *arg)
if
(
date
[
strlen
(
date
)
-
1
]
==
'\n'
)
date
[
strlen
(
date
)
-
1
]
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
date
);
return
0
;
return
RESP_OK
;
}
/* Equivalent to BODY.PEEK[HEADER]. */
static
int
fetch_rfc822_header
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_rfc822_header
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
char
buffer
[
16
];
(
void
)
arg
;
util_send
(
"%s "
,
command
->
name
);
strcpy
(
buffer
,
"[HEADER]"
);
fetch_operation
(
command
->
states
,
buffer
,
1
);
return
0
;
fetch_operation
(
command
->
msgno
,
buffer
,
1
);
return
RESP_OK
;
}
/* Equivalent to BODY[TEXT]. */
/* FIXME: send a Fetch flag if the mail was not set seen ? */
static
int
fetch_rfc822_text
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_rfc822_text
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
char
buffer
[
16
];
attribute_t
attr
=
NULL
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
(
void
)
arg
;
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
attribute_set_read
(
attr
);
if
(
!
attribute_is_seen
(
attr
)
&&
!
attribute_is_read
(
attr
))
{
util_send
(
"FLAGS (
\\
Seen) "
);
attribute_set_seen
(
attr
);
attribute_set_read
(
attr
);
}
util_send
(
"%s "
,
command
->
name
);
strcpy
(
buffer
,
"[TEXT]"
);
fetch_operation
(
command
->
states
,
buffer
,
1
);
return
0
;
fetch_operation
(
command
->
msgno
,
buffer
,
1
);
return
RESP_OK
;
}
/* The [RFC-822] size of the message. */
static
int
fetch_rfc822_size
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_rfc822_size
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
size_t
size
=
0
;
size_t
lines
=
0
;
message_t
msg
=
NULL
;
(
void
)
arg
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_size
(
msg
,
&
size
);
message_lines
(
msg
,
&
lines
);
util_send
(
"%s %u"
,
command
->
name
,
size
+
lines
);
return
0
;
return
RESP_OK
;
}
/* Equivalent to BODY[]. */
/* FIXME: send a Fetch flag if the mail was not set seen ? */
static
int
fetch_rfc822
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_rfc822
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
if
(
*
arg
==
'.'
)
{
if
(
strncasecmp
(
arg
,
".SIZE"
,
5
)
==
0
)
{
struct
imap4d
_command
c_rfc
=
fetch_command_table
[
F_RFC822_SIZE
];
c_rfc
.
states
=
command
->
states
;
struct
fetch
_command
c_rfc
=
fetch_command_table
[
F_RFC822_SIZE
];
c_rfc
.
msgno
=
command
->
msgno
;
fetch_rfc822_size
(
&
c_rfc
,
arg
);
}
else
if
(
strncasecmp
(
arg
,
".TEXT"
,
5
)
==
0
)
{
struct
imap4d
_command
c_rfc
=
fetch_command_table
[
F_RFC822_TEXT
];
c_rfc
.
states
=
command
->
states
;
struct
fetch
_command
c_rfc
=
fetch_command_table
[
F_RFC822_TEXT
];
c_rfc
.
msgno
=
command
->
msgno
;
fetch_rfc822_text
(
&
c_rfc
,
arg
);
}
else
if
(
strncasecmp
(
arg
,
".HEADER"
,
7
)
==
0
)
{
struct
imap4d
_command
c_rfc
=
fetch_command_table
[
F_RFC822_HEADER
];
c_rfc
.
states
=
command
->
states
;
struct
fetch
_command
c_rfc
=
fetch_command_table
[
F_RFC822_HEADER
];
c_rfc
.
msgno
=
command
->
msgno
;
fetch_rfc822_header
(
&
c_rfc
,
arg
);
}
}
...
...
@@ -388,51 +460,294 @@ fetch_rfc822 (struct imap4d_command *command, char *arg)
char
buffer
[
16
];
attribute_t
attr
=
NULL
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
attribute_set_read
(
attr
);
if
(
!
attribute_is_seen
(
attr
)
&&
!
attribute_is_read
(
attr
))
{
util_send
(
"FLAGS (
\\
Seen) "
);
attribute_set_seen
(
attr
);
attribute_set_read
(
attr
);
}
util_send
(
"%s "
,
command
->
name
);
strcpy
(
buffer
,
"[]"
);
fetch_operation
(
command
->
states
,
buffer
,
1
);
fetch_operation
(
command
->
msgno
,
buffer
,
1
);
}
return
0
;
return
RESP_OK
;
}
/* The unique identifier for the message. */
static
int
fetch_uid
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_uid
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
size_t
uid
=
0
;
message_t
msg
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
(
void
)
arg
;
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_uid
(
msg
,
&
uid
);
util_send
(
"%s %d"
,
command
->
name
,
uid
);
return
0
;
return
RESP_OK
;
}
/* FIXME: not implemeted. */
static
int
fetch_bodystructure
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_bodystructure
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
util_send
(
"%s ()"
,
command
->
name
);
return
0
;
message_t
message
=
NULL
;
(
void
)
arg
;
util_send
(
"%s ("
,
command
->
name
);
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
message
);
fetch_bodystructure0
(
message
,
1
);
util_send
(
")"
);
return
RESP_OK
;
}
static
int
fetch_bodystructure0
(
message_t
message
,
int
extension
)
{
size_t
nparts
=
1
;
size_t
i
;
int
is_multipart
=
0
;
message_is_multipart
(
message
,
&
is_multipart
);
if
(
is_multipart
)
{
message_get_num_parts
(
message
,
&
nparts
);
for
(
i
=
1
;
i
<=
nparts
;
i
++
)
{
message_t
msg
=
NULL
;
message_get_part
(
message
,
i
,
&
msg
);
util_send
(
"("
);
fetch_bodystructure0
(
msg
,
extension
);
util_send
(
")"
);
}
/* for () */
/* The extension data for multipart. */
if
(
extension
)
{
header_t
header
=
NULL
;
char
*
buffer
=
NULL
;
char
*
sp
=
NULL
;
char
*
s
;
/* The subtype. */
message_get_header
(
message
,
&
header
);
header_aget_value
(
header
,
MU_HEADER_CONTENT_TYPE
,
&
buffer
);
s
=
strtok_r
(
buffer
,
"
\t\r\n
;"
,
&
sp
);
s
=
strchr
(
buffer
,
'/'
);
if
(
s
)
{
s
++
;
util_send
(
"
\"
%s
\"
"
,
s
);
}
else
util_send
(
" NIL"
);
/* Content-type parameter list. */
util_send
(
" ("
);
{
while
((
s
=
strtok_r
(
NULL
,
"
\t\r\n
;"
,
&
sp
)))
{
char
*
p
=
strchr
(
s
,
'='
);
if
(
p
)
*
p
++
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
s
);
util_send
(
"
\"
%s
\"
"
,
(
p
)
?
p
:
"NIL"
);
}
}
free
(
buffer
);
/* Content-Disposition. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_DISPOSITION
,
&
buffer
);
if
(
*
buffer
)
{
util_send
(
" ("
);
while
((
s
=
strtok_r
(
buffer
,
"
\t\r\n
;"
,
&
sp
)))
{
char
*
p
=
strchr
(
s
,
'='
);
if
(
p
)
*
p
++
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
s
);
util_send
(
"
\"
%s
\"
"
,
(
p
)
?
p
:
"NIL"
);
}
}
else
util_send
(
" NIL"
);
free
(
buffer
);
/* Content-Language. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_LANGUAGE
,
&
buffer
);
if
(
*
buffer
)
util_send
(
"
\"
%s
\"
"
,
buffer
);
else
util_send
(
" NIL"
);
}
/* extension */
}
else
bodystructure
(
message
,
extension
);
return
RESP_OK
;
}
static
int
bodystructure
(
message_t
msg
,
int
extension
)
{
header_t
header
=
NULL
;
char
*
sp
=
NULL
;
char
*
buffer
=
NULL
;
char
*
s
;
size_t
blines
=
0
;
int
message_rfc822
=
0
;
int
text_plain
=
0
;
message_get_header
(
msg
,
&
header
);
/* MIME: */
header_aget_value
(
header
,
MU_HEADER_CONTENT_TYPE
,
&
buffer
);
s
=
strtok_r
(
buffer
,
"
\t\r\n
;"
,
&
sp
);
/* MIME media type and subtype */
if
(
s
)
{
char
*
p
=
strchr
(
s
,
'/'
);
if
(
strcasecmp
(
s
,
"MESSAGE/RFC822"
)
==
0
)
message_rfc822
=
1
;
if
(
strcasecmp
(
s
,
"TEXT/PLAIN"
)
==
0
)
text_plain
=
1
;
if
(
p
)
*
p
++
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
s
);
util_send
(
"
\"
%s
\"
"
,
(
p
)
?
p
:
"NIL"
);
}
else
{
/* Default? */
util_send
(
"TEXT"
);
util_send
(
" PLAIN"
);
}
/* Content-type parameter list. */
util_send
(
" ("
);
{
int
have_charset
=
0
;
while
((
s
=
strtok_r
(
NULL
,
"
\t\r\n
;"
,
&
sp
)))
{
char
*
p
=
strchr
(
s
,
'='
);
if
(
p
)
*
p
++
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
s
);
util_send
(
"
\"
%s
\"
"
,
(
p
)
?
p
:
"NIL"
);
if
(
strcasecmp
(
s
,
"charset"
)
==
0
)
have_charset
=
1
;
}
/* Default. */
if
(
!
have_charset
)
{
util_send
(
"
\"
CHARSET
\"
"
);
util_send
(
"
\"
US-ASCII
\"
"
);
}
}
util_send
(
")"
);
free
(
buffer
);
/* Content-ID. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_ID
,
&
buffer
);
if
(
*
buffer
)
util_send
(
"
\"
%s
\"
"
,
buffer
);
else
util_send
(
" NIL"
);
free
(
buffer
);
/* Content-Description. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_DESCRIPTION
,
&
buffer
);
if
(
*
buffer
)
util_send
(
"
\"
%s
\"
"
,
buffer
);
else
util_send
(
" NIL"
);
free
(
buffer
);
/* Content-Transfer-Encoding. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_TRANSFER_ENCODING
,
&
buffer
);
util_send
(
"
\"
%s
\"
"
,
(
*
buffer
)
?
buffer
:
"7bit"
);
free
(
buffer
);
/* Body size RFC822 format. */
{
size_t
size
=
0
;
body_t
body
=
NULL
;
message_get_body
(
msg
,
&
body
);
body_size
(
body
,
&
size
);
body_lines
(
body
,
&
blines
);
util_send
(
" %d"
,
size
+
blines
);
}
/* If the mime type was text. */
if
(
text_plain
)
{
/* Add the line number of the body. */
util_send
(
" %d"
,
blines
);
}
else
if
(
message_rfc822
)
{
size_t
lines
=
0
;
/* Add envelope structure */
util_send
(
"("
);
fetch_envelope0
(
msg
);
util_send
(
")"
);
/* Add body structure */
util_send
(
"("
);
bodystructure
(
msg
,
1
);
util_send
(
")"
);
/* size in text lines of the encapsulated message. */
message_lines
(
msg
,
&
lines
);
util_send
(
" %d"
,
lines
);
}
if
(
extension
)
{
/* Content-MD5. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_MD5
,
&
buffer
);
if
(
*
buffer
)
util_send
(
"
\"
%s
\"
"
,
buffer
);
else
util_send
(
" NIL"
);
free
(
buffer
);
/* Content-Disposition. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_DISPOSITION
,
&
buffer
);
if
(
*
buffer
)
{
util_send
(
" ("
);
while
((
s
=
strtok_r
(
buffer
,
"
\t\r\n
;"
,
&
sp
)))
{
char
*
p
=
strchr
(
s
,
'='
);
if
(
p
)
*
p
++
=
'\0'
;
util_send
(
"
\"
%s
\"
"
,
s
);
util_send
(
"
\"
%s
\"
"
,
(
p
)
?
p
:
"NIL"
);
}
}
else
util_send
(
" NIL"
);
free
(
buffer
);
/* Content-Language. */
header_aget_value
(
header
,
MU_HEADER_CONTENT_LANGUAGE
,
&
buffer
);
if
(
*
buffer
)
util_send
(
"
\"
%s
\"
"
,
buffer
);
else
util_send
(
" NIL"
);
free
(
buffer
);
}
return
RESP_OK
;
}
/* An alternate form of BODY that does not implicitly set the \Seen flag. */
/* FIXME: send notificaton if seen attribute is set? */
static
int
fetch_body
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_body
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
struct
imap4d
_command
c_body_p
=
fetch_command_table
[
F_BODY_PEEK
];
c_body_p
.
states
=
command
->
states
;
struct
fetch
_command
c_body_p
=
fetch_command_table
[
F_BODY_PEEK
];
c_body_p
.
msgno
=
command
->
msgno
;
/* It's BODY set the message as seen */
if
(
*
arg
==
'['
)
{
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
states
,
&
msg
);
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
attribute_set_seen
(
attr
);
if
(
!
attribute_is_seen
(
attr
)
&&
!
attribute_is_read
(
attr
))
{
util_send
(
"FLAGS (
\\
Seen) "
);
attribute_set_seen
(
attr
);
attribute_set_read
(
attr
);
}
}
else
if
(
strncasecmp
(
arg
,
".PEEK"
,
5
)
==
0
)
{
...
...
@@ -443,22 +758,23 @@ fetch_body (struct imap4d_command *command, char *arg)
}
else
if
(
*
arg
!=
'['
&&
*
arg
!=
'.'
)
{
struct
imap4d_command
c_bs
=
fetch_command_table
[
F_BODYSTRUCTURE
];
c_bs
.
states
=
command
->
states
;
/* FIXME: Call body structure without the extension. */
/* return fetch_bodystructure (&c_bs, arg); */
util_send
(
" ()"
);
return
0
;
message_t
message
=
NULL
;
mailbox_get_message
(
mbox
,
command
->
msgno
,
&
message
);
/* Call body structure without the extension. */
util_send
(
"%s ("
,
command
->
name
);
fetch_bodystructure0
(
message
,
0
);
util_send
(
")"
);
return
RESP_OK
;
}
return
fetch_body_peek
(
&
c_body_p
,
arg
);
}
static
int
fetch_body_peek
(
struct
imap4d
_command
*
command
,
char
*
arg
)
fetch_body_peek
(
struct
fetch
_command
*
command
,
char
*
arg
)
{
util_send
(
"%s "
,
command
->
name
);
fetch_operation
(
command
->
states
,
arg
,
0
);
return
0
;
fetch_operation
(
command
->
msgno
,
arg
,
0
);
return
RESP_OK
;
}
static
int
...
...
@@ -498,7 +814,7 @@ fetch_operation (size_t msgno, char *arg, int silent)
if
(
status
!=
0
)
{
util_send
(
"
\"\"
"
);
return
0
;
return
RESP_OK
;
}
}
...
...
@@ -537,7 +853,7 @@ fetch_operation (size_t msgno, char *arg, int silent)
}
else
util_send
(
"
\"\"
"
);
return
0
;
return
RESP_OK
;
}
static
int
...
...
@@ -595,7 +911,7 @@ fetch_io (stream_t stream, unsigned long start, unsigned long end)
if
(
start
==
ULONG_MAX
)
{
start
=
0
;
util_send
(
"{%u}
\r\n
"
,
end
);
util_send
(
"
{%u}
\r\n
"
,
end
);
}
else
util_send
(
"<%lu> {%u}
\r\n
"
,
start
,
end
);
...
...
@@ -613,7 +929,7 @@ fetch_io (stream_t stream, unsigned long start, unsigned long end)
}
util_send
(
"%s"
,
buffer
);
}
return
0
;
return
RESP_OK
;
}
static
int
...
...
@@ -630,7 +946,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
status
=
memory_stream_create
(
&
stream
);
if
(
status
!=
0
)
util_quit
(
1
);
/* FIXME: ENOMEM, send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
/* Save the fields in an array. */
{
...
...
@@ -641,7 +957,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
{
array
=
realloc
(
array
,
(
array_len
+
1
)
*
sizeof
(
*
array
));
if
(
!
array
)
util_quit
(
1
);
/* FIXME: ENOMEM, send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
array
[
array_len
]
=
field
;
}
}
...
...
@@ -668,7 +984,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
if
(
status
!=
0
)
{
free
(
array
);
util_quit
(
1
);
/* FIXME: send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
}
}
}
...
...
@@ -694,7 +1010,7 @@ fetch_header_fields (message_t msg, char *arg, unsigned long start,
fetch_io
(
stream
,
start
,
end
);
if
(
array
)
free
(
array
);
return
0
;
return
RESP_OK
;
}
static
int
...
...
@@ -711,7 +1027,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
status
=
memory_stream_create
(
&
stream
);
if
(
status
)
util_quit
(
1
);
/* FIXME: ENOMEM, send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
/* Save the field we want to ignore. */
{
...
...
@@ -722,7 +1038,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
{
array
=
realloc
(
array
,
(
array_len
+
1
)
*
sizeof
(
*
array
));
if
(
!
array
)
util_quit
(
1
);
/* FIXME: ENOMEM, send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
array
[
array_len
]
=
field
;
}
}
...
...
@@ -777,7 +1093,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
if
(
status
!=
0
)
{
free
(
array
);
util_quit
(
1
);
/* FIXME: send a "* BYE" to the client. */
util_quit
(
ERR_NO_MEM
);
}
}
}
...
...
@@ -802,7 +1118,7 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
fetch_io
(
stream
,
start
,
end
);
if
(
array
)
free
(
array
);
return
0
;
return
RESP_OK
;
}
/* FIXME: The address is limit by a buffer of 128, no good. We should
...
...
@@ -816,7 +1132,7 @@ fetch_send_address (char *addr)
if
(
*
addr
==
'\0'
)
{
util_send
(
"NIL"
);
return
0
;
return
RESP_OK
;
}
address_create
(
&
address
,
addr
);
...
...
@@ -874,5 +1190,5 @@ fetch_send_address (char *addr)
util_send
(
")"
);
}
util_send
(
")"
);
return
0
;
return
RESP_OK
;
}
...
...
imap4d/imap4d.c
View file @
43ba0c6
...
...
@@ -17,14 +17,13 @@
#include "imap4d.h"
int
*
ifile
;
FILE
*
ofile
;
unsigned
int
timeout
=
1800
;
/* RFC2060: 30 minutes, if enable. */
mailbox_t
mbox
;
char
*
homedir
;
int
state
=
STATE_NONAUTH
;
static
int
imap4_mainloop
__P
((
int
,
int
));
static
int
imap4
d
_mainloop
__P
((
int
,
int
));
int
main
(
int
argc
,
char
**
argv
)
...
...
@@ -39,18 +38,19 @@ main (int argc, char **argv)
list_append
(
bookie
,
path_record
);
}
/* FIXME: Incomplete, make it work for standalone, see pop3d. */
imap4_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
imap4
d
_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
return
0
;
}
static
int
imap4_mainloop
(
int
infile
,
int
outfile
)
imap4
d
_mainloop
(
int
infile
,
int
outfile
)
{
const
char
*
remote_host
=
""
;
FILE
*
ifile
;
ifile
=
fdopen
(
infile
,
"r"
);
ofile
=
fdopen
(
outfile
,
"w"
);
if
(
ofile
==
NULL
)
util_quit
(
1
);
if
(
!
ofile
||
!
ifile
)
util_quit
(
ERR_NO_OFILE
);
/* FIXME: Retreive hostname with getpeername() and log. */
syslog
(
LOG_INFO
,
"Incoming connection from %s"
,
remote_host
);
...
...
@@ -61,9 +61,11 @@ imap4_mainloop (int infile, int outfile)
while
(
1
)
{
char
*
cmd
=
imap4d_readline
(
i
n
file
);
char
*
cmd
=
imap4d_readline
(
ifile
);
/* check for updates */
imap4d_sync
();
util_do_command
(
cmd
);
imap4d_sync
();
free
(
cmd
);
fflush
(
ofile
);
}
...
...
imap4d/imap4d.h
View file @
43ba0c6
...
...
@@ -99,12 +99,17 @@ struct imap4d_command
#define STATE_ALL (STATE_NONE | STATE_NONAUTH | STATE_AUTH | STATE_SEL \
| STATE_LOGOUT)
/* Response code. */
#define RESP_OK 0
#define RESP_BAD 1
#define RESP_NO 2
#define RESP_BYE 3
#define RESP_NONE 4
/* Error values. */
#define ERR_NO_MEM 1
#define ERR_NO_OFILE 2
extern
struct
imap4d_command
imap4d_command_table
[];
extern
FILE
*
ofile
;
extern
unsigned
int
timeout
;
...
...
@@ -135,10 +140,18 @@ extern int imap4d_close __P ((struct imap4d_command *, char *));
extern
int
imap4d_expunge
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_search
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_fetch
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_fetch0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_store
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_store0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_copy
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_copy0
__P
((
char
*
,
int
,
char
*
,
size_t
));
extern
int
imap4d_uid
__P
((
struct
imap4d_command
*
,
char
*
));
/* Synchronisation on simultenous access. */
extern
int
imap4d_sync
__P
((
void
));
extern
int
imap4d_sync_flags
__P
((
size_t
));
extern
size_t
uid_to_msgno
__P
((
size_t
));
/* Helper functions. */
extern
int
util_out
__P
((
int
,
const
char
*
,
...));
extern
int
util_send
__P
((
const
char
*
,
...));
...
...
@@ -146,14 +159,14 @@ extern int util_start __P ((char *));
extern
int
util_finish
__P
((
struct
imap4d_command
*
,
int
,
const
char
*
,
...));
extern
int
util_getstate
__P
((
void
));
extern
int
util_do_command
__P
((
char
*
));
extern
char
*
imap4d_readline
__P
((
int
));
extern
char
*
imap4d_readline
__P
((
FILE
*
));
extern
void
util_quit
__P
((
int
));
extern
char
*
util_getword
__P
((
char
*
,
char
**
));
extern
int
util_token
__P
((
char
*
,
size_t
,
char
**
));
extern
void
util_unquote
__P
((
char
**
));
extern
char
*
util_tilde_expansion
__P
((
const
char
*
,
const
char
*
));
extern
char
*
util_getfullpath
__P
((
char
*
,
const
char
*
));
extern
int
util_msgset
__P
((
char
*
,
in
t
**
,
int
*
,
int
));
extern
int
util_msgset
__P
((
char
*
,
size_
t
**
,
int
*
,
int
));
extern
int
util_upper
__P
((
char
*
));
extern
struct
imap4d_command
*
util_getcommand
__P
((
char
*
,
struct
imap4d_command
[]));
...
...
imap4d/login.c
View file @
43ba0c6
...
...
@@ -97,6 +97,7 @@ imap4d_login (struct imap4d_command *command, char *arg)
return
util_finish
(
command
,
RESP_NO
,
"Too many args"
);
pw
=
getpwnam
(
arg
);
#ifndef USE_LIBPAM
if
(
pw
==
NULL
||
pw
->
pw_uid
<
1
)
return
util_finish
(
command
,
RESP_NO
,
"User name or passwd rejected"
);
...
...
@@ -105,7 +106,7 @@ imap4d_login (struct imap4d_command *command, char *arg)
#ifdef HAVE_SHADOW_H
struct
spwd
*
spw
;
spw
=
getspnam
(
arg
);
if
(
spw
==
NULL
||
strcmp
(
spw
->
sp_pwdp
,
crypt
(
pass
,
spw
->
sp_pwdp
)))
if
(
spw
==
NULL
||
strcmp
(
spw
->
sp_pwdp
,
(
char
*
)
crypt
(
pass
,
spw
->
sp_pwdp
)))
#endif
/* HAVE_SHADOW_H */
return
util_finish
(
command
,
RESP_NO
,
"User name or passwd rejected"
);
}
...
...
imap4d/select.c
View file @
43ba0c6
...
...
@@ -50,6 +50,8 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
{
mailbox_close
(
mbox
);
mailbox_destroy
(
&
mbox
);
/* Destroy the old uid table. */
imap4d_sync
();
}
if
(
strcasecmp
(
mailbox_name
,
"INBOX"
)
==
0
)
...
...
@@ -63,7 +65,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
&&
mailbox_open
(
mbox
,
flags
)
==
0
)
{
const
char
*
mflags
=
"
\\
Answered
\\
Flagged
\\
Deleted
\\
Seen
\\
Draft"
;
const
char
*
pflags
=
"
\\
Answered
\\
Flagged
\\
Deleted
\\
Seen
\\
Draft
"
;
const
char
*
pflags
=
"
\\
Answered
\\
Deleted
\\
Seen
"
;
unsigned
long
uidvalidity
=
0
;
size_t
count
=
0
,
recent
=
0
,
unseen
=
0
,
uidnext
=
0
;
...
...
@@ -83,10 +85,13 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
/* FIXME:
- '\*' can be supported if we use the attribute_set userflag()
- Answered is still not set in the mailbox code. */
util_out
(
RESP_OK
,
"[PERMANENTFLAGS (%s)] Permanent flags"
,
pflags
);
if
(
flags
==
MU_STREAM_READ
)
util_out
(
RESP_OK
,
"[PERMANENTFLAGS ()] No Permanent flags"
);
else
util_out
(
RESP_OK
,
"[PERMANENTFLAGS (%s)] Permanent flags"
,
pflags
);
/* Need to set the state explicitely for select. */
state
=
STATE_SEL
;
return
util_send
(
"%s OK [%s] %s Complete
\r\n
"
,
command
->
tag
,
return
util_send
(
"%s OK [%s] %s Complete
d
\r\n
"
,
command
->
tag
,
(
MU_STREAM_READ
==
flags
)
?
"READ-ONLY"
:
"READ-WRITE"
,
command
->
name
);
}
...
...
imap4d/status.c
View file @
43ba0c6
...
...
@@ -144,7 +144,7 @@ status_unseen (mailbox_t smbox)
attribute_t
attr
=
NULL
;
mailbox_get_message
(
smbox
,
i
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
if
(
!
attribute_is_seen
(
attr
))
if
(
!
attribute_is_seen
(
attr
)
&&
!
attribute_is_read
(
attr
)
)
unseen
++
;
}
util_send
(
"UNSEEN %d"
,
unseen
);
...
...
imap4d/store.c
View file @
43ba0c6
...
...
@@ -25,23 +25,36 @@ static int get_attribute_type __P ((const char *, int *));
int
imap4d_store
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
int
rc
;
char
buffer
[
64
];
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
rc
=
imap4d_store0
(
arg
,
0
,
buffer
,
sizeof
buffer
);
return
util_finish
(
command
,
rc
,
buffer
);
}
int
imap4d_store0
(
char
*
arg
,
int
isuid
,
char
*
resp
,
size_t
resplen
)
{
char
*
msgset
;
char
*
data
;
char
*
sp
=
NULL
;
int
status
;
int
ack
=
0
;
size_t
i
,
n
=
0
;
in
t
*
set
=
NULL
;
size_
t
*
set
=
NULL
;
enum
value_type
{
STORE_SET
,
STORE_ADD
,
STORE_UNSET
}
how
;
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
msgset
=
util_getword
(
arg
,
&
sp
);
data
=
util_getword
(
NULL
,
&
sp
);
if
(
!
msgset
||
!
data
||
!
sp
||
*
sp
==
'\0'
)
return
util_finish
(
command
,
RESP_BAD
,
"Too few args"
);
{
snprintf
(
resp
,
resplen
,
"Too few args"
);
return
RESP_BAD
;
}
/* The parsing of the data-item is a little slugish. */
if
(
strcasecmp
(
data
,
"FLAGS"
)
==
0
)
...
...
@@ -75,12 +88,18 @@ imap4d_store (struct imap4d_command *command, char *arg)
how
=
STORE_UNSET
;
}
else
return
util_finish
(
command
,
RESP_BAD
,
"Bogus data item"
);
{
snprintf
(
resp
,
resplen
,
"Bogus data item"
);
return
RESP_BAD
;
}
/* Get the message numbers in set[]. */
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
0
);
status
=
util_msgset
(
msgset
,
&
set
,
&
n
,
isuid
);
if
(
status
!=
0
)
return
util_finish
(
command
,
RESP_BAD
,
"Bogus number set"
);
{
snprintf
(
resp
,
resplen
,
"Bogus number set"
);
return
RESP_BAD
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
...
...
@@ -89,8 +108,10 @@ imap4d_store (struct imap4d_command *command, char *arg)
char
*
items
=
strdup
(
sp
);
/* Don't use the orignal list. */
char
*
flags
=
strdup
(
""
);
int
first
=
1
;
size_t
msgno
;
mailbox_get_message
(
mbox
,
set
[
i
],
&
msg
);
msgno
=
(
isuid
)
?
uid_to_msgno
(
set
[
i
])
:
set
[
i
];
mailbox_get_message
(
mbox
,
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
/* Get the fetch command names. */
...
...
@@ -124,9 +145,12 @@ imap4d_store (struct imap4d_command *command, char *arg)
util_out
(
RESP_NONE
,
"%d FETCH FLAGS (%s)"
,
set
[
i
],
flags
);
free
(
items
);
free
(
flags
);
/* Update the flags of uid table. */
imap4d_sync_flags
(
set
[
i
]);
}
free
(
set
);
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
snprintf
(
resp
,
resplen
,
"Completed"
);
return
RESP_OK
;
}
static
int
...
...
imap4d/sync.c
0 → 100644
View file @
43ba0c6
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2001 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. */
#include "imap4d.h"
/*
*/
struct
_uid_table
{
size_t
uid
;
size_t
msgno
;
int
notify
;
attribute_t
attr
;
};
static
struct
_uid_table
*
uid_table
;
static
size_t
uid_table_count
;
static
void
add_flag
(
char
**
pbuf
,
const
char
*
f
)
{
char
*
abuf
=
*
pbuf
;
abuf
=
realloc
(
abuf
,
strlen
(
abuf
)
+
strlen
(
f
)
+
2
);
if
(
abuf
==
NULL
)
util_quit
(
ERR_NO_MEM
);
if
(
*
abuf
)
strcat
(
abuf
,
" "
);
strcat
(
abuf
,
"
\\
Seen"
);
*
pbuf
=
abuf
;
}
static
void
notify_flag
(
size_t
msgno
,
attribute_t
oattr
)
{
message_t
msg
=
NULL
;
attribute_t
nattr
=
NULL
;
int
status
;
mailbox_get_message
(
mbox
,
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
nattr
);
status
=
attribute_is_equal
(
oattr
,
nattr
);
//if (!attribute_is_equal (oattr, nattr))
if
(
status
==
0
)
{
char
*
abuf
=
malloc
(
1
);;
if
(
!
abuf
)
util_quit
(
ERR_NO_MEM
);
*
abuf
=
'\0'
;
if
(
attribute_is_seen
(
nattr
)
&&
attribute_is_read
(
nattr
))
if
(
!
attribute_is_seen
(
oattr
)
&&
!
attribute_is_read
(
oattr
))
{
attribute_set_seen
(
oattr
);
attribute_set_read
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Seen"
);
}
if
(
attribute_is_answered
(
nattr
))
if
(
!
attribute_is_answered
(
oattr
))
{
attribute_set_answered
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Answered"
);
}
if
(
attribute_is_flagged
(
nattr
))
if
(
!
attribute_is_flagged
(
oattr
))
{
attribute_set_flagged
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Flagged"
);
}
if
(
attribute_is_deleted
(
nattr
))
if
(
!
attribute_is_deleted
(
oattr
))
{
attribute_set_deleted
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Deleted"
);
}
if
(
attribute_is_draft
(
nattr
))
if
(
!
attribute_is_draft
(
oattr
))
{
attribute_set_draft
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Draft"
);
}
if
(
attribute_is_recent
(
nattr
))
if
(
!
attribute_is_recent
(
oattr
))
{
attribute_set_recent
(
oattr
);
add_flag
(
&
abuf
,
"
\\
Recent"
);
}
if
(
*
abuf
)
util_out
(
RESP_NONE
,
"%d FETCH FLAGS (%s)"
,
msgno
,
abuf
);
free
(
abuf
);
}
}
static
void
notify_deleted
(
void
)
{
if
(
uid_table
)
{
size_t
i
;
for
(
i
=
0
;
i
<
uid_table_count
;
i
++
)
{
if
(
!
(
uid_table
[
i
].
notify
))
{
util_out
(
RESP_NONE
,
"%d EXPUNGE"
,
uid_table
[
i
].
msgno
);
uid_table
[
i
].
notify
=
1
;
}
}
}
}
static
int
notify_uid
(
size_t
uid
)
{
if
(
uid_table
)
{
size_t
i
;
for
(
i
=
0
;
i
<
uid_table_count
;
i
++
)
{
if
(
uid_table
[
i
].
uid
==
uid
)
{
notify_flag
(
uid_table
[
i
].
msgno
,
uid_table
[
i
].
attr
);
uid_table
[
i
].
notify
=
1
;
return
1
;
}
}
}
return
0
;
}
static
void
notify
(
void
)
{
if
(
uid_table
)
{
size_t
total
=
0
;
size_t
i
;
size_t
recent
=
0
;
mailbox_messages_count
(
mbox
,
&
total
);
for
(
i
=
1
;
i
<=
total
;
i
++
)
{
message_t
msg
=
NULL
;
size_t
uid
=
0
;
mailbox_get_message
(
mbox
,
i
,
&
msg
);
message_get_uid
(
msg
,
&
uid
);
if
(
!
notify_uid
(
uid
))
recent
++
;
}
util_out
(
RESP_NONE
,
"%d EXISTS"
,
total
);
if
(
recent
)
util_out
(
RESP_NONE
,
"%d RECENT"
,
recent
);
notify_deleted
();
}
}
static
void
free_uids
(
void
)
{
if
(
uid_table
)
{
size_t
i
;
for
(
i
=
0
;
i
<
uid_table_count
;
i
++
)
attribute_destroy
(
&
(
uid_table
[
i
].
attr
),
NULL
);
free
(
uid_table
);
uid_table
=
NULL
;
uid_table_count
=
0
;
}
}
static
void
reset_uids
(
void
)
{
size_t
total
=
0
;
size_t
i
;
notify
();
free_uids
();
mailbox_messages_count
(
mbox
,
&
total
);
for
(
i
=
1
;
i
<=
total
;
i
++
)
{
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
size_t
uid
=
0
;
uid_table
=
realloc
(
uid_table
,
sizeof
(
*
uid_table
)
*
(
uid_table_count
+
1
));
if
(
!
uid_table
)
util_quit
(
ERR_NO_MEM
);
mailbox_get_message
(
mbox
,
i
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
message_get_uid
(
msg
,
&
uid
);
uid_table
[
uid_table_count
].
uid
=
uid
;
uid_table
[
uid_table_count
].
msgno
=
i
;
uid_table
[
uid_table_count
].
notify
=
0
;
attribute_create
(
&
(
uid_table
[
uid_table_count
].
attr
),
NULL
);
attribute_copy
(
uid_table
[
uid_table_count
].
attr
,
attr
);
uid_table_count
++
;
}
}
size_t
uid_to_msgno
(
size_t
uid
)
{
size_t
i
;
for
(
i
=
0
;
i
<
uid_table_count
;
i
++
)
if
(
uid_table
[
i
].
uid
==
uid
)
return
uid_table
[
i
].
msgno
;
return
0
;
}
int
imap4d_sync_flags
(
size_t
msgno
)
{
size_t
i
;
for
(
i
=
0
;
i
<
uid_table_count
;
i
++
)
if
(
uid_table
[
i
].
msgno
==
msgno
)
{
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
mailbox_get_message
(
mbox
,
msgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
attribute_copy
(
uid_table
[
i
].
attr
,
attr
);
break
;
}
return
0
;
}
int
imap4d_sync
(
void
)
{
/* if mbox --> NULL, it means to free all the ressources.
it may be because of close or before select/examine a new mailbox. */
if
(
mbox
==
NULL
)
free_uids
();
else
if
(
uid_table
==
NULL
||
!
mailbox_is_updated
(
mbox
))
reset_uids
();
return
0
;
}
imap4d/uid.c
View file @
43ba0c6
...
...
@@ -25,7 +25,33 @@
int
imap4d_uid
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
char
*
cmd
;
char
*
sp
=
NULL
;
int
rc
=
RESP_NO
;
char
buffer
[
64
];
if
(
!
(
command
->
states
&
state
))
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
return
util_finish
(
command
,
RESP_NO
,
"Not supported"
);
cmd
=
util_getword
(
arg
,
&
sp
);
if
(
!
cmd
)
util_finish
(
command
,
RESP_BAD
,
"Too few args"
);
if
(
strcasecmp
(
cmd
,
"FETCH"
)
==
0
)
{
rc
=
imap4d_fetch0
(
sp
,
1
,
buffer
,
sizeof
buffer
);
}
else
if
(
strcasecmp
(
cmd
,
"COPY"
)
==
0
)
{
rc
=
imap4d_copy0
(
sp
,
1
,
buffer
,
sizeof
buffer
);
}
else
if
(
strcasecmp
(
cmd
,
"STORE"
)
==
0
)
{
rc
=
imap4d_store0
(
sp
,
1
,
buffer
,
sizeof
buffer
);
}
else
{
snprintf
(
buffer
,
sizeof
buffer
,
"Error uknown uid command"
);
rc
=
RESP_BAD
;
}
return
util_finish
(
command
,
rc
,
"%s %s"
,
cmd
,
buffer
);
}
...
...
imap4d/util.c
View file @
43ba0c6
...
...
@@ -18,7 +18,7 @@
#include "imap4d.h"
#include <ctype.h>
static
int
add2set
__P
((
in
t
**
,
int
*
,
unsigned
long
,
size_t
));
static
int
add2set
__P
((
size_
t
**
,
int
*
,
unsigned
long
,
size_t
));
static
const
char
*
sc2string
__P
((
int
));
/* Get the next space/CR/NL separated word, some words are between double
...
...
@@ -67,7 +67,8 @@ util_token (char *buf, size_t len, char **ptr)
if
(
**
ptr
==
' '
||
**
ptr
==
'.'
||
**
ptr
==
'('
||
**
ptr
==
')'
||
**
ptr
==
'['
||
**
ptr
==
']'
||
**
ptr
==
'<'
||
**
ptr
==
'>'
)
||
**
ptr
==
'<'
||
**
ptr
==
'>'
||
**
ptr
==
'\r'
||
**
ptr
==
'\n'
)
{
/* Advance. */
if
(
start
==
(
*
ptr
))
...
...
@@ -172,7 +173,7 @@ util_getfullpath (char *name, const char *delim)
FIXME: The algo below is to relaxe, things like <,,,> or <:12> or <20:10>
will not generate an error. */
int
util_msgset
(
char
*
s
,
in
t
**
set
,
int
*
n
,
int
isuid
)
util_msgset
(
char
*
s
,
size_
t
**
set
,
int
*
n
,
int
isuid
)
{
unsigned
long
val
=
0
;
unsigned
long
low
=
0
;
...
...
@@ -340,93 +341,79 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
return
status
;
}
#if 0
/* Need a replacement for readline that can support literals. */
/* Clients are allowed to send literal string to the servers. this
mean that it can me everywhere where a string is allowed.
A literal is a sequence of zero or more octets (including CR and LF)
prefix-quoted with an octet count in the form of an open brace ("{"),
the number of octets, close brace ("}"), and CRLF.
*/
char
*
imap4d_readline
(
FILE
*
fp
)
{
char
buffer
[
512
];
char *line;
size_t
len
;
long
number
=
0
;
size_t
total
=
0
;
char
*
line
=
malloc
(
1
);
alarm (timeout);
line = fgets (buffer, sizeof (buffer), fp);
alarm (0);
if
(
!
line
)
util_quit (
1
);
line = strdup (buffer);
l
en = strlen (buffer);
if (len > 2)
util_quit
(
ERR_NO_MEM
);
l
ine
[
0
]
=
'\0'
;
/* start with a empty string. */
do
{
len--; /* C arrays are 0-based. */
if (line[len] == '\n' && line[len - 1] == '}')
alarm
(
timeout
);
if
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
)
==
NULL
)
util_quit
(
0
);
/* Logout. */
alarm
(
0
);
len
=
strlen
(
buffer
);
/* If we were in a litteral substract. We have to do it since the CR
is part of the count in a literal. */
if
(
number
)
number
-=
len
;
/* Remove CR. */
if
(
len
>
2
&&
buffer
[
len
-
1
]
==
'\n'
)
{
while (len && line[len] != '{') len--;
if (line [len] == '{')
if
(
buffer
[
len
-
2
]
==
'\r'
)
{
char *sp = NULL;
long number = strtoul (line + len + 1, &sp, 10);
if (*sp != '+')
util_send ("+ GO AHEAD\r\n");
line[len] = '\0';
while (number > 0)
{
char *literal = imap4d_readline (fd);
size_t n = strlen (literal);
line = realloc (line, strlen (line) + n + 1);
strcat (line, literal);
number -= n;
free (literal);
}
buffer
[
len
-
2
]
=
'\n'
;
buffer
[
len
-
1
]
=
'\0'
;
}
}
}
return line;
}
#endif
char
*
imap4d_readline
(
int
fd
)
{
fd_set
rfds
;
struct
timeval
tv
;
char
buf
[
512
],
*
ret
=
NULL
;
int
nread
;
int
total
=
0
;
int
available
;
FD_ZERO
(
&
rfds
);
FD_SET
(
fd
,
&
rfds
);
tv
.
tv_sec
=
timeout
;
tv
.
tv_usec
=
0
;
line
=
realloc
(
line
,
total
+
len
+
1
);
if
(
!
line
)
util_quit
(
ERR_NO_MEM
);
strcat
(
line
,
buffer
);
do
{
if
(
timeout
)
{
available
=
select
(
fd
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
if
(
!
available
)
util_quit
(
1
);
}
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
nread
<
1
)
util_quit
(
1
);
total
=
strlen
(
line
);
buf
[
nread
]
=
'\0'
;
ret
=
realloc
(
ret
,
(
total
+
nread
+
1
)
*
sizeof
(
char
));
if
(
ret
==
NULL
)
util_quit
(
1
);
memcpy
(
ret
+
total
,
buf
,
nread
+
1
);
total
+=
nread
;
/* Check if the client try to send a literal and we are not already
retrieving a litera. */
if
(
number
<=
0
&&
len
>
2
)
{
size_t
n
=
total
-
1
;
/* C arrays are 0-based. */
if
(
line
[
n
]
==
'\n'
&&
line
[
n
-
1
]
==
'}'
)
{
while
(
n
&&
line
[
n
]
!=
'{'
)
n
--
;
if
(
line
[
n
]
==
'{'
)
{
char
*
sp
=
NULL
;
/* Truncate where the literal number was. */
line
[
n
]
=
'\0'
;
number
=
strtoul
(
line
+
n
+
1
,
&
sp
,
10
);
/* Client can ask for non synchronise literal,
if a '+' is append to the octet count. */
if
(
*
sp
!=
'+'
)
util_send
(
"+ GO AHEAD
\r\n
"
);
}
}
}
}
while
(
memchr
(
buf
,
'\n'
,
nread
)
==
NULL
);
/* Nuke CR'\r' */
for
(
nread
=
total
;
nread
>
0
;
nread
--
)
if
(
ret
[
nread
]
==
'\r'
||
ret
[
nread
]
==
'\n'
)
ret
[
nread
]
=
'\0'
;
return
ret
;
while
(
number
>
0
);
return
line
;
}
int
...
...
@@ -435,6 +422,7 @@ util_do_command (char *prompt)
char
*
sp
=
NULL
,
*
tag
,
*
cmd
;
struct
imap4d_command
*
command
;
static
struct
imap4d_command
nullcommand
;
size_t
len
;
tag
=
util_getword
(
prompt
,
&
sp
);
cmd
=
util_getword
(
NULL
,
&
sp
);
...
...
@@ -462,6 +450,9 @@ util_do_command (char *prompt)
}
command
->
tag
=
tag
;
len
=
strlen
(
sp
);
if
(
len
&&
sp
[
len
-
1
]
==
'\n'
)
sp
[
len
-
1
]
=
'\0'
;
return
command
->
func
(
command
,
sp
);
}
...
...
@@ -487,8 +478,17 @@ util_start (char *tag)
void
util_quit
(
int
err
)
{
if
(
err
)
util_out
(
RESP_BYE
,
"Server terminating"
);
switch
(
err
)
{
case
ERR_NO_OFILE
:
/*util_out (RESP_BYE, "Server terminating dead socket."); */
break
;
case
ERR_NO_MEM
:
util_out
(
RESP_BYE
,
"Server terminating no more ressources."
);
break
;
default:
util_out
(
RESP_BYE
,
"Server terminating"
);
}
exit
(
err
);
}
...
...
@@ -535,7 +535,7 @@ sc2string (int rc)
}
static
int
add2set
(
in
t
**
set
,
int
*
n
,
unsigned
long
val
,
size_t
max
)
add2set
(
size_
t
**
set
,
int
*
n
,
unsigned
long
val
,
size_t
max
)
{
int
*
tmp
;
if
(
val
==
0
||
val
>
max
...
...
include/mailutils/header.h
View file @
43ba0c6
...
...
@@ -34,39 +34,43 @@
extern
"C"
{
#endif
#define MU_HEADER_UNIX_FROM "From "
#define MU_HEADER_RETURN_PATH "Return-Path"
#define MU_HEADER_RECEIVED "Received"
#define MU_HEADER_DATE "Date"
#define MU_HEADER_FROM "From"
#define MU_HEADER_SENDER "Sender"
#define MU_HEADER_RESENT_FROM "Resent-From"
#define MU_HEADER_SUBJECT "Subject"
#define MU_HEADER_SENDER "Sender"
#define MU_HEADER_RESENT_SENDER "Resent-SENDER"
#define MU_HEADER_TO "To"
#define MU_HEADER_RESENT_TO "Resent-To"
#define MU_HEADER_CC "Cc"
#define MU_HEADER_RESENT_CC "Resent-Cc"
#define MU_HEADER_BCC "Bcc"
#define MU_HEADER_RESENT_BCC "Resent-Bcc"
#define MU_HEADER_REPLY_TO "Reply-To"
#define MU_HEADER_RESENT_REPLY_TO "Resent-Reply-To"
#define MU_HEADER_MESSAGE_ID "Message-ID"
#define MU_HEADER_RESENT_MESSAGE_ID "Resent-Message-ID"
#define MU_HEADER_IN_REPLY_TO "In-Reply-To"
#define MU_HEADER_REFERENCE "Reference"
#define MU_HEADER_ENCRYPTED "Encrypted"
#define MU_HEADER_PRECEDENCE "Precedence"
#define MU_HEADER_STATUS "Status"
#define MU_HEADER_CONTENT_LENGTH "Content-Length"
#define MU_HEADER_CONTENT_LANGUAGE "Content-Language"
#define MU_HEADER_CONTENT_ENCODING "Content-transfer-encoding"
#define MU_HEADER_CONTENT_TYPE "Content-Type"
#define MU_HEADER_MIME_VERSION "MIME-Version"
#define MU_HEADER_X_UIDL "X-UIDL"
#define MU_HEADER_X_UID "X-UID"
#define MU_HEADER_X_IMAPBASE "X-IMAPbase"
#define MU_HEADER_UNIX_FROM "From "
#define MU_HEADER_RETURN_PATH "Return-Path"
#define MU_HEADER_RECEIVED "Received"
#define MU_HEADER_DATE "Date"
#define MU_HEADER_FROM "From"
#define MU_HEADER_SENDER "Sender"
#define MU_HEADER_RESENT_FROM "Resent-From"
#define MU_HEADER_SUBJECT "Subject"
#define MU_HEADER_SENDER "Sender"
#define MU_HEADER_RESENT_SENDER "Resent-SENDER"
#define MU_HEADER_TO "To"
#define MU_HEADER_RESENT_TO "Resent-To"
#define MU_HEADER_CC "Cc"
#define MU_HEADER_RESENT_CC "Resent-Cc"
#define MU_HEADER_BCC "Bcc"
#define MU_HEADER_RESENT_BCC "Resent-Bcc"
#define MU_HEADER_REPLY_TO "Reply-To"
#define MU_HEADER_RESENT_REPLY_TO "Resent-Reply-To"
#define MU_HEADER_MESSAGE_ID "Message-ID"
#define MU_HEADER_RESENT_MESSAGE_ID "Resent-Message-ID"
#define MU_HEADER_IN_REPLY_TO "In-Reply-To"
#define MU_HEADER_REFERENCE "Reference"
#define MU_HEADER_ENCRYPTED "Encrypted"
#define MU_HEADER_PRECEDENCE "Precedence"
#define MU_HEADER_STATUS "Status"
#define MU_HEADER_CONTENT_LENGTH "Content-Length"
#define MU_HEADER_CONTENT_LANGUAGE "Content-Language"
#define MU_HEADER_CONTENT_TRANSFER_ENCODING "Content-transfer-encoding"
#define MU_HEADER_CONTENT_ID "Content-ID"
#define MU_HEADER_CONTENT_TYPE "Content-Type"
#define MU_HEADER_CONTENT_DESCRIPTION "Content-Description"
#define MU_HEADER_CONTENT_DISPOSITION "Content-Disposition"
#define MU_HEADER_CONTENT_MD5 "Content-MD5"
#define MU_HEADER_MIME_VERSION "MIME-Version"
#define MU_HEADER_X_UIDL "X-UIDL"
#define MU_HEADER_X_UID "X-UID"
#define MU_HEADER_X_IMAPBASE "X-IMAPbase"
/* Mime support header attribute */
...
...
include/mailutils/parse822.h
View file @
43ba0c6
...
...
@@ -78,6 +78,7 @@ extern int parse822_address __P ((const char** p, const char* e, address_
extern
int
parse822_route_addr
__P
((
const
char
**
p
,
const
char
*
e
,
address_t
*
a
));
extern
int
parse822_route
__P
((
const
char
**
p
,
const
char
*
e
,
char
**
route
));
extern
int
parse822_addr_spec
__P
((
const
char
**
p
,
const
char
*
e
,
address_t
*
a
));
extern
int
parse822_unix_mbox
__P
((
const
char
**
p
,
const
char
*
e
,
address_t
*
a
));
extern
int
parse822_local_part
__P
((
const
char
**
p
,
const
char
*
e
,
char
**
local_part
));
extern
int
parse822_domain
__P
((
const
char
**
p
,
const
char
*
e
,
char
**
domain
));
extern
int
parse822_sub_domain
__P
((
const
char
**
p
,
const
char
*
e
,
char
**
sub_domain
));
...
...
mailbox/attribute.c
View file @
43ba0c6
...
...
@@ -441,7 +441,9 @@ attribute_copy (attribute_t dest, attribute_t src)
{
if
(
dest
==
NULL
||
src
==
NULL
)
return
EINVAL
;
memcpy
(
dest
,
src
,
sizeof
(
*
dest
));
/* Can not be a deep copy. */
/* memcpy (dest, src, sizeof (*dest)); */
dest
->
flags
=
src
->
flags
;
return
0
;
}
...
...
mailbox/file_stream.c
View file @
43ba0c6
...
...
@@ -55,6 +55,13 @@ _file_read (stream_t stream, char *optr, size_t osize,
size_t
n
;
int
err
=
0
;
if
(
!
fs
->
file
)
{
if
(
nbytes
)
*
nbytes
=
0
;
return
0
;
}
if
(
fs
->
offset
!=
offset
)
{
if
(
fseek
(
fs
->
file
,
offset
,
SEEK_SET
)
!=
0
)
...
...
@@ -84,6 +91,13 @@ _file_readline (stream_t stream, char *optr, size_t osize,
size_t
n
=
0
;
int
err
=
0
;
if
(
!
fs
->
file
)
{
if
(
nbytes
)
*
nbytes
=
0
;
return
0
;
}
if
(
fs
->
offset
!=
offset
)
{
if
(
fseek
(
fs
->
file
,
offset
,
SEEK_SET
)
!=
0
)
...
...
@@ -117,6 +131,13 @@ _file_write (stream_t stream, const char *iptr, size_t isize,
size_t
n
;
int
err
=
0
;
if
(
!
fs
->
file
)
{
if
(
nbytes
)
*
nbytes
=
0
;
return
0
;
}
if
(
fs
->
offset
!=
offset
)
{
if
(
fseek
(
fs
->
file
,
offset
,
SEEK_SET
)
!=
0
)
...
...
@@ -144,7 +165,7 @@ static int
_file_truncate
(
stream_t
stream
,
off_t
len
)
{
struct
_file_stream
*
fs
=
stream_get_owner
(
stream
);
if
(
ftruncate
(
fileno
(
fs
->
file
),
len
)
!=
0
)
if
(
f
s
->
file
&&
f
truncate
(
fileno
(
fs
->
file
),
len
)
!=
0
)
return
errno
;
return
0
;
}
...
...
@@ -154,6 +175,12 @@ _file_size (stream_t stream, off_t *psize)
{
struct
_file_stream
*
fs
=
stream_get_owner
(
stream
);
struct
stat
stbuf
;
if
(
!
fs
->
file
)
{
if
(
psize
)
*
psize
=
0
;
return
0
;
}
fflush
(
fs
->
file
);
if
(
fstat
(
fileno
(
fs
->
file
),
&
stbuf
)
==
-
1
)
return
errno
;
...
...
@@ -166,16 +193,24 @@ static int
_file_flush
(
stream_t
stream
)
{
struct
_file_stream
*
fs
=
stream_get_owner
(
stream
);
return
fflush
(
fs
->
file
);
if
(
fs
->
file
)
return
fflush
(
fs
->
file
);
return
0
;
}
static
int
_file_get_fd
(
stream_t
stream
,
int
*
pfd
)
{
struct
_file_stream
*
fs
=
stream_get_owner
(
stream
);
int
status
=
0
;
if
(
pfd
)
*
pfd
=
fileno
(
fs
->
file
);
return
0
;
{
if
(
fs
->
file
)
*
pfd
=
fileno
(
fs
->
file
);
else
status
=
EINVAL
;
}
return
status
;
}
static
int
...
...
mailbox/mailbox.c
View file @
43ba0c6
...
...
@@ -261,7 +261,7 @@ int
mailbox_is_updated
(
mailbox_t
mbox
)
{
if
(
mbox
==
NULL
||
mbox
->
_is_updated
==
NULL
)
return
ENOSYS
;
return
1
;
return
mbox
->
_is_updated
(
mbox
);
}
...
...
mailbox/parse822.c
View file @
43ba0c6
...
...
@@ -18,20 +18,9 @@
/*
Things to consider:
- A group should create an address node for a group, accessable
with address_get_personal(). Perhaps an is_group() would be
useful? Test that a zero-length phrase is rejected! So these
are invalid:
: a@b ;
"" : ;
- When parsing phrase, should I ignore non-ascii, or replace with a
'?' character? Right now parsing fails.
- Make domain optional in addr-spec, for parsing address lists
provided to local mail utilities, but NOT in the addr-spec of a
route-addr.
- Are comments allowed in domain-literals?
- Need a way to mark the *end* of a group. Maybe add a field to _address,
...
...
@@ -53,14 +42,12 @@ Things to consider:
gets one address, or just say it is or it isn't in RFC format?
Right now we're strict, we'll see how it goes.
- parse field names and bodies?
- parse dates?
- parse Received: field?
- test for memory leaks on malloc failure
- fix the realloc, try a struct _string { char* b, size_t sz };
- get example mail from drums, and from the perl code.
- get example addresses from rfc2822, and from the perl code.
*/
#ifdef HAVE_CONFIG_H
...
...
@@ -610,12 +597,15 @@ int parse822_address_list(address_t* a, const char* s)
int
parse822_address
(
const
char
**
p
,
const
char
*
e
,
address_t
*
a
)
{
/* address = mailbox / group */
/* address = mailbox / group
/ unix-mbox
*/
int
rc
;
if
((
rc
=
parse822_mail_box
(
p
,
e
,
a
))
==
EPARSE
)
rc
=
parse822_group
(
p
,
e
,
a
);
if
((
rc
=
parse822_mail_box
(
p
,
e
,
a
))
==
EPARSE
)
{
if
((
rc
=
parse822_group
(
p
,
e
,
a
))
==
EPARSE
)
{
rc
=
parse822_unix_mbox
(
p
,
e
,
a
);
}
}
return
rc
;
}
...
...
@@ -690,7 +680,9 @@ int parse822_group(const char** p, const char* e, address_t* a)
int
parse822_mail_box
(
const
char
**
p
,
const
char
*
e
,
address_t
*
a
)
{
/* mailbox = addr-spec [ "(" comment ")" ] / [phrase] route-addr
/* mailbox =
* addr-spec [ "(" comment ")" ] /
* [phrase] route-addr
*
* Note: we parse the ancient comment on the right since
* it's such "common practice". :-(
...
...
@@ -717,10 +709,6 @@ int parse822_mail_box(const char** p, const char* e, address_t* a)
return
rc
;
}
if
(
rc
!=
EPARSE
)
{
*
p
=
save
;
return
rc
;
}
/* -> phrase route-addr */
{
...
...
@@ -732,17 +720,23 @@ int parse822_mail_box(const char** p, const char* e, address_t* a)
return
rc
;
}
if
((
rc
=
parse822_route_addr
(
p
,
e
,
a
)))
{
if
((
rc
=
parse822_route_addr
(
p
,
e
,
a
))
==
EOK
)
{
/* add the phrase */
(
*
a
)
->
personal
=
phrase
;
return
EOK
;
}
else
if
(
rc
!=
EPARSE
)
{
/* some internal error, fail out */
*
p
=
save
;
str_free
(
&
phrase
);
return
rc
;
}
*
p
=
save
;
/* add the phrase */
(
*
a
)
->
personal
=
phrase
;
return
rc
;
}
return
EOK
;
return
rc
;
}
int
parse822_route_addr
(
const
char
**
p
,
const
char
*
e
,
address_t
*
a
)
...
...
@@ -874,6 +868,29 @@ int parse822_addr_spec(const char** p, const char* e, address_t* a)
return
rc
;
}
int
parse822_unix_mbox
(
const
char
**
p
,
const
char
*
e
,
address_t
*
a
)
{
/* unix-mbox = atom */
const
char
*
save
=
*
p
;
char
*
mbox
=
0
;
int
rc
;
parse822_skip_comments
(
p
,
e
);
rc
=
parse822_atom
(
p
,
e
,
&
mbox
);
if
(
!
rc
)
{
rc
=
fill_mb
(
a
,
0
,
0
,
mbox
,
0
);
}
if
(
rc
)
{
*
p
=
save
;
str_free
(
&
mbox
);
}
return
rc
;
}
int
parse822_local_part
(
const
char
**
p
,
const
char
*
e
,
char
**
local_part
)
{
/* local-part = word *("." word)
...
...
Please
register
or
sign in
to post a comment