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
a9a11cf9
...
a9a11cf95bbfad541ae242cffecb963065621fa1
authored
2001-05-20 02:37:16 +0000
by
Alain Magloire
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Updates from Sam Roberts.
1 parent
3e158c93
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
353 additions
and
71 deletions
mailbox/address.c
mailbox/mbx_default.c
mailbox/parse822.c
mailbox/address.c
View file @
a9a11cf
...
...
@@ -33,28 +33,54 @@
/* Get email address from rfc822 address. */
int
address_create
(
address_t
*
a
,
const
char
*
p
)
address_create
(
address_t
*
a
,
const
char
*
s
)
{
/* 'paddress' must exist, and can't already have been initialized
*/
int
status
;
char
*
s
;
/* FIXME: Remove when done, see below */
const
char
*
e
;
const
char
*
save
;
char
*
fb
;
if
(
!
a
)
return
EINVAL
;
*
a
=
NULL
;
save
=
s
;
e
=
&
s
[
strlen
(
s
)];
fb
=
calloc
(
1
,
1
);
/* FIXME: parse822 does not seem to like '\n' in the field body
take care of it here until the proper fix. */
s
=
strdup
(
p
);
{
char
*
nl
=
s
;
while
((
nl
=
strchr
(
nl
,
'\n'
)))
*
nl
++
=
' '
;
}
/* We need to unfold the string. Do the same thing as parse822_field_body()
but we have to be more flexible in allowing bare '\n' as CRLF. */
for
(;;)
{
const
char
*
eol
=
s
;
size_t
len
=
strlen
(
fb
);
while
(
eol
!=
e
)
{
/* if (eol[0] == '\r' && (eol+1) != e && eol[1] == '\n') */
if
(
*
eol
==
'\n'
)
break
;
++
eol
;
}
fb
=
realloc
(
fb
,
len
+
(
eol
-
s
)
+
1
);
memcpy
(
fb
+
len
,
s
,
eol
-
s
);
fb
[
len
+
(
eol
-
s
)]
=
'\0'
;
s
=
eol
;
s
+=
2
;
if
(
s
==
e
)
break
;
/* no more, so we're done */
/* check if next line is a continuation line */
if
(
*
s
!=
' '
&&
*
s
!=
'\t'
)
break
;
}
status
=
parse822_address_list
(
a
,
(
char
*
)
s
);
status
=
parse822_address_list
(
a
,
(
char
*
)
fb
);
free
(
fb
);
if
(
status
==
0
)
{
/* And address-list may contain 0 addresses but parse correctly.
...
...
@@ -62,15 +88,13 @@ address_create (address_t *a, const char *p)
if
(
!*
a
)
return
ENOENT
;
(
*
a
)
->
addr
=
strdup
(
s
);
(
*
a
)
->
addr
=
strdup
(
s
ave
);
if
(
!
(
*
a
)
->
addr
)
{
address_destroy
(
a
);
return
ENOMEM
;
}
}
/* FIXME: part of the hack/fix above remove when done. */
free
(
s
);
return
status
;
}
...
...
mailbox/mbx_default.c
View file @
a9a11cf
...
...
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <pwd.h>
#include <unistd.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
...
...
@@ -35,52 +37,268 @@
# define _PATH_MAILDIR "/usr/spool/mail"
#endif
/* Is this a security risk? */
#define USE_ENVIRON 1
static
char
*
tilde_expansion
__P
((
const
char
*
));
static
char
*
plus_equal_expansion
__P
((
const
char
*
));
static
char
*
get_cwd
__P
((
void
));
static
char
*
get_full_path
__P
((
const
char
*
));
static
const
char
*
get_homedir
__P
((
const
char
*
));
/* Do + and = expansion to ~/Mail, if necessary. */
static
char
*
plus_equal_expansion
(
const
char
*
file
)
{
char
*
p
=
NULL
;
if
(
file
&&
(
*
file
==
'+'
||
*
file
==
'='
))
{
char
*
folder
;
/* Skip '+' or '='. */
file
++
;
folder
=
tilde_expansion
(
"~/Mail"
);
if
(
folder
)
{
p
=
malloc
(
strlen
(
folder
)
+
1
+
strlen
(
file
)
+
1
);
if
(
p
)
sprintf
(
p
,
"%s/%s"
,
folder
,
file
);
free
(
folder
);
}
}
if
(
!
p
)
p
=
strdup
(
file
);
return
p
;
}
static
const
char
*
get_homedir
(
const
char
*
user
)
{
const
char
*
homedir
=
NULL
;
struct
passwd
*
pw
=
NULL
;
if
(
user
)
{
pw
=
getpwnam
(
user
);
if
(
pw
)
homedir
=
pw
->
pw_dir
;
}
else
{
#ifdef USE_ENVIRON
/* NOTE: Should we honor ${HOME}? */
homedir
=
getenv
(
"HOME"
);
if
(
homedir
==
NULL
)
{
pw
=
getpwuid
(
getuid
());
if
(
pw
)
homedir
=
pw
->
pw_dir
;
}
#else
pw
=
getpwuid
(
getuid
());
if
(
pw
)
homedir
=
pw
->
pw_dir
;
#endif
}
return
homedir
;
}
/* Do ~ , if necessary. We do not use $HOME. */
static
char
*
tilde_expansion
(
const
char
*
file
)
{
char
*
p
=
NULL
;
const
char
*
homedir
=
NULL
;
const
char
delim
=
'/'
;
/* Not portable. */
if
(
file
&&
*
file
==
'~'
)
{
/* Skip the tilde. */
file
++
;
/* This means we have ~ or ~/something. */
if
(
*
file
==
delim
||
*
file
==
'\0'
)
{
homedir
=
get_homedir
(
NULL
);
if
(
homedir
)
{
p
=
calloc
(
strlen
(
homedir
)
+
strlen
(
file
)
+
1
,
1
);
if
(
p
)
{
strcpy
(
p
,
homedir
);
strcat
(
p
,
file
);
}
}
}
/* Means we have ~user or ~user/something. */
else
{
const
char
*
s
=
file
;
/* Move to the first delim. */
while
(
*
s
&&
*
s
!=
delim
)
s
++
;
/* Get the username homedir. */
{
char
*
name
;
name
=
calloc
(
s
-
file
+
1
,
1
);
if
(
name
)
{
memcpy
(
name
,
file
,
s
-
file
);
name
[
s
-
file
]
=
'\0'
;
}
homedir
=
get_homedir
(
name
);
free
(
name
);
}
if
(
homedir
)
{
p
=
calloc
(
strlen
(
homedir
)
+
strlen
(
s
)
+
1
,
1
);
if
(
p
)
{
strcpy
(
p
,
homedir
);
strcat
(
p
,
s
);
}
}
}
}
if
(
!
p
)
p
=
strdup
(
file
);
return
p
;
}
static
char
*
get_cwd
()
{
char
*
ret
;
unsigned
path_max
;
char
buf
[
128
];
errno
=
0
;
ret
=
getcwd
(
buf
,
sizeof
(
buf
));
if
(
ret
!=
NULL
)
return
strdup
(
buf
);
if
(
errno
!=
ERANGE
)
return
NULL
;
path_max
=
128
;
path_max
+=
2
;
/* The getcwd docs say to do this. */
for
(;;)
{
char
*
cwd
=
(
char
*
)
malloc
(
path_max
);
errno
=
0
;
ret
=
getcwd
(
cwd
,
path_max
);
if
(
ret
!=
NULL
)
return
ret
;
if
(
errno
!=
ERANGE
)
{
int
save_errno
=
errno
;
free
(
cwd
);
errno
=
save_errno
;
return
NULL
;
}
free
(
cwd
);
path_max
+=
path_max
/
16
;
path_max
+=
32
;
}
/* oops? */
return
NULL
;
}
static
char
*
get_full_path
(
const
char
*
file
)
{
char
*
p
=
NULL
;
if
(
!
file
)
p
=
get_cwd
();
else
if
(
*
file
!=
'/'
)
{
char
*
cwd
=
get_cwd
();
if
(
cwd
)
{
p
=
calloc
(
strlen
(
cwd
)
+
1
+
strlen
(
file
)
+
1
,
1
);
if
(
p
)
sprintf
(
p
,
"%s/%s"
,
cwd
,
file
);
free
(
cwd
);
}
}
if
(
!
p
)
p
=
strdup
(
file
);
return
p
;
}
/* We are trying to be smart about the location of the mail.
mailbox_create() is not doing this.
~/file --> /home/user/file
~user/file --> /home/user/file
+file --> /home/user/Mail/file
=file --> /home/user/Mail/file
*/
int
mailbox_create_default
(
mailbox_t
*
pmbox
,
const
char
*
mail
)
{
const
char
*
user
=
NULL
;
char
*
mbox
=
NULL
;
int
status
;
/* Sanity. */
if
(
pmbox
==
NULL
)
return
EINVAL
;
/* Other utilities may not understand GNU mailutils url namespace, so
use FOLDER instead, to not confuse others by using MAIL. */
if
(
mail
==
NULL
)
mail
=
getenv
(
"FOLDER"
);
/* Fallback to wellknown environment. */
if
(
mail
==
NULL
)
mail
=
getenv
(
"MAIL"
);
if
(
mail
)
/* FIXME: This is weak, it would be better to check
for all the known schemes to detect presence of URLs. */
if
(
mail
&&
*
mail
&&
strchr
(
mail
,
':'
)
==
NULL
)
{
/* Is it a fullpath ? */
if
(
mail
[
0
]
!=
'/'
)
{
/* Is it a URL ? */
if
(
strchr
(
mail
,
':'
)
==
NULL
)
{
/* A user name. */
user
=
mail
;
mail
=
NULL
;
}
}
char
*
mail0
;
char
*
mail2
;
mail0
=
tilde_expansion
(
mail
);
mail2
=
plus_equal_expansion
(
mail0
);
free
(
mail0
);
mbox
=
get_full_path
(
mail2
);
free
(
mail2
);
}
if
(
mail
==
NULL
)
/* Search the spooldir. */
if
(
mbox
==
NULL
)
{
int
status
;
char
*
mail0
;
const
char
*
user
=
NULL
;
#ifdef USE_ENVIRON
user
=
(
getenv
(
"LOGNAME"
))
?
getenv
(
"LOGNAME"
)
:
getenv
(
"USER"
);
#endif
if
(
user
==
NULL
)
{
user
=
(
getenv
(
"LOGNAME"
))
?
getenv
(
"LOGNAME"
)
:
getenv
(
"USER"
);
if
(
user
==
NULL
)
struct
passwd
*
pw
;
pw
=
getpwuid
(
getuid
());
if
(
pw
)
user
=
pw
->
pw_name
;
else
{
mu_error
(
"Who am I ?
\n
"
);
return
EINVAL
;
}
}
m
ail0
=
malloc
(
strlen
(
user
)
+
strlen
(
_PATH_MAILDIR
)
+
2
);
if
(
m
ail0
==
NULL
)
m
box
=
malloc
(
strlen
(
user
)
+
strlen
(
_PATH_MAILDIR
)
+
2
);
if
(
m
box
==
NULL
)
return
ENOMEM
;
sprintf
(
mail0
,
"%s/%s"
,
_PATH_MAILDIR
,
user
);
status
=
mailbox_create
(
pmbox
,
mail0
);
free
(
mail0
);
return
status
;
sprintf
(
mbox
,
"%s/%s"
,
_PATH_MAILDIR
,
user
);
}
return
mailbox_create
(
pmbox
,
mail
);
status
=
mailbox_create
(
pmbox
,
mbox
);
free
(
mbox
);
return
status
;
}
...
...
mailbox/parse822.c
View file @
a9a11cf
...
...
@@ -211,12 +211,53 @@ int parse822_is_smtp_q(char c)
/***** From RFC 822, 3.3 Lexical Tokens *****/
int
parse822_skip_
ws
(
const
char
**
p
,
const
char
*
e
)
int
parse822_skip_
crlf
(
const
char
**
p
,
const
char
*
e
)
{
while
((
*
p
!=
e
)
&&
parse822_is_lwsp_char
(
**
p
))
{
const
char
*
s
=
*
p
;
if
(
(
&
s
[
1
]
<
e
)
&&
s
[
0
]
==
'\r'
&&
s
[
1
]
==
'\n'
)
{
*
p
+=
2
;
return
EOK
;
}
return
EPARSE
;
}
int
parse822_skip_lwsp_char
(
const
char
**
p
,
const
char
*
e
)
{
if
(
*
p
<
e
&&
parse822_is_lwsp_char
(
**
p
))
{
*
p
+=
1
;
return
EOK
;
}
return
EOK
;
return
EPARSE
;
}
int
parse822_skip_lwsp
(
const
char
**
p
,
const
char
*
e
)
{
/*
* linear-white-space = 1*([CRLF] LWSP-char)
*/
int
space
=
0
;
while
(
*
p
!=
e
)
{
const
char
*
save
=
*
p
;
if
(
parse822_skip_lwsp_char
(
p
,
e
)
==
EOK
)
{
space
=
1
;
continue
;
}
if
(
parse822_skip_crlf
(
p
,
e
)
==
EOK
)
{
if
(
parse822_skip_lwsp_char
(
p
,
e
)
==
EOK
)
{
continue
;
}
*
p
=
save
;
return
EPARSE
;
}
break
;
}
return
space
?
EOK
:
EPARSE
;
}
int
parse822_skip_comments
(
const
char
**
p
,
const
char
*
e
)
...
...
@@ -258,7 +299,7 @@ int parse822_digits(const char** p, const char* e,
int
parse822_special
(
const
char
**
p
,
const
char
*
e
,
char
c
)
{
parse822_skip_
ws
(
p
,
e
);
/* not comments, they start with a special... */
parse822_skip_
lwsp
(
p
,
e
);
/* not comments, they start with a special... */
if
((
*
p
!=
e
)
&&
**
p
==
c
)
{
*
p
+=
1
;
...
...
@@ -694,7 +735,7 @@ int parse822_mail_box(const char** p, const char* e, address_t* a)
/* -> addr-spec */
if
((
rc
=
parse822_addr_spec
(
p
,
e
,
a
))
==
EOK
)
{
parse822_skip_
ws
(
p
,
e
);
parse822_skip_
lwsp
(
p
,
e
);
/* yuck. */
if
((
rc
=
parse822_comment
(
p
,
e
,
&
(
*
a
)
->
personal
))
==
EPARSE
)
{
...
...
@@ -1087,20 +1128,18 @@ int parse822_domain_literal(const char** p, const char* e, char** domain_literal
return
rc
;
}
#if 0
/***** From RFC 822, 3.2 Header Field Definitions *****/
int
parse822_field_name
(
const
char
**
p
,
const
char
*
e
,
char
**
fieldname
)
{
/* field-name = 1*<any char, excluding ctlS, space, and ":"> ":" */
Ptr save =
p;
const
char
*
save
=
*
p
;
Rope fn
;
char
*
fn
=
NULL
;
while
(
*
p
!=
e
)
{
char c = *p;
char
c
=
*
*
p
;
if
(
!
parse822_is_char
(
c
))
break
;
...
...
@@ -1112,66 +1151,67 @@ int parse822_field_name(const char** p, const char* e, char** fieldname)
if
(
c
==
':'
)
break
;
fn.append(
c);
str_append_char
(
&
fn
,
c
);
*
p
+=
1
;
}
/* must be at least one char in the field name */
if(
fn.empty()
) {
p = save;
return
0
;
if
(
!
fn
)
{
*
p
=
save
;
return
EPARSE
;
}
parse822_skip_comments
(
p
,
e
);
if
(
!
parse822_special
(
p
,
e
,
':'
))
{
p = save;
return 0;
*
p
=
save
;
if
(
fn
)
free
(
fn
);
return
EPARSE
;
}
fieldname = fn;
*
fieldname
=
fn
;
return
1
;
return
EOK
;
}
int parse822_field_body(const char
** p, const char* e, Rope&
fieldbody)
int
parse822_field_body
(
const
char
**
p
,
const
char
*
e
,
char
**
fieldbody
)
{
/* field-body = *text [CRLF lwsp-char field-body] */
Ptr save = p;
/*const char *save = *p; */
Rope fb
;
char
*
fb
=
NULL
;
for
(;;)
{
Ptr eol =
p;
const
char
*
eol
=
*
p
;
while
(
eol
!=
e
)
{
char c = *eol;
/*char c = *eol; */
if
(
eol
[
0
]
==
'\r'
&&
(
eol
+
1
)
!=
e
&&
eol
[
1
]
==
'\n'
)
break
;
++
eol
;
}
fb.append(
p, eol);
p = eol;
str_append_range
(
&
fb
,
*
p
,
eol
);
*
p
=
eol
;
if
(
eol
==
e
)
break
;
/* no more, so we're done */
assert(p[0] == '\r');
assert(p[1] == '\n');
/*assert(p[0] == '\r'); */
/*assert(p[1] == '\n'); */
p += 2;
*
p
+=
2
;
if
(
*
p
==
e
)
break
;
/* no more, so we're done */
/* check if next line is a continuation line */
if(*
p != ' ' &&
*p != '\t')
if
(
*
*
p
!=
' '
&&
*
*
p
!=
'\t'
)
break
;
}
fieldbody = fb;
*
fieldbody
=
fb
;
return
1
;
return
EOK
;
}
#endif
/***** RFC 822 Quoting Functions *****/
...
...
Please
register
or
sign in
to post a comment