Finally took time to put the code in from Jakob first draft, in
an email excerpt: states is the valid states for a command (eg. LOGIN is only valid in non-authenticated state, SELECT is valid in authenticated or selected). success is the state to enter when the command completes successfully (STATE_NONE means no change) and failure is the state to enter when the command fails. The fetch code is getting close to completion! ye!
Showing
38 changed files
with
468 additions
and
152 deletions
1 | 2001-04-18 Alain Magloire | ||
2 | |||
3 | Finally took time to put the code in from Jakob first draft, in | ||
4 | an email excerpt: | ||
5 | states is the valid states for a command (eg. LOGIN is only valid in | ||
6 | non-authenticated state, SELECT is valid in authenticated or | ||
7 | selected). success is the state to enter when the command completes | ||
8 | successfully (STATE_NONE means no change) and failure is the state to | ||
9 | enter when the command fails. | ||
10 | |||
11 | * imap4d/*.c: All the commands check there state. | ||
12 | * imap4d/fetch.c: Cleanup the fetch code, and broke | ||
13 | the fetch_operation() routine in multiple routines. | ||
14 | (fetch_message): New function. | ||
15 | (fetch_header): Likewised | ||
16 | (fetch_content): Likewised | ||
17 | (fetch_io): Likewised | ||
18 | (fetch_header_fields): Likewised | ||
19 | (fetch_header_fields_not): Likewised | ||
20 | (fetch_send_address): Likewised | ||
21 | |||
22 | * mailbox/header.c: Some functions were usefull while | ||
23 | programming the imap server, put them here. | ||
24 | (header_aget_value): New function. | ||
25 | (header_aget_field_name): New function. | ||
26 | (header_aget_field_value): New function. | ||
27 | |||
28 | * mailbox/memory_stream.c: New file, implemented a | ||
29 | malloc() buffer that you can access via the stream interface. | ||
30 | * mailbox/file_stream.c: Remove spurious checks. | ||
31 | * mailbox/mapfile_stream.c: Remove spurious checks. | ||
32 | (_mapfile_read): check if there is no newline left. | ||
33 | |||
1 | 2001-04-16 Alain Magloire | 34 | 2001-04-16 Alain Magloire |
2 | 35 | ||
3 | To get things to compile on Solaris, change configure to check | 36 | To get things to compile on Solaris, change configure to check | ... | ... |
... | @@ -72,16 +72,20 @@ MIME-Version | ... | @@ -72,16 +72,20 @@ MIME-Version |
72 | 72 | ||
73 | @end deftypefun | 73 | @end deftypefun |
74 | 74 | ||
75 | @deftypefun int header_get_value (header_t @var{hdr}, const char *fn, char *fv, size_t len, size_t *n) | 75 | @deftypefun int header_get_value (header_t @var{hdr}, const char *@var{fn}, char *@var{fv}, size_t @var{len}, size_t *@var{n}) |
76 | Value of field-name @var{fn} is returned in buffer @var{fv} of size @var{len}. | 76 | Value of field-name @var{fn} is returned in buffer @var{fv} of size @var{len}. |
77 | The number of bytes written is put in @var{n}. | 77 | The number of bytes written is put in @var{n}. |
78 | @end deftypefun | 78 | @end deftypefun |
79 | 79 | ||
80 | @deftypefun int header_aget_value (header_t @var{hdr}, const char *@var{fn}, char **@var{fv}) | ||
81 | The value is allocated. | ||
82 | @end deftypefun | ||
83 | |||
80 | @deftypefun int header_get_stream (header_t @var{hdr}, stream_t *@var{pstream}) | 84 | @deftypefun int header_get_stream (header_t @var{hdr}, stream_t *@var{pstream}) |
81 | @end deftypefun | 85 | @end deftypefun |
82 | 86 | ||
83 | @deftypefun int header_size (header_t @var{hdr}, size_t *@var{size}) | 87 | @deftypefun int header_set_size (header_t @var{hdr}, size_t *@var{size}) |
84 | @end deftypefun | 88 | @end deftypefun |
85 | 89 | ||
86 | @deftypefun int header_lines (header_t @var{hdr}, size_t *@var{lpines}) | 90 | @deftypefun int header_set_lines (header_t @var{hdr}, size_t *@var{lpines}) |
87 | @end deftypefun | 91 | @end deftypefun | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_append (struct imap4d_command *command, char *arg) | 25 | imap4d_append (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not implemented"); | 29 | return util_finish (command, RESP_NO, "Not implemented"); |
28 | } | 30 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_authenticate (struct imap4d_command *command, char *arg) | 25 | imap4d_authenticate (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Command not supported"); | 29 | return util_finish (command, RESP_NO, "Command not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -20,6 +20,8 @@ | ... | @@ -20,6 +20,8 @@ |
20 | int | 20 | int |
21 | imap4d_capability (struct imap4d_command *command, char *arg) | 21 | imap4d_capability (struct imap4d_command *command, char *arg) |
22 | { | 22 | { |
23 | if (! (command->states & state)) | ||
24 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
23 | util_out (RESP_NONE, "CAPABILITY IMAP4rev1"); | 25 | util_out (RESP_NONE, "CAPABILITY IMAP4rev1"); |
24 | return util_finish (command, RESP_OK, "Completed"); | 26 | return util_finish (command, RESP_OK, "Completed"); |
25 | } | 27 | } | ... | ... |
... | @@ -26,5 +26,7 @@ | ... | @@ -26,5 +26,7 @@ |
26 | int | 26 | int |
27 | imap4d_check (struct imap4d_command *command, char *arg) | 27 | imap4d_check (struct imap4d_command *command, char *arg) |
28 | { | 28 | { |
29 | if (! (command->states & state)) | ||
30 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
29 | return util_finish (command, RESP_OK, "Completed"); | 31 | return util_finish (command, RESP_OK, "Completed"); |
30 | } | 32 | } | ... | ... |
... | @@ -25,14 +25,11 @@ imap4d_close (struct imap4d_command *command, char *arg) | ... | @@ -25,14 +25,11 @@ imap4d_close (struct imap4d_command *command, char *arg) |
25 | { | 25 | { |
26 | /* FIXME: Check args. */ | 26 | /* FIXME: Check args. */ |
27 | /* FIXME: Check state and if they selected. */ | 27 | /* FIXME: Check state and if they selected. */ |
28 | /* FIXME: state = AUTHENTICATE. */ | 28 | if (! (command->states & state)) |
29 | 29 | return util_finish (command, RESP_BAD, "Wrong state"); | |
30 | /* FIXME: Check and report errors. */ | 30 | /* FIXME: Check and report errors. */ |
31 | mailbox_expunge (mbox); | 31 | mailbox_expunge (mbox); |
32 | mailbox_close (mbox); | 32 | mailbox_close (mbox); |
33 | mailbox_destroy (&mbox); | 33 | mailbox_destroy (&mbox); |
34 | |||
35 | /* FIXME: state = Not selected. */ | ||
36 | |||
37 | return util_finish (command, RESP_OK, "Completed"); | 34 | return util_finish (command, RESP_OK, "Completed"); |
38 | } | 35 | } | ... | ... |
... | @@ -19,29 +19,29 @@ | ... | @@ -19,29 +19,29 @@ |
19 | 19 | ||
20 | struct imap4d_command imap4d_command_table [] = | 20 | struct imap4d_command imap4d_command_table [] = |
21 | { | 21 | { |
22 | { "CAPABILITY", imap4d_capability, STATE_ALL, STATE_NONE, STATE_NONE }, | 22 | { "CAPABILITY", imap4d_capability, STATE_ALL, STATE_NONE, STATE_NONE, NULL }, |
23 | { "NOOP", imap4d_noop, STATE_ALL, STATE_NONE, STATE_NONE }, | 23 | { "NOOP", imap4d_noop, STATE_ALL, STATE_NONE, STATE_NONE, NULL }, |
24 | { "LOGOUT", imap4d_logout, STATE_ALL, STATE_LOGOUT, STATE_NONE }, | 24 | { "LOGOUT", imap4d_logout, STATE_ALL, STATE_LOGOUT, STATE_NONE, NULL }, |
25 | { "AUTHENTICATE", imap4d_authenticate, STATE_NONAUTH, STATE_NONE, STATE_AUTH }, | 25 | { "AUTHENTICATE", imap4d_authenticate, STATE_NONAUTH, STATE_NONE, STATE_AUTH, NULL }, |
26 | { "LOGIN", imap4d_login, STATE_NONAUTH, STATE_NONE, STATE_AUTH }, | 26 | { "LOGIN", imap4d_login, STATE_NONAUTH, STATE_NONE, STATE_AUTH, NULL }, |
27 | { "SELECT", imap4d_select, STATE_AUTH | STATE_SEL, STATE_AUTH, STATE_SEL }, | 27 | { "SELECT", imap4d_select, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_SEL, NULL }, |
28 | { "EXAMINE", imap4d_examine, STATE_AUTH | STATE_SEL, STATE_AUTH, STATE_SEL }, | 28 | { "EXAMINE", imap4d_examine, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_SEL, NULL }, |
29 | { "CREATE", imap4d_create, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 29 | { "CREATE", imap4d_create, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
30 | { "DELETE", imap4d_delete, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 30 | { "DELETE", imap4d_delete, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
31 | { "RENAME", imap4d_rename, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 31 | { "RENAME", imap4d_rename, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
32 | { "SUBSCRIBE", imap4d_subscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 32 | { "SUBSCRIBE", imap4d_subscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
33 | { "UNSUBSCRIBE", imap4d_unsubscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 33 | { "UNSUBSCRIBE", imap4d_unsubscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
34 | { "LIST", imap4d_list, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 34 | { "LIST", imap4d_list, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
35 | { "LSUB", imap4d_lsub, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 35 | { "LSUB", imap4d_lsub, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
36 | { "STATUS", imap4d_status, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 36 | { "STATUS", imap4d_status, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
37 | { "APPEND", imap4d_append, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, | 37 | { "APPEND", imap4d_append, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
38 | { "CHECK", imap4d_check, STATE_SEL, STATE_NONE, STATE_NONE }, | 38 | { "CHECK", imap4d_check, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
39 | { "CLOSE", imap4d_close, STATE_SEL, STATE_AUTH, STATE_AUTH }, | 39 | { "CLOSE", imap4d_close, STATE_SEL, STATE_AUTH, STATE_AUTH, NULL }, |
40 | { "EXPUNGE", imap4d_expunge, STATE_SEL, STATE_NONE, STATE_NONE }, | 40 | { "EXPUNGE", imap4d_expunge, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
41 | { "SEARCH", imap4d_search, STATE_SEL, STATE_NONE, STATE_NONE }, | 41 | { "SEARCH", imap4d_search, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
42 | { "FETCH", imap4d_fetch, STATE_SEL, STATE_NONE, STATE_NONE }, | 42 | { "FETCH", imap4d_fetch, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
43 | { "STORE", imap4d_store, STATE_SEL, STATE_NONE, STATE_NONE }, | 43 | { "STORE", imap4d_store, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
44 | { "COPY", imap4d_copy, STATE_SEL, STATE_NONE, STATE_NONE }, | 44 | { "COPY", imap4d_copy, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
45 | { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE }, | 45 | { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, |
46 | { 0, 0, 0} | 46 | { NULL, 0, 0, 0, 0, NULL } |
47 | }; | 47 | }; | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_copy (struct imap4d_command *command, char *arg) | 25 | imap4d_copy (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Command not supported"); | 29 | return util_finish (command, RESP_NO, "Command not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_create (struct imap4d_command *command, char *arg) | 25 | imap4d_create (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Command not supported"); | 29 | return util_finish (command, RESP_NO, "Command not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_delete (struct imap4d_command *command, char *arg) | 25 | imap4d_delete (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Command not supported");; | 29 | return util_finish (command, RESP_NO, "Command not supported");; |
28 | } | 30 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_examine (struct imap4d_command *command, char *arg) | 25 | imap4d_examine (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return imap4d_select0 (command, arg, MU_STREAM_READ); | 29 | return imap4d_select0 (command, arg, MU_STREAM_READ); |
28 | } | 30 | } | ... | ... |
... | @@ -25,11 +25,12 @@ int | ... | @@ -25,11 +25,12 @@ int |
25 | imap4d_expunge (struct imap4d_command *command, char *arg) | 25 | imap4d_expunge (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | char *sp = NULL; | 27 | char *sp = NULL; |
28 | 28 | if (! (command->states & state)) | |
29 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
29 | if (util_getword (arg, &sp)) | 30 | if (util_getword (arg, &sp)) |
30 | return util_finish (command, RESP_NO, "Too many args"); | 31 | return util_finish (command, RESP_NO, "Too many args"); |
31 | 32 | ||
32 | /* FIXME: Check state, check for errors. */ | 33 | /* FIXME: check for errors. */ |
33 | mailbox_expunge (mbox); | 34 | mailbox_expunge (mbox); |
34 | return util_finish (command, RESP_OK, "Completed"); | 35 | return util_finish (command, RESP_OK, "Completed"); |
35 | } | 36 | } | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -21,6 +21,7 @@ int *ifile; | ... | @@ -21,6 +21,7 @@ int *ifile; |
21 | FILE *ofile; | 21 | FILE *ofile; |
22 | unsigned int timeout = 1800; /* RFC2060: 30 minutes, if enable. */ | 22 | unsigned int timeout = 1800; /* RFC2060: 30 minutes, if enable. */ |
23 | mailbox_t mbox; | 23 | mailbox_t mbox; |
24 | int state = STATE_NONAUTH; | ||
24 | 25 | ||
25 | static int imap4_mainloop __P ((int, int)); | 26 | static int imap4_mainloop __P ((int, int)); |
26 | 27 | ... | ... |
... | @@ -62,6 +62,8 @@ | ... | @@ -62,6 +62,8 @@ |
62 | #include <mailutils/body.h> | 62 | #include <mailutils/body.h> |
63 | #include <mailutils/address.h> | 63 | #include <mailutils/address.h> |
64 | #include <mailutils/registrar.h> | 64 | #include <mailutils/registrar.h> |
65 | #include <mailutils/filter.h> | ||
66 | #include <mailutils/stream.h> | ||
65 | 67 | ||
66 | #ifdef __cplusplus | 68 | #ifdef __cplusplus |
67 | extern "C" { | 69 | extern "C" { |
... | @@ -80,17 +82,17 @@ struct imap4d_command | ... | @@ -80,17 +82,17 @@ struct imap4d_command |
80 | const char *name; | 82 | const char *name; |
81 | int (*func) __P ((struct imap4d_command *, char *)); | 83 | int (*func) __P ((struct imap4d_command *, char *)); |
82 | int states; | 84 | int states; |
83 | int success; | ||
84 | int failure; | 85 | int failure; |
86 | int success; | ||
85 | char *tag; | 87 | char *tag; |
86 | }; | 88 | }; |
87 | 89 | ||
88 | /* Global variables and constants*/ | 90 | /* Global variables and constants*/ |
89 | #define STATE_NONE (1 << 0) | 91 | #define STATE_NONE (0) |
90 | #define STATE_NONAUTH (1 << 1) | 92 | #define STATE_NONAUTH (1 << 0) |
91 | #define STATE_AUTH (1 << 2) | 93 | #define STATE_AUTH (1 << 1) |
92 | #define STATE_SEL (1 << 3) | 94 | #define STATE_SEL (1 << 2) |
93 | #define STATE_LOGOUT (1 << 4) | 95 | #define STATE_LOGOUT (1 << 3) |
94 | 96 | ||
95 | #define STATE_ALL (STATE_NONE | STATE_NONAUTH | STATE_AUTH | STATE_SEL \ | 97 | #define STATE_ALL (STATE_NONE | STATE_NONAUTH | STATE_AUTH | STATE_SEL \ |
96 | | STATE_LOGOUT) | 98 | | STATE_LOGOUT) |
... | @@ -105,7 +107,7 @@ extern struct imap4d_command imap4d_command_table[]; | ... | @@ -105,7 +107,7 @@ extern struct imap4d_command imap4d_command_table[]; |
105 | extern FILE *ofile; | 107 | extern FILE *ofile; |
106 | extern unsigned int timeout; | 108 | extern unsigned int timeout; |
107 | extern mailbox_t mbox; | 109 | extern mailbox_t mbox; |
108 | extern unsigned int state; | 110 | extern int state; |
109 | 111 | ||
110 | /* Imap4 commands */ | 112 | /* Imap4 commands */ |
111 | int imap4d_capability __P ((struct imap4d_command *, char *)); | 113 | int imap4d_capability __P ((struct imap4d_command *, char *)); | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_list (struct imap4d_command *command, char *arg) | 25 | imap4d_list (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not supported"); | 29 | return util_finish (command, RESP_NO, "Not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -86,6 +86,8 @@ imap4d_login (struct imap4d_command *command, char *arg) | ... | @@ -86,6 +86,8 @@ imap4d_login (struct imap4d_command *command, char *arg) |
86 | int pamerror; | 86 | int pamerror; |
87 | #endif /* !USE_LIBPAM */ | 87 | #endif /* !USE_LIBPAM */ |
88 | 88 | ||
89 | if (! (command->states & state)) | ||
90 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
89 | username = util_getword (arg, &sp); | 91 | username = util_getword (arg, &sp); |
90 | pass = util_getword (NULL, &sp); | 92 | pass = util_getword (NULL, &sp); |
91 | 93 | ... | ... |
... | @@ -25,6 +25,8 @@ int | ... | @@ -25,6 +25,8 @@ int |
25 | imap4d_logout (struct imap4d_command *command, char *arg) | 25 | imap4d_logout (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | char *sp = NULL; | 27 | char *sp = NULL; |
28 | if (! (command->states & state)) | ||
29 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
28 | if (util_getword (arg, &sp)) | 30 | if (util_getword (arg, &sp)) |
29 | return util_finish (command, RESP_BAD, "Too many args"); | 31 | return util_finish (command, RESP_BAD, "Too many args"); |
30 | util_out (RESP_BYE, "Logging out"); | 32 | util_out (RESP_BYE, "Logging out"); | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_lsub (struct imap4d_command *command, char *arg) | 25 | imap4d_lsub (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not supported"); | 29 | return util_finish (command, RESP_NO, "Not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -22,6 +22,8 @@ int | ... | @@ -22,6 +22,8 @@ int |
22 | imap4d_noop (struct imap4d_command *command, char *arg) | 22 | imap4d_noop (struct imap4d_command *command, char *arg) |
23 | { | 23 | { |
24 | char *sp = NULL; | 24 | char *sp = NULL; |
25 | if (! (command->states & state)) | ||
26 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
25 | if (util_getword (arg, &sp)) | 27 | if (util_getword (arg, &sp)) |
26 | return util_finish (command, RESP_BAD, "Too many args"); | 28 | return util_finish (command, RESP_BAD, "Too many args"); |
27 | return util_finish (command, RESP_OK, "Completed"); | 29 | return util_finish (command, RESP_OK, "Completed"); | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_rename (struct imap4d_command *command, char *arg) | 25 | imap4d_rename (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not Supported"); | 29 | return util_finish (command, RESP_NO, "Not Supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -26,5 +26,7 @@ | ... | @@ -26,5 +26,7 @@ |
26 | int | 26 | int |
27 | imap4d_search (struct imap4d_command *command, char *arg) | 27 | imap4d_search (struct imap4d_command *command, char *arg) |
28 | { | 28 | { |
29 | if (! (command->states & state)) | ||
30 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
29 | return util_finish (command, RESP_NO, "Not supported"); | 31 | return util_finish (command, RESP_NO, "Not supported"); |
30 | } | 32 | } | ... | ... |
... | @@ -22,6 +22,8 @@ | ... | @@ -22,6 +22,8 @@ |
22 | int | 22 | int |
23 | imap4d_select (struct imap4d_command *command, char *arg) | 23 | imap4d_select (struct imap4d_command *command, char *arg) |
24 | { | 24 | { |
25 | if (! (command->states & state)) | ||
26 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
25 | return imap4d_select0 (command, arg, MU_STREAM_RDWR); | 27 | return imap4d_select0 (command, arg, MU_STREAM_RDWR); |
26 | } | 28 | } |
27 | 29 | ||
... | @@ -61,6 +63,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) | ... | @@ -61,6 +63,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) |
61 | unsigned long uidvalidity = 0; | 63 | unsigned long uidvalidity = 0; |
62 | size_t count = 0, recent = 0, unseen = 0, uidnext = 0; | 64 | size_t count = 0, recent = 0, unseen = 0, uidnext = 0; |
63 | 65 | ||
66 | state = STATE_SEL; | ||
64 | mailbox_uidvalidity (mbox, &uidvalidity); | 67 | mailbox_uidvalidity (mbox, &uidvalidity); |
65 | mailbox_uidnext (mbox, &uidnext); | 68 | mailbox_uidnext (mbox, &uidnext); |
66 | mailbox_messages_count (mbox, &count); | 69 | mailbox_messages_count (mbox, &count); | ... | ... |
... | @@ -27,6 +27,8 @@ imap4d_status (struct imap4d_command *command, char *arg) | ... | @@ -27,6 +27,8 @@ imap4d_status (struct imap4d_command *command, char *arg) |
27 | char *sp = NULL; | 27 | char *sp = NULL; |
28 | char *mailbox_name; | 28 | char *mailbox_name; |
29 | char *data; | 29 | char *data; |
30 | if (! (command->states & state)) | ||
31 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
30 | mailbox_name = util_getword (arg, &sp); | 32 | mailbox_name = util_getword (arg, &sp); |
31 | data = util_getword (NULL, &sp); | 33 | data = util_getword (NULL, &sp); |
32 | if (!mailbox_name || !data) | 34 | if (!mailbox_name || !data) | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_store (struct imap4d_command *command, char *arg) | 25 | imap4d_store (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not supported"); | 29 | return util_finish (command, RESP_NO, "Not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_subscribe (struct imap4d_command *command, char *arg) | 25 | imap4d_subscribe (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not supported"); | 29 | return util_finish (command, RESP_NO, "Not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -25,5 +25,7 @@ | ... | @@ -25,5 +25,7 @@ |
25 | int | 25 | int |
26 | imap4d_uid (struct imap4d_command *command, char *arg) | 26 | imap4d_uid (struct imap4d_command *command, char *arg) |
27 | { | 27 | { |
28 | if (! (command->states & state)) | ||
29 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
28 | return util_finish (command, RESP_NO, "Not supported"); | 30 | return util_finish (command, RESP_NO, "Not supported"); |
29 | } | 31 | } | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | int | 24 | int |
25 | imap4d_unsubscribe (struct imap4d_command *command, char *arg) | 25 | imap4d_unsubscribe (struct imap4d_command *command, char *arg) |
26 | { | 26 | { |
27 | if (! (command->states & state)) | ||
28 | return util_finish (command, RESP_BAD, "Wrong state"); | ||
27 | return util_finish (command, RESP_NO, "Not supported"); | 29 | return util_finish (command, RESP_NO, "Not supported"); |
28 | } | 30 | } | ... | ... |
... | @@ -207,6 +207,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) | ... | @@ -207,6 +207,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) |
207 | { | 207 | { |
208 | char *buf = NULL; | 208 | char *buf = NULL; |
209 | const char *resp; | 209 | const char *resp; |
210 | int new_state; | ||
210 | va_list ap; | 211 | va_list ap; |
211 | 212 | ||
212 | va_start (ap, format); | 213 | va_start (ap, format); |
... | @@ -216,6 +217,9 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) | ... | @@ -216,6 +217,9 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) |
216 | resp = sc2string (rc); | 217 | resp = sc2string (rc); |
217 | fprintf (ofile, "%s %s%s %s\r\n", command->tag, resp, command->name, buf); | 218 | fprintf (ofile, "%s %s%s %s\r\n", command->tag, resp, command->name, buf); |
218 | free (buf); | 219 | free (buf); |
220 | new_state = (rc == RESP_OK) ? command->success : command->failure; | ||
221 | if (new_state != STATE_NONE) | ||
222 | state = new_state; | ||
219 | return 0; | 223 | return 0; |
220 | } | 224 | } |
221 | 225 | ... | ... |
... | @@ -74,56 +74,70 @@ extern "C" { | ... | @@ -74,56 +74,70 @@ extern "C" { |
74 | struct _header; | 74 | struct _header; |
75 | typedef struct _header * header_t; | 75 | typedef struct _header * header_t; |
76 | 76 | ||
77 | extern int header_create __P ((header_t *, const char *, | 77 | extern int header_create __P ((header_t *, const char *, |
78 | size_t, void *)); | 78 | size_t, void *)); |
79 | extern void header_destroy __P ((header_t *, void *)); | 79 | extern void header_destroy __P ((header_t *, void *)); |
80 | extern void *header_get_owner __P ((header_t)); | 80 | extern void *header_get_owner __P ((header_t)); |
81 | 81 | ||
82 | extern int header_is_modified __P ((header_t)); | 82 | extern int header_is_modified __P ((header_t)); |
83 | extern int header_clear_modified __P ((header_t)); | 83 | extern int header_clear_modified __P ((header_t)); |
84 | 84 | ||
85 | extern int header_get_property __P ((header_t, property_t *)); | 85 | extern int header_get_property __P ((header_t, property_t *)); |
86 | extern int header_set_property __P ((header_t, property_t, void *)); | 86 | extern int header_set_property __P ((header_t, property_t, void *)); |
87 | 87 | ||
88 | extern int header_set_value __P ((header_t, const char *, | 88 | extern int header_set_value __P ((header_t, const char *, |
89 | const char *, int)); | 89 | const char *, int)); |
90 | extern int header_set_set_value __P ((header_t, int (*_set_value) | 90 | extern int header_set_set_value __P ((header_t, |
91 | __P ((header_t, const char *, | 91 | int (*_set_value) __P ((header_t, |
92 | const char *, int)), void *)); | 92 | const char *, |
93 | 93 | const char *, | |
94 | extern int header_get_value __P ((header_t, const char *, char *, | 94 | int)), |
95 | size_t, size_t *)); | 95 | void *)); |
96 | extern int header_set_get_value __P ((header_t, int (*_get_value) | 96 | |
97 | __P ((header_t, const char *, char *, | 97 | extern int header_get_value __P ((header_t, const char *, char *, |
98 | size_t, size_t *)), void *)); | 98 | size_t, size_t *)); |
99 | extern int header_set_get_fvalue __P ((header_t, int (*_get_value) | 99 | extern int header_aget_value __P ((header_t, const char *, char **)); |
100 | __P ((header_t, const char *, char *, | 100 | extern int header_set_get_value __P ((header_t, |
101 | size_t, size_t *)), void *)); | 101 | int (*_get_value) __P ((header_t, |
102 | 102 | const char *, | |
103 | extern int header_get_field_count __P ((header_t, size_t *)); | 103 | char *, |
104 | extern int header_get_field_value __P ((header_t, size_t, char *, | 104 | size_t, |
105 | size_t, size_t *)); | 105 | size_t *)), |
106 | extern int header_get_field_name __P ((header_t, size_t, char *, | 106 | void *)); |
107 | size_t, size_t *)); | 107 | extern int header_set_get_fvalue __P ((header_t, |
108 | 108 | int (*_get_value) __P ((header_t, | |
109 | extern int header_get_stream __P ((header_t, stream_t *)); | 109 | const char *, |
110 | extern int header_set_stream __P ((header_t, stream_t, void *)); | 110 | char *, |
111 | 111 | size_t, | |
112 | extern int header_size __P ((header_t, size_t *)); | 112 | size_t *)), |
113 | extern int header_set_size __P ((header_t, int (*_size) | 113 | void *)); |
114 | __P ((header_t, size_t *)), void *)); | 114 | |
115 | 115 | extern int header_get_field_count __P ((header_t, size_t *)); | |
116 | extern int header_lines __P ((header_t, size_t *)); | 116 | extern int header_get_field_value __P ((header_t, size_t, char *, |
117 | extern int header_set_lines __P ((header_t, | 117 | size_t, size_t *)); |
118 | int (*_lines) __P ((header_t, | 118 | extern int header_aget_field_value __P ((header_t, size_t, char **)); |
119 | size_t *)), | 119 | extern int header_get_field_name __P ((header_t, size_t, char *, |
120 | void *)); | 120 | size_t, size_t *)); |
121 | 121 | extern int header_aget_field_name __P ((header_t, size_t, char **)); | |
122 | extern int header_set_fill __P ((header_t, | 122 | |
123 | int (*_fill) __P ((header_t, char *, | 123 | extern int header_get_stream __P ((header_t, stream_t *)); |
124 | size_t, off_t, | 124 | extern int header_set_stream __P ((header_t, stream_t, void *)); |
125 | |||
126 | extern int header_size __P ((header_t, size_t *)); | ||
127 | extern int header_set_size __P ((header_t, int (*_size) | ||
128 | __P ((header_t, size_t *)), void *)); | ||
129 | |||
130 | extern int header_lines __P ((header_t, size_t *)); | ||
131 | extern int header_set_lines __P ((header_t, | ||
132 | int (*_lines) __P ((header_t, | ||
133 | size_t *)), | ||
134 | void *)); | ||
135 | |||
136 | extern int header_set_fill __P ((header_t, | ||
137 | int (*_fill) __P ((header_t, char *, | ||
138 | size_t, off_t, | ||
125 | size_t *)), | 139 | size_t *)), |
126 | void *owner)); | 140 | void *owner)); |
127 | #ifdef __cplusplus | 141 | #ifdef __cplusplus |
128 | } | 142 | } |
129 | #endif | 143 | #endif | ... | ... |
... | @@ -119,11 +119,12 @@ extern int stream_get_state __P ((stream_t, int *pstate)); | ... | @@ -119,11 +119,12 @@ extern int stream_get_state __P ((stream_t, int *pstate)); |
119 | /* Misc. */ | 119 | /* Misc. */ |
120 | extern int file_stream_create __P ((stream_t *stream)); | 120 | extern int file_stream_create __P ((stream_t *stream)); |
121 | extern int mapfile_stream_create __P ((stream_t *stream)); | 121 | extern int mapfile_stream_create __P ((stream_t *stream)); |
122 | extern int memory_stream_create __P ((stream_t *stream)); | ||
123 | extern int tcp_stream_create __P ((stream_t *stream)); | ||
122 | extern int encoder_stream_create __P ((stream_t *stream, stream_t iostream, | 124 | extern int encoder_stream_create __P ((stream_t *stream, stream_t iostream, |
123 | const char *encoding)); | 125 | const char *encoding)); |
124 | extern int decoder_stream_create __P ((stream_t *stream, stream_t iostream, | 126 | extern int decoder_stream_create __P ((stream_t *stream, stream_t iostream, |
125 | const char *encoding)); | 127 | const char *encoding)); |
126 | extern int tcp_stream_create __P ((stream_t *stream)); | ||
127 | 128 | ||
128 | #ifdef __cplusplus | 129 | #ifdef __cplusplus |
129 | } | 130 | } | ... | ... |
... | @@ -41,8 +41,7 @@ static void | ... | @@ -41,8 +41,7 @@ static void |
41 | _file_destroy (stream_t stream) | 41 | _file_destroy (stream_t stream) |
42 | { | 42 | { |
43 | struct _file_stream *fs = stream_get_owner (stream); | 43 | struct _file_stream *fs = stream_get_owner (stream); |
44 | 44 | if (fs->file) | |
45 | if (fs && fs->file) | ||
46 | fclose (fs->file); | 45 | fclose (fs->file); |
47 | free (fs); | 46 | free (fs); |
48 | } | 47 | } |
... | @@ -55,9 +54,6 @@ _file_read (stream_t stream, char *optr, size_t osize, | ... | @@ -55,9 +54,6 @@ _file_read (stream_t stream, char *optr, size_t osize, |
55 | size_t n; | 54 | size_t n; |
56 | int err = 0; | 55 | int err = 0; |
57 | 56 | ||
58 | if (fs == NULL) | ||
59 | return EINVAL; | ||
60 | |||
61 | if (fs->offset != offset) | 57 | if (fs->offset != offset) |
62 | { | 58 | { |
63 | if (fseek (fs->file, offset, SEEK_SET) != 0) | 59 | if (fseek (fs->file, offset, SEEK_SET) != 0) |
... | @@ -87,9 +83,6 @@ _file_readline (stream_t stream, char *optr, size_t osize, | ... | @@ -87,9 +83,6 @@ _file_readline (stream_t stream, char *optr, size_t osize, |
87 | size_t n = 0; | 83 | size_t n = 0; |
88 | int err = 0; | 84 | int err = 0; |
89 | 85 | ||
90 | if (fs == NULL) | ||
91 | return EINVAL; | ||
92 | |||
93 | if (fs->offset != offset) | 86 | if (fs->offset != offset) |
94 | { | 87 | { |
95 | if (fseek (fs->file, offset, SEEK_SET) != 0) | 88 | if (fseek (fs->file, offset, SEEK_SET) != 0) |
... | @@ -123,9 +116,6 @@ _file_write (stream_t stream, const char *iptr, size_t isize, | ... | @@ -123,9 +116,6 @@ _file_write (stream_t stream, const char *iptr, size_t isize, |
123 | size_t n; | 116 | size_t n; |
124 | int err = 0; | 117 | int err = 0; |
125 | 118 | ||
126 | if (fs == NULL) | ||
127 | return EINVAL; | ||
128 | |||
129 | if (fs->offset != offset) | 119 | if (fs->offset != offset) |
130 | { | 120 | { |
131 | if (fseek (fs->file, offset, SEEK_SET) != 0) | 121 | if (fseek (fs->file, offset, SEEK_SET) != 0) |
... | @@ -153,9 +143,6 @@ static int | ... | @@ -153,9 +143,6 @@ static int |
153 | _file_truncate (stream_t stream, off_t len) | 143 | _file_truncate (stream_t stream, off_t len) |
154 | { | 144 | { |
155 | struct _file_stream *fs = stream_get_owner (stream); | 145 | struct _file_stream *fs = stream_get_owner (stream); |
156 | |||
157 | if (fs == NULL) | ||
158 | return EINVAL; | ||
159 | if (ftruncate (fileno(fs->file), len) != 0) | 146 | if (ftruncate (fileno(fs->file), len) != 0) |
160 | return errno; | 147 | return errno; |
161 | return 0; | 148 | return 0; |
... | @@ -166,9 +153,6 @@ _file_size (stream_t stream, off_t *psize) | ... | @@ -166,9 +153,6 @@ _file_size (stream_t stream, off_t *psize) |
166 | { | 153 | { |
167 | struct _file_stream *fs = stream_get_owner (stream); | 154 | struct _file_stream *fs = stream_get_owner (stream); |
168 | struct stat stbuf; | 155 | struct stat stbuf; |
169 | |||
170 | if (fs == NULL) | ||
171 | return EINVAL; | ||
172 | fflush (fs->file); | 156 | fflush (fs->file); |
173 | if (fstat(fileno(fs->file), &stbuf) == -1) | 157 | if (fstat(fileno(fs->file), &stbuf) == -1) |
174 | return errno; | 158 | return errno; |
... | @@ -181,9 +165,6 @@ static int | ... | @@ -181,9 +165,6 @@ static int |
181 | _file_flush (stream_t stream) | 165 | _file_flush (stream_t stream) |
182 | { | 166 | { |
183 | struct _file_stream *fs = stream_get_owner (stream); | 167 | struct _file_stream *fs = stream_get_owner (stream); |
184 | |||
185 | if (fs == NULL) | ||
186 | return EINVAL; | ||
187 | return fflush (fs->file); | 168 | return fflush (fs->file); |
188 | } | 169 | } |
189 | 170 | ||
... | @@ -191,9 +172,6 @@ static int | ... | @@ -191,9 +172,6 @@ static int |
191 | _file_get_fd (stream_t stream, int *pfd) | 172 | _file_get_fd (stream_t stream, int *pfd) |
192 | { | 173 | { |
193 | struct _file_stream *fs = stream_get_owner (stream); | 174 | struct _file_stream *fs = stream_get_owner (stream); |
194 | |||
195 | if (fs == NULL) | ||
196 | return EINVAL; | ||
197 | if (pfd) | 175 | if (pfd) |
198 | *pfd = fileno (fs->file); | 176 | *pfd = fileno (fs->file); |
199 | return 0; | 177 | return 0; |
... | @@ -204,9 +182,6 @@ _file_close (stream_t stream) | ... | @@ -204,9 +182,6 @@ _file_close (stream_t stream) |
204 | { | 182 | { |
205 | struct _file_stream *fs = stream_get_owner (stream); | 183 | struct _file_stream *fs = stream_get_owner (stream); |
206 | int err = 0; | 184 | int err = 0; |
207 | |||
208 | if (fs == NULL) | ||
209 | return EINVAL; | ||
210 | if (fs->file) | 185 | if (fs->file) |
211 | { | 186 | { |
212 | if (fclose (fs->file) != 0) | 187 | if (fclose (fs->file) != 0) |
... | @@ -226,9 +201,6 @@ _file_open (stream_t stream, const char *filename, int port, int flags) | ... | @@ -226,9 +201,6 @@ _file_open (stream_t stream, const char *filename, int port, int flags) |
226 | 201 | ||
227 | (void)port; /* Ignored. */ | 202 | (void)port; /* Ignored. */ |
228 | 203 | ||
229 | if (fs == NULL) | ||
230 | return EINVAL; | ||
231 | |||
232 | if (fs->file) | 204 | if (fs->file) |
233 | { | 205 | { |
234 | fclose (fs->file); | 206 | fclose (fs->file); | ... | ... |
... | @@ -189,7 +189,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, | ... | @@ -189,7 +189,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, |
189 | rfc822->residue = 0; | 189 | rfc822->residue = 0; |
190 | } | 190 | } |
191 | buffer += nread; | 191 | buffer += nread; |
192 | } while (buflen > 0 || !isreadline); | 192 | } while (buflen > 0 && !isreadline); |
193 | 193 | ||
194 | if (isreadline) | 194 | if (isreadline) |
195 | *buffer = '\0'; | 195 | *buffer = '\0'; | ... | ... |
... | @@ -495,6 +495,25 @@ header_get_value (header_t header, const char *name, char *buffer, | ... | @@ -495,6 +495,25 @@ header_get_value (header_t header, const char *name, char *buffer, |
495 | } | 495 | } |
496 | 496 | ||
497 | int | 497 | int |
498 | header_aget_value (header_t header, const char *name, char **pvalue) | ||
499 | { | ||
500 | char *value; | ||
501 | size_t n = 0; | ||
502 | int status = header_get_value (header, name, NULL, 0, &n); | ||
503 | if (status == 0) | ||
504 | { | ||
505 | value = calloc (n + 1, 1); | ||
506 | if (value == NULL) | ||
507 | return ENOMEM; | ||
508 | header_get_value (header, name, value, n + 1, NULL); | ||
509 | *pvalue = value; | ||
510 | } | ||
511 | else | ||
512 | *pvalue = strdup (""); | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | int | ||
498 | header_get_field_count (header_t header, size_t *pcount) | 517 | header_get_field_count (header_t header, size_t *pcount) |
499 | { | 518 | { |
500 | if (header == NULL) | 519 | if (header == NULL) |
... | @@ -553,6 +572,25 @@ header_get_field_name (header_t header, size_t num, char *buf, | ... | @@ -553,6 +572,25 @@ header_get_field_name (header_t header, size_t num, char *buf, |
553 | } | 572 | } |
554 | 573 | ||
555 | int | 574 | int |
575 | header_aget_field_name (header_t header, size_t num, char **pvalue) | ||
576 | { | ||
577 | char *value; | ||
578 | size_t n = 0; | ||
579 | int status = header_get_field_name (header, num, NULL, 0, &n); | ||
580 | if (status == 0) | ||
581 | { | ||
582 | value = calloc (n + 1, 1); | ||
583 | if (value == NULL) | ||
584 | return ENOMEM; | ||
585 | header_get_field_name (header, num, value, n + 1, NULL); | ||
586 | *pvalue = value; | ||
587 | } | ||
588 | else | ||
589 | *pvalue = strdup (""); | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | int | ||
556 | header_get_field_value (header_t header, size_t num, char *buf, | 594 | header_get_field_value (header_t header, size_t num, char *buf, |
557 | size_t buflen, size_t *nwritten) | 595 | size_t buflen, size_t *nwritten) |
558 | { | 596 | { |
... | @@ -588,6 +626,25 @@ header_get_field_value (header_t header, size_t num, char *buf, | ... | @@ -588,6 +626,25 @@ header_get_field_value (header_t header, size_t num, char *buf, |
588 | } | 626 | } |
589 | 627 | ||
590 | int | 628 | int |
629 | header_aget_field_value (header_t header, size_t num, char **pvalue) | ||
630 | { | ||
631 | char *value; | ||
632 | size_t n = 0; | ||
633 | int status = header_get_field_value (header, num, NULL, 0, &n); | ||
634 | if (status == 0) | ||
635 | { | ||
636 | value = calloc (n + 1, 1); | ||
637 | if (value == NULL) | ||
638 | return ENOMEM; | ||
639 | header_get_field_value (header, num, value, n + 1, NULL); | ||
640 | *pvalue = value; | ||
641 | } | ||
642 | else | ||
643 | *pvalue = strdup (""); | ||
644 | return status; | ||
645 | } | ||
646 | |||
647 | int | ||
591 | header_set_lines (header_t header, int (*_lines) | 648 | header_set_lines (header_t header, int (*_lines) |
592 | (header_t, size_t *), void *owner) | 649 | (header_t, size_t *), void *owner) |
593 | { | 650 | { | ... | ... |
... | @@ -48,7 +48,7 @@ _mapfile_destroy (stream_t stream) | ... | @@ -48,7 +48,7 @@ _mapfile_destroy (stream_t stream) |
48 | { | 48 | { |
49 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 49 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
50 | 50 | ||
51 | if (mfs && mfs->ptr != MAP_FAILED) | 51 | if (mfs->ptr != MAP_FAILED) |
52 | { | 52 | { |
53 | munmap (mfs->ptr, mfs->size); | 53 | munmap (mfs->ptr, mfs->size); |
54 | close (mfs->fd); | 54 | close (mfs->fd); |
... | @@ -61,21 +61,17 @@ _mapfile_read (stream_t stream, char *optr, size_t osize, | ... | @@ -61,21 +61,17 @@ _mapfile_read (stream_t stream, char *optr, size_t osize, |
61 | off_t offset, size_t *nbytes) | 61 | off_t offset, size_t *nbytes) |
62 | { | 62 | { |
63 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 63 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
64 | size_t n; | 64 | size_t n = 0; |
65 | 65 | ||
66 | if (mfs == NULL || mfs->ptr == MAP_FAILED) | 66 | if (mfs->ptr == MAP_FAILED) |
67 | return EINVAL; | 67 | return EINVAL; |
68 | 68 | ||
69 | if (offset >= (off_t)mfs->size) | 69 | if (offset < (off_t)mfs->size) |
70 | { | 70 | { |
71 | if (nbytes) | 71 | n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize; |
72 | *nbytes = 0; | 72 | memcpy (optr, mfs->ptr + offset, n); |
73 | return 0; | ||
74 | } | 73 | } |
75 | 74 | ||
76 | n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize; | ||
77 | memcpy (optr, mfs->ptr + offset, n); | ||
78 | |||
79 | if (nbytes) | 75 | if (nbytes) |
80 | *nbytes = n; | 76 | *nbytes = n; |
81 | return 0; | 77 | return 0; |
... | @@ -89,24 +85,21 @@ _mapfile_readline (stream_t stream, char *optr, size_t osize, | ... | @@ -89,24 +85,21 @@ _mapfile_readline (stream_t stream, char *optr, size_t osize, |
89 | char *nl; | 85 | char *nl; |
90 | size_t n = 0; | 86 | size_t n = 0; |
91 | 87 | ||
92 | if (mfs == NULL || mfs->ptr == MAP_FAILED) | 88 | if (mfs->ptr == MAP_FAILED) |
93 | return EINVAL; | 89 | return EINVAL; |
94 | /* Save space for the null byte. */ | 90 | |
95 | osize--; | 91 | if (offset < (off_t)mfs->size) |
96 | if (offset >= (off_t)mfs->size) | ||
97 | { | 92 | { |
98 | if (nbytes) | 93 | /* Save space for the null byte. */ |
99 | *nbytes = 0; | 94 | osize--; |
100 | return 0; | 95 | nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); |
96 | n = (nl) ? nl - (mfs->ptr + offset) + 1 : mfs->size - offset; | ||
97 | n = (n > osize) ? osize : n; | ||
98 | memcpy (optr, mfs->ptr + offset, n); | ||
99 | optr[n] = '\0'; | ||
101 | } | 100 | } |
102 | |||
103 | nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); | ||
104 | n = nl - (mfs->ptr + offset) + 1; | ||
105 | n = (n > osize) ? osize : n; | ||
106 | memcpy (optr, mfs->ptr + offset, n); | ||
107 | if (nbytes) | 101 | if (nbytes) |
108 | *nbytes = n; | 102 | *nbytes = n; |
109 | optr[n] = '\0'; | ||
110 | return 0; | 103 | return 0; |
111 | } | 104 | } |
112 | 105 | ||
... | @@ -116,7 +109,7 @@ _mapfile_write (stream_t stream, const char *iptr, size_t isize, | ... | @@ -116,7 +109,7 @@ _mapfile_write (stream_t stream, const char *iptr, size_t isize, |
116 | { | 109 | { |
117 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 110 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
118 | 111 | ||
119 | if (mfs == NULL || mfs->ptr == MAP_FAILED) | 112 | if (mfs->ptr == MAP_FAILED) |
120 | return EINVAL; | 113 | return EINVAL; |
121 | 114 | ||
122 | if (! (mfs->flags & PROT_WRITE)) | 115 | if (! (mfs->flags & PROT_WRITE)) |
... | @@ -155,7 +148,7 @@ static int | ... | @@ -155,7 +148,7 @@ static int |
155 | _mapfile_truncate (stream_t stream, off_t len) | 148 | _mapfile_truncate (stream_t stream, off_t len) |
156 | { | 149 | { |
157 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 150 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
158 | if (mfs == NULL || mfs->ptr == MAP_FAILED) | 151 | if (mfs->ptr == MAP_FAILED) |
159 | return EINVAL; | 152 | return EINVAL; |
160 | /* Remap. */ | 153 | /* Remap. */ |
161 | if (munmap (mfs->ptr, mfs->size) != 0) | 154 | if (munmap (mfs->ptr, mfs->size) != 0) |
... | @@ -185,7 +178,7 @@ _mapfile_size (stream_t stream, off_t *psize) | ... | @@ -185,7 +178,7 @@ _mapfile_size (stream_t stream, off_t *psize) |
185 | struct stat stbuf; | 178 | struct stat stbuf; |
186 | int err = 0; | 179 | int err = 0; |
187 | 180 | ||
188 | if (mfs == NULL || mfs->ptr == MAP_FAILED) | 181 | if (mfs->ptr == MAP_FAILED) |
189 | return EINVAL; | 182 | return EINVAL; |
190 | msync (mfs->ptr, mfs->size, MS_SYNC); | 183 | msync (mfs->ptr, mfs->size, MS_SYNC); |
191 | if (fstat(mfs->fd, &stbuf) != 0) | 184 | if (fstat(mfs->fd, &stbuf) != 0) |
... | @@ -220,8 +213,6 @@ static int | ... | @@ -220,8 +213,6 @@ static int |
220 | _mapfile_flush (stream_t stream) | 213 | _mapfile_flush (stream_t stream) |
221 | { | 214 | { |
222 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 215 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
223 | if (mfs == NULL) | ||
224 | return EINVAL; | ||
225 | return msync (mfs->ptr, mfs->size, MS_SYNC); | 216 | return msync (mfs->ptr, mfs->size, MS_SYNC); |
226 | } | 217 | } |
227 | 218 | ||
... | @@ -229,8 +220,6 @@ static int | ... | @@ -229,8 +220,6 @@ static int |
229 | _mapfile_get_fd (stream_t stream, int *pfd) | 220 | _mapfile_get_fd (stream_t stream, int *pfd) |
230 | { | 221 | { |
231 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 222 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
232 | if (mfs == NULL) | ||
233 | return EINVAL; | ||
234 | if (pfd) | 223 | if (pfd) |
235 | *pfd = mfs->fd; | 224 | *pfd = mfs->fd; |
236 | return 0; | 225 | return 0; |
... | @@ -241,7 +230,7 @@ _mapfile_close (stream_t stream) | ... | @@ -241,7 +230,7 @@ _mapfile_close (stream_t stream) |
241 | { | 230 | { |
242 | struct _mapfile_stream *mfs = stream_get_owner (stream); | 231 | struct _mapfile_stream *mfs = stream_get_owner (stream); |
243 | int err = 0; | 232 | int err = 0; |
244 | if (mfs && mfs->ptr != MAP_FAILED) | 233 | if (mfs->ptr != MAP_FAILED) |
245 | { | 234 | { |
246 | if (munmap (mfs->ptr, mfs->size) != 0) | 235 | if (munmap (mfs->ptr, mfs->size) != 0) |
247 | err = errno; | 236 | err = errno; |
... | @@ -262,9 +251,6 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags) | ... | @@ -262,9 +251,6 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags) |
262 | 251 | ||
263 | (void)port; /* Ignored. */ | 252 | (void)port; /* Ignored. */ |
264 | 253 | ||
265 | if (mfs == NULL) | ||
266 | return EINVAL; | ||
267 | |||
268 | /* Close any previous file. */ | 254 | /* Close any previous file. */ |
269 | if (mfs->ptr != MAP_FAILED) | 255 | if (mfs->ptr != MAP_FAILED) |
270 | { | 256 | { | ... | ... |
mailbox/memory_stream.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <errno.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | #include <sys/types.h> | ||
27 | |||
28 | #include <mailutils/stream.h> | ||
29 | |||
30 | struct _memory_stream | ||
31 | { | ||
32 | char *ptr; | ||
33 | size_t size; | ||
34 | }; | ||
35 | |||
36 | static void | ||
37 | _memory_destroy (stream_t stream) | ||
38 | { | ||
39 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
40 | if (mfs && mfs->ptr != NULL) | ||
41 | free (mfs->ptr); | ||
42 | free (mfs); | ||
43 | } | ||
44 | |||
45 | static int | ||
46 | _memory_read (stream_t stream, char *optr, size_t osize, | ||
47 | off_t offset, size_t *nbytes) | ||
48 | { | ||
49 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
50 | size_t n = 0; | ||
51 | if (mfs->ptr != NULL && (offset <= (off_t)mfs->size)) | ||
52 | { | ||
53 | n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize; | ||
54 | memcpy (optr, mfs->ptr + offset, n); | ||
55 | } | ||
56 | if (nbytes) | ||
57 | *nbytes = n; | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int | ||
62 | _memory_readline (stream_t stream, char *optr, size_t osize, | ||
63 | off_t offset, size_t *nbytes) | ||
64 | { | ||
65 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
66 | char *nl; | ||
67 | size_t n = 0; | ||
68 | if (mfs->ptr && (offset < (off_t)mfs->size)) | ||
69 | { | ||
70 | /* Save space for the null byte. */ | ||
71 | osize--; | ||
72 | nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset); | ||
73 | n = (nl) ? nl - (mfs->ptr + offset) + 1 : mfs->size - offset; | ||
74 | n = (n > osize) ? osize : n; | ||
75 | memcpy (optr, mfs->ptr + offset, n); | ||
76 | optr[n] = '\0'; | ||
77 | } | ||
78 | if (nbytes) | ||
79 | *nbytes = n; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int | ||
84 | _memory_write (stream_t stream, const char *iptr, size_t isize, | ||
85 | off_t offset, size_t *nbytes) | ||
86 | { | ||
87 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
88 | |||
89 | /* Bigger we have to realloc. */ | ||
90 | if (mfs->size < (offset + isize)) | ||
91 | { | ||
92 | char *tmp = realloc (mfs->ptr, offset + isize); | ||
93 | if (tmp == NULL) | ||
94 | return ENOMEM; | ||
95 | mfs->ptr = tmp; | ||
96 | mfs->size = offset + isize; | ||
97 | } | ||
98 | |||
99 | memcpy (mfs->ptr + offset, iptr, isize); | ||
100 | if (nbytes) | ||
101 | *nbytes = isize; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int | ||
106 | _memory_truncate (stream_t stream, off_t len) | ||
107 | { | ||
108 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
109 | |||
110 | if (len == 0) | ||
111 | { | ||
112 | free (mfs->ptr); | ||
113 | mfs->ptr = NULL; | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | char *tmp = realloc (mfs, len); | ||
118 | if (tmp == NULL) | ||
119 | return ENOMEM; | ||
120 | mfs->ptr = tmp; | ||
121 | } | ||
122 | mfs->size = len; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int | ||
127 | _memory_size (stream_t stream, off_t *psize) | ||
128 | { | ||
129 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
130 | if (psize) | ||
131 | *psize = mfs->size; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int | ||
136 | _memory_close (stream_t stream) | ||
137 | { | ||
138 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
139 | if (mfs->ptr) | ||
140 | { | ||
141 | free (mfs->ptr); | ||
142 | mfs->ptr = NULL; | ||
143 | mfs->size = 0; | ||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | _memory_open (stream_t stream, const char *filename, int port, int flags) | ||
150 | { | ||
151 | struct _memory_stream *mfs = stream_get_owner (stream); | ||
152 | |||
153 | (void)port; /* Ignored. */ | ||
154 | (void)filename; /* Ignored. */ | ||
155 | (void)flags; /* Ignored. */ | ||
156 | |||
157 | /* Close any previous file. */ | ||
158 | if (mfs->ptr) | ||
159 | { | ||
160 | free (mfs->ptr); | ||
161 | mfs->ptr = NULL; | ||
162 | mfs->size = 0; | ||
163 | } | ||
164 | stream_set_flags (stream, flags |MU_STREAM_NO_CHECK); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | int | ||
169 | memory_stream_create (stream_t *stream) | ||
170 | { | ||
171 | struct _memory_stream *mfs; | ||
172 | int ret; | ||
173 | |||
174 | if (stream == NULL) | ||
175 | return EINVAL; | ||
176 | |||
177 | mfs = calloc (1, sizeof (*mfs)); | ||
178 | if (mfs == NULL) | ||
179 | return ENOMEM; | ||
180 | |||
181 | mfs->ptr = NULL; | ||
182 | mfs->size = 0; | ||
183 | |||
184 | ret = stream_create (stream, MU_STREAM_NO_CHECK, mfs); | ||
185 | if (ret != 0) | ||
186 | { | ||
187 | free (mfs); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | stream_set_open (*stream, _memory_open, mfs); | ||
192 | stream_set_close (*stream, _memory_close, mfs); | ||
193 | stream_set_read (*stream, _memory_read, mfs); | ||
194 | stream_set_readline (*stream, _memory_readline, mfs); | ||
195 | stream_set_write (*stream, _memory_write, mfs); | ||
196 | stream_set_truncate (*stream, _memory_truncate, mfs); | ||
197 | stream_set_size (*stream, _memory_size, mfs); | ||
198 | stream_set_destroy (*stream, _memory_destroy, mfs); | ||
199 | return 0; | ||
200 | } |
-
Please register or sign in to post a comment