summaryrefslogtreecommitdiff
path: root/pith/stream.h
diff options
context:
space:
mode:
Diffstat (limited to 'pith/stream.h')
-rw-r--r--pith/stream.h471
1 files changed, 471 insertions, 0 deletions
diff --git a/pith/stream.h b/pith/stream.h
new file mode 100644
index 00000000..eafe6f24
--- /dev/null
+++ b/pith/stream.h
@@ -0,0 +1,471 @@
+/*
+ * $Id: stream.h 768 2007-10-24 00:10:03Z hubert@u.washington.edu $
+ *
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+#ifndef PITH_STREAM_INCLUDED
+#define PITH_STREAM_INCLUDED
+
+
+#include "../pith/context.h"
+#include "../pith/msgno.h"
+#include "../pith/savetype.h"
+
+
+#define AOS_NONE 0x00 /* alredy_open_stream: no flag */
+#define AOS_RW_ONLY 0x01 /* don't match readonly streams */
+
+/* pine_mail_list flags */
+#define PML_IS_MOVE_MBOX 0x01
+
+
+/*
+ * The stream pool is where we keep pointers to open streams. Some of them are
+ * actively being used, some are connected to a folder but aren't actively
+ * in use, some are random temporary use streams left open for possible
+ * re-use. Each open stream should be in the streams array, which is of
+ * size nstream altogether. Streams which are not to be re-used (don't have
+ * the flag SP_USEPOOL set) are in the array anyway.
+ */
+
+/*
+ * Structure holds global information about the stream pool. The per-stream
+ * information is stored in a PER_STREAM_S struct attached to each stream.
+ */
+typedef struct stream_pool {
+ int max_remstream; /* max implicitly cached remote streams */
+ int nstream; /* size of streams array */
+ MAILSTREAM **streams; /* the array of streams in stream pool */
+} SP_S;
+
+/*
+ * Pine's private per-stream data stored on the c-client's stream
+ * spare pointer.
+ */
+typedef struct pine_per_stream_data {
+ MSGNO_S *msgmap;
+ CONTEXT_S *context; /* context fldr was interpreted in */
+ char *fldr; /* folder name, alloced copy */
+ unsigned long flags;
+ unsigned long icache_flags;
+ int ref_cnt;
+ long new_mail_count; /* new mail since the last new_mail check */
+ long mail_since_cmd; /* new mail since last key pressed */
+ long expunge_count;
+ long first_unseen;
+ long recent_since_visited;
+ int check_cnt;
+ time_t first_status_change;
+ time_t last_ping; /* Keeps track of when the last */
+ /* command was. The command wasn't */
+ /* necessarily a ping. */
+ time_t last_expunged_reaper; /* Some IMAP commands defer the */
+ /* return of EXPUNGE responses. */
+ /* This is the time of the last */
+ /* command which did not defer. */
+ time_t last_chkpnt_done;
+ time_t last_use_time;
+ time_t last_activity;
+ imapuid_t saved_uid_validity;
+ imapuid_t saved_uid_last;
+ char *saved_cur_msg_id;
+ unsigned unsorted_newmail:1;
+ unsigned need_to_rethread:1;
+ unsigned io_error_on_stream:1;
+ unsigned mail_box_changed:1;
+ unsigned viewing_a_thread:1;
+ unsigned dead_stream:1;
+ unsigned noticed_dead_stream:1;
+ unsigned closing:1;
+} PER_STREAM_S;
+
+/*
+ * Complicated set of flags for stream pool cache.
+ * LOCKED, PERMLOCKED, TEMPUSE, and USEPOOL are flags stored in the stream
+ * flags of the PER_STREAM_S structure.
+ *
+ * SP_LOCKED -- In use, don't re-use this.
+ * That isn't a good description of SP_LOCKED. Every time
+ * we pine_mail_open a stream it is SP_LOCKED and a ref_cnt
+ * is incremented. Pine_mail_close decrements the ref_cnt
+ * and unlocks it when we get to zero.
+ * SP_PERMLOCKED -- Should always be kept open, like INBOX. Right now the
+ * only significance of this is that the expunge_and_close
+ * won't happen if this is set (like the way INBOX works).
+ * If a stream is PERMLOCKED it should no doubt be LOCKED
+ * as well (it isn't done implicitly in the tests).
+ * SP_INBOX -- This stream is open on the INBOX.
+ * SP_USERFLDR -- This stream was opened by the user explicitly, not
+ * implicitly like would happen with a save or a remote
+ * address book, etc.
+ * SP_FILTERED -- This stream was opened by the user explicitly and
+ * filtered.
+ * SP_TEMPUSE -- If a stream is not SP_LOCKED, that says we can re-use
+ * it if need be but we should prefer to use another unused
+ * slot if there is one. If a stream is marked TEMPUSE we
+ * should consider re-using it before we consider re-using
+ * a stream which is not LOCKED but not marked TEMPUSE.
+ * This flag is not only stored in the PER_STREAM_S flags,
+ * it is also an input argument to sp_stream_get.
+ * It may make sense to mark a stream both SP_LOCKED and
+ * SP_TEMPUSE. That way, when we close the stream it will
+ * be SP_TEMPUSE and more re-usable than if we didn't.
+ * SP_USEPOOL -- Passed to pine_mail_open, it means to consider the
+ * stream pool when opening and to put it into the stream
+ * pool after we open it. If this is not set when we open,
+ * we do an honest open and an honest close when we close.
+ *
+ * These flags are input flags to sp_stream_get.
+ * SP_MATCH -- We're looking for a stream that is already open on
+ * this mailbox. This is good if we are reopening the
+ * same mailbox we already had opened.
+ * SP_SAME -- We're looking for a stream that is open to the same
+ * server. For example, we might want to do a STATUS
+ * command or a DELETE. We could use any stream that
+ * is already open for this. Unless SP_MATCH is also
+ * set, this will not return exact matches. (For example,
+ * it is a bad idea to do a STATUS command on an already
+ * selected mailbox. There may be locking problems if you
+ * try to delete a folder that is selected...)
+ * SP_TEMPUSE -- The checking for SP_SAME streams is controlled by these
+ * SP_UNLOCKED two flags. If SP_TEMPUSE is set then we will only match
+ * streams which are marked TEMPUSE and not LOCKED.
+ * If TEMPUSE is not set but UNLOCKED is, then we will
+ * match on any same stream that is not locked. We'll choose
+ * SP_TEMPUSE streams in preference to those that aren't
+ * SP_TEMPUSE. If neither SP_TEMPUSE or SP_UNLOCKED is set,
+ * then we'll consider any stream, even if it is locked.
+ * We'll still prefer TEMPUSE first, then UNLOCKED, then any.
+ *
+ * Careful with the values of these flags. Some of them should really be
+ * in separate name spaces, but we've combined all of them for convenience.
+ * In particular, SP_USERFLDR, SP_INBOX, SP_USEPOOL, and SP_TEMPUSE are
+ * all passed in the pine_mail_open flags argument, alongside OP_DEBUG and
+ * friends from c-client. So they have to have different values than
+ * those OP_ flags. SP_PERMLOCKED was passed at one time but isn't anymore.
+ * Still, include it in the careful set. C-client reserves the bits
+ * 0xff000000 for client flags.
+ */
+
+#define SP_USERFLDR 0x01000000
+#define SP_INBOX 0x02000000
+#define SP_USEPOOL 0x04000000
+#define SP_TEMPUSE 0x08000000
+
+#define SP_PERMLOCKED 0x10000000
+#define SP_LOCKED 0x20000000
+
+#define SP_MATCH 0x00100000
+#define SP_SAME 0x00200000
+#define SP_UNLOCKED 0x00400000
+#define SP_FILTERED 0x00800000
+#define SP_RO_OK 0x01000000 /* Readonly stream ok for SP_MATCH */
+
+/* these are for icache_flags */
+#define SP_NEED_FORMAT_SETUP 0x01
+#define SP_FORMAT_INCLUDES_MSGNO 0x02
+#define SP_FORMAT_INCLUDES_SMARTDATE 0x04
+
+
+/* access value of first_unseen, but don't set it with this */
+#define sp_first_unseen(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->first_unseen : 0L)
+
+/* use this to set it */
+#define sp_set_first_unseen(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->first_unseen = (val);}while(0)
+
+#define sp_flags(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->flags : 0L)
+
+#define sp_set_flags(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->flags = (val);}while(0)
+
+#define sp_icache_flags(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->icache_flags : 0L)
+
+#define sp_set_icache_flags(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->icache_flags = (val);}while(0)
+
+#define sp_ref_cnt(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->ref_cnt : 0L)
+
+#define sp_set_ref_cnt(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->ref_cnt = (val);}while(0)
+
+#define sp_expunge_count(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->expunge_count : 0L)
+
+#define sp_set_expunge_count(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->expunge_count = (val);}while(0)
+
+#define sp_new_mail_count(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->new_mail_count : 0L)
+
+#define sp_set_new_mail_count(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->new_mail_count = (val);}while(0)
+
+#define sp_mail_since_cmd(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->mail_since_cmd : 0L)
+
+#define sp_set_mail_since_cmd(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->mail_since_cmd = (val);}while(0)
+
+#define sp_recent_since_visited(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->recent_since_visited : 0L)
+
+#define sp_set_recent_since_visited(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->recent_since_visited = (val);}while(0)
+
+#define sp_check_cnt(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->check_cnt : 0L)
+
+#define sp_set_check_cnt(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->check_cnt = (val);}while(0)
+
+#define sp_first_status_change(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->first_status_change : 0L)
+
+#define sp_set_first_status_change(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->first_status_change = (val);}while(0)
+
+#define sp_last_ping(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->last_ping : 0L)
+
+#define sp_set_last_ping(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->last_ping = (val);}while(0)
+
+#define sp_last_expunged_reaper(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->last_expunged_reaper : 0L)
+
+#define sp_set_last_expunged_reaper(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->last_expunged_reaper = (val);}while(0)
+
+#define sp_last_chkpnt_done(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->last_chkpnt_done : 0L)
+
+#define sp_set_last_chkpnt_done(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->last_chkpnt_done = (val);}while(0)
+
+#define sp_last_use_time(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->last_use_time : 0L)
+
+#define sp_set_last_use_time(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->last_use_time = (val);}while(0)
+
+#define sp_last_activity(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->last_activity : 0L)
+
+#define sp_set_last_activity(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->last_activity = (val);}while(0)
+
+#define sp_saved_uid_validity(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->saved_uid_validity : 0L)
+
+#define sp_set_saved_uid_validity(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->saved_uid_validity = (val);}while(0)
+
+#define sp_saved_uid_last(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->saved_uid_last : 0L)
+
+#define sp_set_saved_uid_last(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->saved_uid_last = (val);}while(0)
+
+#define sp_mail_box_changed(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->mail_box_changed : 0L)
+
+#define sp_set_mail_box_changed(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->mail_box_changed = (val);}while(0)
+
+#define sp_unsorted_newmail(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->unsorted_newmail : 0L)
+
+#define sp_set_unsorted_newmail(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->unsorted_newmail = (val);}while(0)
+
+#define sp_need_to_rethread(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->need_to_rethread : 0L)
+
+#define sp_set_need_to_rethread(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->need_to_rethread = (val);}while(0)
+
+#define sp_viewing_a_thread(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->viewing_a_thread : 0L)
+
+#define sp_set_viewing_a_thread(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->viewing_a_thread = (val);}while(0)
+
+#define sp_dead_stream(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->dead_stream : 0L)
+
+#define sp_set_dead_stream(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->dead_stream = (val);}while(0)
+
+#define sp_noticed_dead_stream(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->noticed_dead_stream : 0L)
+
+#define sp_set_noticed_dead_stream(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->noticed_dead_stream = (val);}while(0)
+
+#define sp_closing(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->closing : 0L)
+
+#define sp_set_closing(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->closing = (val);}while(0)
+
+#define sp_io_error_on_stream(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->io_error_on_stream : 0L)
+
+#define sp_set_io_error_on_stream(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->io_error_on_stream = (val);}while(0)
+
+#define sp_fldr(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->fldr : (char *) NULL)
+
+#define sp_saved_cur_msg_id(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->saved_cur_msg_id : (char *) NULL)
+
+#define sp_context(stream) \
+ ((sp_data(stream) && *sp_data(stream)) \
+ ? (*sp_data(stream))->context : 0L)
+
+#define sp_set_context(stream,val) do{ \
+ if(sp_data(stream) && *sp_data(stream)) \
+ (*sp_data(stream))->context = (val);}while(0)
+
+
+extern MAILSTATUS *pine_cached_status;
+
+
+/*
+ * Macros to help fetch specific fields
+ */
+#define pine_fetchheader_lines(S,N,M,F) pine_fetch_header(S,N,M,F,0L)
+#define pine_fetchheader_lines_not(S,N,M,F) pine_fetch_header(S,N,M,F,FT_NOT)
+
+
+/* exported protoypes */
+MAILSTREAM *pine_mail_open(MAILSTREAM *, char *, long, long *);
+long pine_mail_create(MAILSTREAM *, char *);
+long pine_mail_delete(MAILSTREAM *, char *);
+long pine_mail_append_full(MAILSTREAM *, char *, char *, char *, STRING *);
+#define pine_mail_append(stream,mailbox,message) \
+ pine_mail_append_full(stream,mailbox,NULL,NULL,message)
+long pine_mail_append_multiple(MAILSTREAM *, char *, append_t, APPENDPACKAGE *, MAILSTREAM *);
+long pine_mail_copy_full(MAILSTREAM *, char *, char *, long);
+#define pine_mail_copy(stream,sequence,mailbox) \
+ pine_mail_copy_full(stream,sequence,mailbox,0)
+long pine_mail_rename(MAILSTREAM *, char *, char *);
+void pine_mail_close(MAILSTREAM *);
+void pine_mail_actually_close(MAILSTREAM *);
+void maybe_kill_old_stream(MAILSTREAM *);
+long pine_mail_search_full(MAILSTREAM *, char *, SEARCHPGM *, long);
+void pine_mail_fetch_flags(MAILSTREAM *, char *, long);
+ENVELOPE *pine_mail_fetchenvelope(MAILSTREAM *, unsigned long);
+ENVELOPE *pine_mail_fetch_structure(MAILSTREAM *, unsigned long, BODY **, long);
+ENVELOPE *pine_mail_fetchstructure(MAILSTREAM *, unsigned long, BODY **);
+char *pine_mail_fetch_body(MAILSTREAM *, unsigned long, char *, unsigned long *, long);
+char *pine_mail_fetch_text(MAILSTREAM *, unsigned long, char *, unsigned long *, long);
+char *pine_mail_partial_fetch_wrapper(MAILSTREAM *, unsigned long, char *, unsigned long *,
+ long, unsigned long, char **, int);
+long pine_mail_ping(MAILSTREAM *);
+void pine_mail_check(MAILSTREAM *);
+int pine_mail_list(MAILSTREAM *, char *, char *, unsigned *);
+long pine_mail_status(MAILSTREAM *, char *, long);
+long pine_mail_status_full(MAILSTREAM *, char *, long, imapuid_t *, imapuid_t *);
+int check_for_move_mbox(char *, char *, size_t, char **);
+MAILSTREAM *already_open_stream(char *, int);
+void pine_imap_cmd_happened(MAILSTREAM *, char *, long);
+void sp_cleanup_dead_streams(void);
+int sp_flagged(MAILSTREAM *, unsigned long);
+void sp_set_fldr(MAILSTREAM *, char *);
+void sp_set_saved_cur_msg_id(MAILSTREAM *, char *);
+void sp_flag(MAILSTREAM *, unsigned long);
+void sp_unflag(MAILSTREAM *, unsigned long);
+void sp_mark_stream_dead(MAILSTREAM *);
+int sp_nremote_permlocked(void);
+MAILSTREAM *sp_stream_get(char *, unsigned long);
+void sp_end(void);
+int sp_a_locked_stream_is_dead(void);
+int sp_a_locked_stream_changed(void);
+MAILSTREAM *sp_inbox_stream(void);
+PER_STREAM_S **sp_data(MAILSTREAM *);
+MSGNO_S *sp_msgmap(MAILSTREAM *);
+void sp_free_callback(void **);
+MAILSTREAM *same_stream(char *, MAILSTREAM *);
+MAILSTREAM *same_stream_and_mailbox(char *, MAILSTREAM *);
+int same_remote_mailboxes(char *, char *);
+int is_imap_stream(MAILSTREAM *);
+int modern_imap_stream(MAILSTREAM *);
+int streams_died(void);
+int some_stream_is_locked(void);
+void appenduid_cb(char *mailbox,unsigned long uidvalidity, SEARCHSET *set);
+imapuid_t get_last_append_uid(void);
+MAILSTREAM *mail_cmd_stream(CONTEXT_S *, int *);
+long dummy_soutr(void *, char *);
+
+
+#endif /* PITH_STREAM_INCLUDED */