dthelp: Change to ANSI function definitions
[oweals/cde.git] / cde / programs / dtmail / libDtMail / RFC / RFCImpl.hh
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *
27  *      $TOG: RFCImpl.hh /main/22 1998/10/01 17:28:08 mgreess $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #ifndef I_HAVE_NO_IDENT
45 #endif
46
47 #ifndef _RFCIMPL_HH
48 #define _RFCIMPL_HH
49
50 #include <DtMail/Buffer.hh>
51 #include <DtMail/DtMail.hh>
52 #include <DtMail/DtMailServer.hh>
53 #include <DtMail/FileShare.hh>
54 #include <DtMail/Threads.hh>
55
56 #include <sys/param.h>
57 #include <sys/types.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <sys/wait.h>
61
62 #if defined(NEED_MMAP_WRAPPER)
63 extern "C" {
64 #endif
65   #include <sys/mman.h>
66 #if defined(NEED_MMAP_WRAPPER)
67 }
68 #endif
69
70
71 // Structs needed to exec sendmail
72 typedef struct waitentry {
73         struct waitentry * next;
74         int pid;
75         void * data;
76         SubProcessFinishedProc * proc;
77 } waitentry_t;
78  
79 typedef struct pipedata {
80         int pid;
81         int status;
82 } pipedata_t;
83
84 typedef enum { 
85   DTMBX_LONGLOCK_FAILED_CANCEL,    // failed to obtain lock, cancel operation
86   DTMBX_LONGLOCK_FAILED_READONLY,  // failed to obtain lock, open read only
87   DTMBX_LONGLOCK_FAILED_READWRITE, // failed to obtain lock,
88                                    // open read write [user locking override]
89   DTMBX_LONGLOCK_SUCCESSFUL        // obtained the lock
90 } DTMBX_LONGLOCK;
91
92 class RFCMailBox;
93 class RFCBodyPart;
94
95
96 class RFCMessage : public DtMail::Message {
97   public:
98     RFCMessage(DtMailEnv & error,
99                DtMail::MailBox * parent,
100                const char ** start, // Also returns the end of the message.
101                const char * end_of_file);
102
103     RFCMessage(DtMailEnv & error,
104                const char * alt_start,
105                const char * alt_end);
106   
107     RFCMessage(DtMailEnv & error,
108                DtMail::Session * session,
109                DtMailObjectSpace space,
110                void * arg,
111                DtMailCallback cb,
112                void * client_data);
113
114     virtual ~RFCMessage(void);
115     
116     virtual DtMail::Envelope * getEnvelope(DtMailEnv &);
117     
118     // This should only be used when you REALLY need to know
119     // how many body parts are present before actually traversing
120     // the body parts (i.e. like when writing a MIME format message).
121     virtual int getBodyCount(DtMailEnv &);
122     
123     virtual DtMail::BodyPart * getFirstBodyPart(DtMailEnv &);
124     virtual DtMail::BodyPart * getNextBodyPart(DtMailEnv &,
125                                                DtMail::BodyPart *);
126
127     virtual DtMail::BodyPart * newBodyPart(DtMailEnv &,
128                                            DtMail::BodyPart *);
129
130 #ifdef DEAD_WOOD
131     virtual void newBodyPartOrder(DtMailEnv &,
132                                   DtMail::BodyPart *,
133                                   const int) { };
134 #endif /* DEAD_WOOD */
135
136     virtual void setFlag(DtMailEnv &,
137                          const DtMailMessageState);
138     
139     virtual void resetFlag(DtMailEnv &,
140                            const DtMailMessageState);
141     
142     virtual DtMailBoolean flagIsSet(DtMailEnv &,
143                                     const DtMailMessageState);
144
145     virtual time_t getDeleteTime(DtMailEnv &);
146     
147     virtual void toBuffer(DtMailEnv & error, DtMailBuffer &);
148
149     virtual const char * impl(DtMailEnv &);
150
151     // Methods following this point are specific to RFCMessage.
152     //
153     void markDirty(const int delta);
154
155     void fixMessageLocation(char ** msgHeaderStart, long & msgHeaderLen,
156                             char ** msgBodyStart, long &msgBodyLen,
157                             int & msgTemporary, long & msgBodyOffset);
158
159     void unfixMessageLocation(char *msgStart, int msgTemporary);
160
161     void adjustMessageLocation(
162                         char * oldStart,
163                         char * newStart,
164                         long newLength,
165                         int msgTemporary,
166                         long newBodyOffset);
167
168     void pinMessageDown(char ** msgHeaderStart, long & msgHeaderLen,
169                         char ** msgBodyStart, long &msgBodyLen);
170   
171     RFCMailBox * parent(void) { return (RFCMailBox *)_parent; }
172
173   protected:
174     unsigned long       _object_signature;
175     const char *        _msg_start;
176     const char *        _msg_end;
177     const char *        _body_start;
178     SafeScalar<int>     _dirty;
179     DtMailBuffer        *_msg_buf;
180
181     struct BodyPartCache : public DtCPlusPlusAllocator {
182         RFCBodyPart     *body;
183         const char *    body_start;
184     };
185
186     DtVirtArray<BodyPartCache *>        _bp_cache;
187
188     // _alternativeMultipart -- does message contain alternative messages?
189     // If DTM_FALSE: this message does not contain alternative messages.
190     //   .. can ignore: _alt_msg_cache, _alternativeValid
191     // If DTM_TRUE: this message does contain alternative messages.
192     //   The body part cache is allocated; however, the pointers within
193     //   the cache are copied from the latest valid alternative message
194     //   within the alternative message cache, and so should not be
195     //   deleted when a message is destroyed and this is true.
196     //   The alternative message cache (_alt_msg_cache) contains one or
197     //   more messages that map 1 to 1 with the corresponding alternative
198     //   messages contained within the entire message.
199     //   
200     DtMailBoolean       _alternativeMultipart;
201
202     // _alternativeMessage -- is this message an alternative message?
203     // If DTM_FALSE: this is not an alternative message but rather a real
204     //   message -- _msg_start, _msg_end, _body_start, etc. are valid.
205     // If DTM_TRUE: this message is an alternative message; _msg_start,
206     //   _msg_end, _body_start, etc. demark the alternative message within
207     //   the entire real message. The body part cache is fully allocated and
208     //   represents all body parts contained within this alternative message.
209     //
210     DtMailBoolean       _alternativeMessage;
211
212     // _alternativeValid -- is this alternative message part valid?
213     // If DTM_FALSE: this alternative cannot be displayed or otherwise
214     //   acted upon on this system
215     // If DTM_TRUE: this alternative can be displayed or otherwise
216     //   acted upon on this system
217     //
218     DtMailBoolean       _alternativeValid;
219     
220     // _alt_msg_cache is the "alternative message cache", an array of
221     //   MIMEBodyParts an RFCMessages, which have _alternativeMessage
222     //   set, and contain only those body parts that are associated with a
223     //   single alternative message. There is one entry in the array for
224     //   each alternative message within the entire message. Each alternative
225     //   message will have _alternativeMessage == DTM_TRUE.
226     // This cache is present only if _alternativeMultipart == DTM_TRUE.
227     //
228     struct AlternativeMessageCache : public DtCPlusPlusAllocator {
229       RFCMessage *      amc_msg;        // -> RFCMessage for alternative
230       RFCBodyPart *     amc_body;       // -> MIMEBodyPart for alternative
231       const char *      amc_body_start; // -> first byte of body
232       const char *      amc_body_end;   // -> last byte of body
233     };
234   
235     DtVirtArray<AlternativeMessageCache *>      _alt_msg_cache;
236
237     DtMail::BodyPart * bodyPart(DtMailEnv & error, const int slot);
238
239     int lookupByBody(DtMail::BodyPart *);
240
241     const char * parseMsg(DtMailEnv &, const char * end_of_file);
242     const char * findMsgEnd(DtMailEnv &, const char * end_of_file);
243     void parseBodies(DtMailEnv &);
244     void parseMIMEBodies(DtMailEnv &);
245     void parseMIMETextPlain(DtMailEnv &);
246     void parseMIMEMultipartSubtype(DtMailEnv &, const char * subtype);
247     void parseMIMEMessageSubtype(DtMailEnv &, const char * subtype);
248     void parseMIMEMessageExternalBody(DtMailEnv &);
249     void parseMIMEMultipartMixed(DtMailEnv &, const char * boundary);
250     void parseMIMEMultipartAlternative(DtMailEnv &, const char * boundary);
251     void parseV3Bodies(DtMailEnv &);
252
253     void writeMsg(char * buffer);
254
255     int sizeMIMEBodies(DtMailEnv &);
256     int sizeV3Bodies(DtMailEnv &);
257
258     char * extractBoundary(const char * content_type);
259     DtMailBoolean hasHeaders(const char * buf, const unsigned long size);
260
261     // This friend declaration is used temporarily by copyMsg to copy
262     // messages from RFC->RFC. A more general solution is needed for
263     // FCS.
264 friend class RFCMailBox;
265 };
266
267 class RFCEnvelope : public DtMail::Envelope {
268   public:
269     RFCEnvelope(DtMailEnv & error,
270                 DtMail::Message * parent,
271                 const char * start,
272                 const int len);
273     
274     virtual ~RFCEnvelope(void);
275
276     virtual DtMailHeaderHandle getFirstHeader(DtMailEnv &,
277                                               char ** name,
278                                               DtMailValueSeq & value);
279     
280     virtual DtMailHeaderHandle getNextHeader(DtMailEnv &,
281                                              DtMailHeaderHandle last,
282                                              char ** name,
283                                              DtMailValueSeq & value);
284     
285     virtual void getHeader(DtMailEnv &,
286                            const char * name,
287                            const DtMailBoolean abstract,
288                            DtMailValueSeq & value);
289     
290     virtual void setHeaderSeq(DtMailEnv &, 
291                               const char *,
292                               const DtMailValueSeq &) {} ;
293     
294     // The last parameter is left to the client to provide
295     // because it can not be done in a type safe manner.
296     //
297     virtual void setHeader(DtMailEnv &, 
298                            const char *, 
299                            const DtMailBoolean,
300                            const char *);
301     
302     virtual void removeHeader(DtMailEnv &,
303                               const char *);
304
305     // Methods below this point are specific to RFCEnvelope.
306     //
307     int dirty(void) { return _dirty; }
308
309     void adjustHeaderLocation(char * headerStart, int headerLength);
310   
311     char *writeHeaders(char *buf);
312
313     const char * headerLocation(void) { return _header_text; }
314   
315     long headerLength(void) { return _header_len; }
316     
317     const char * unixFrom(DtMailEnv &, int & length);
318     //
319     // fix for the defect 177527
320     // when a reply-to field is in a message headers, the reply-to is
321     // going to be displayed as the send in RMW's msg list scrolled window
322     // instead of the real sender. The following three public methods are
323     // going to access _use_reply_to.
324     // 
325     void setUseReplyTo(void) { _use_reply_to = DTM_TRUE; }
326     void unsetUseReplyTo(void) {  _use_reply_to = DTM_FALSE; }
327     DtMailBoolean getUseReplyTo(void) { return _use_reply_to; }
328
329
330   protected:
331
332     DtMailBoolean       _use_reply_to;
333     unsigned long       _object_signature;
334     SafeScalar<int>     _dirty;
335
336     struct ParsedHeader : public DtCPlusPlusAllocator {
337             ParsedHeader(void);
338             ~ParsedHeader(void);
339         const char      *name_start;
340         int             name_len;
341         const char      *value_start;
342         int             value_len;
343         int             alloc_mask; // Tracks updates to value.
344         void *          mutex;
345     };
346
347     const char *        _header_text;
348     int                 _header_len;
349     DtVirtArray<ParsedHeader *> _parsed_headers;
350     void *              _header_lock;
351
352     void getTransportHeader(DtMailEnv & error,
353                             const char * name,
354                             DtMailValueSeq & value);
355
356     DtMailBoolean matchName(const ParsedHeader &, const char *);
357
358     void parseUnixFrom(DtMailEnv &,
359                        const ParsedHeader &,
360                        DtMailValueSeq & value);
361
362     void parseUnixDate(DtMailEnv &,
363                        const ParsedHeader &,
364                        DtMailValueSeq & value);
365
366     void makeValue(DtMailEnv &,
367                    const ParsedHeader &,
368                    DtMailValueSeq & value);
369
370     void makeReply(DtMailEnv &,
371                    const char * name,
372                    DtMailValueSeq & value);
373
374     DtMailBoolean metooAddr(DtMailValueAddress & addr,
375                             DtMailAddressSeq & alts,
376                             DtMailBoolean allnet);
377
378     void parseHeaders(void);
379
380     int lookupHeader(const char * name, DtMailBoolean real_only = DTM_FALSE);
381     const char * mapName(const char * name);
382 };
383
384 class RFCBodyPart : public DtMail::BodyPart {
385   public:
386     RFCBodyPart(DtMailEnv &,
387                 DtMail::Message * parent,
388                 const char * start,
389                 const int len,
390                 RFCEnvelope * body_env);
391
392     virtual void lockContents(DtMailEnv &, const DtMailLock);
393     virtual void unlockContents(DtMailEnv &);
394
395     virtual void getContents(DtMailEnv &,
396                              const void ** contents,
397                              unsigned long * length,
398                              char ** type,
399                              char ** name,
400                              int * mode,
401                              char ** description);
402     
403     virtual void setContents(DtMailEnv &,
404                              const void * contents,
405                              const unsigned long length,
406                              const char * type,
407                              const char * name,
408                              const int mode,
409                              const char * description);
410
411     virtual void setFlag(DtMailEnv &,
412                          DtMailBodyPartState);
413     
414     virtual void resetFlag(DtMailEnv &,
415                            DtMailBodyPartState);
416     
417     virtual DtMailBoolean flagIsSet(DtMailEnv &,
418                                     DtMailBodyPartState);
419     
420     virtual time_t getDeleteTime(DtMailEnv &);
421
422     virtual void getHeader(DtMailEnv &,
423         const char * name,
424         const DtMailBoolean abstract,
425         DtMailValueSeq & value);
426
427         // For CHARSET
428     //---------------------------------------------------
429     // These methods are duplicated in class BodyPart (also being implemented
430     // in class Session) because RFCFormat and RFCBodyPart need to access
431     // them.  Duplicating routines like what is being done here is a workaround
432     // for an implementation bug/hole because there is no class where global
433     // routines can be defined (and be accessed by any class).
434     // class Session is not a proper place to put (global) methods because
435     // not every class can get at Session.
436     // RFCFormat accesses these routines through its private Session handle.
437     // RFCBodyPart does not have a Session handle.  Hence the need to duplicate
438     // the following routines.
439
440     virtual int OpenLcxDb(void);
441     virtual void DtXlateStdToOpLocale(char *op, char *std, char *dflt,
442                  char **ret);
443     virtual void DtXlateOpToStdLocale(char *op, char *opLoc, char **retLoc,
444                  char **ret_retLang, char **retSet);
445     virtual void DtXlateStdToOpCodeset(char *op, char *std, char *dflt,
446                  char **ret);
447     virtual void DtXlateMimeToIconv(const char *, const char *, const char *,
448                  char **, char **);
449     virtual void DtXlateLocaleToMime(const char *, const char *,
450                   const char *, char **);
451  
452     virtual char *csToConvName(char *);
453     virtual char *locToConvName();
454     virtual char *targetConvName();
455     virtual char *targetTagName();
456     virtual int csConvert(char **, unsigned long &, int, char *, char *);
457     //---------------------------------------------------
458    
459         // Implement in both MIMEBodyPart and V3BodyPart
460     virtual char *csFromContentType(DtMailValueSeq & value) = 0;
461         // End of For CHARSET
462
463 #ifdef DEAD_WOOD
464     virtual DtMailChecksumState checksum(DtMailEnv &) = 0;
465 #endif /* DEAD_WOOD */
466
467     // Methods below this point are specific to RFCBodyPart.
468     //
469     virtual char *writeBodyParts(char * buf) = 0;
470
471     void adjustBodyPartsLocation(char * start);
472   
473     virtual int rfcSize(const char * boundary, DtMailBoolean &) = 0;
474
475   protected:
476     ~RFCBodyPart(void);
477     DtMailBoolean isTerm(const char *); // Determines if we have an eol.
478
479     void *              _body_lock;
480
481     // _body_start includes any boundaries.
482     const char *        _body_start;
483
484     // _body_text is where the text of the body begins, after
485     // boundaries, headers, and other uninteresting stuff.
486     //
487     const char *        _body_text;
488     int                 _body_len;
489     RFCEnvelope *       _body_env;
490     DtMailBoolean       _my_env; // True if we made the envelope.
491     SafeScalar<int>     _dirty;
492
493 friend class RFCMessage;
494
495     // The following entries are a computed cache. They
496     // are built in a lazy fashion, based on the caller's
497     // requests. These entries can be very expensive to
498     // compute so lazy is important.
499     //
500     char *              _body;
501     DtMailBoolean       _must_free_body;
502     int                 _body_decoded_len;
503     char *              _body_type;
504
505     // The sub classes implement these because they are the major difference
506     // in the get/set contents methods.
507     //
508     virtual void getContentType(DtMailEnv &, char**) = 0;
509     virtual void getDtType(DtMailEnv &) = 0;
510     virtual void loadBody(DtMailEnv &) = 0;
511     virtual char * getDescription(DtMailEnv &) = 0;
512     virtual char * getName(DtMailEnv &) = 0;
513     virtual void setName(DtMailEnv &, const char *) = 0;
514     virtual unsigned long getLength(DtMailEnv &) = 0;
515     virtual const void * getBody(DtMailEnv &);
516 };
517
518 class MIMEBodyPart : public RFCBodyPart {
519   public:
520     MIMEBodyPart(DtMailEnv &,
521                  DtMail::Message * parent,
522                  const char * start,
523                  const int len,
524                  RFCEnvelope * body_env);
525     
526     MIMEBodyPart(DtMailEnv &,
527                  DtMail::Message * parent,
528                  const char * start,
529                  const char ** end,
530                  const char * boundary);
531
532 #ifdef DEAD_WOOD
533     virtual DtMailChecksumState checksum(DtMailEnv &);
534 #endif /* DEAD_WOOD */
535
536     char *writeBodyParts(char * buf);
537
538     int rfcSize(const char * boundary, DtMailBoolean &);
539
540     // For CHARSET
541     virtual char *csFromContentType(DtMailValueSeq & value);
542
543     char * parameterValue(
544                         DtMailValueSeq & value,
545                         const char* parameter,
546                         DtMailBoolean isCaseSensitive);
547
548   protected:
549 friend RFCMessage::~RFCMessage(void);
550     ~MIMEBodyPart(void);
551
552     void getContentType(DtMailEnv &, char **);
553     void getDtType(DtMailEnv &);
554     void loadBody(DtMailEnv &);
555     char * getDescription(DtMailEnv &);
556     char * getName(DtMailEnv &);
557     void setName(DtMailEnv &, const char *);
558     char * getNameHeaderVal(DtMailEnv &);
559     unsigned long getLength(DtMailEnv &);
560     const void * getBody(DtMailEnv &);
561 };
562
563 class V3BodyPart : public RFCBodyPart {
564   public:
565     V3BodyPart(DtMailEnv &,
566                DtMail::Message * parent,
567                const char * start,
568                const int len,
569                RFCEnvelope * body_env);
570
571     V3BodyPart(DtMailEnv &,
572                DtMail::Message * parent,
573                const char * start,
574                const char ** end);
575
576 #ifdef DEAD_WOOD
577     virtual DtMailChecksumState checksum(DtMailEnv &);
578 #endif /* DEAD_WOOD */
579
580     char *writeBodyParts(char * buf);
581
582     int rfcSize(const char * boundary, DtMailBoolean &);
583
584         // For CHARSET
585         virtual char *csFromContentType(DtMailValueSeq & value);
586
587   protected:
588 friend RFCMessage::~RFCMessage(void);
589     ~V3BodyPart(void);
590
591     void getContentType(DtMailEnv &, char **);
592     void getDtType(DtMailEnv &);
593     void loadBody(DtMailEnv &);
594     char * getDescription(DtMailEnv &);
595     char * getName(DtMailEnv &);
596     void setName(DtMailEnv &, const char *);
597     unsigned long getLength(DtMailEnv &);
598 };
599
600 class RFCMailBox : public DtMail::MailBox
601 {
602   public:
603
604     RFCMailBox(DtMailEnv &,
605                DtMail::Session * session,
606                DtMailObjectSpace space,
607                void * arg,
608                DtMailCallback cb,
609                void * clientData,
610                const char * impl_name);
611     
612     virtual ~RFCMailBox(void);
613
614     static void  appendCB(DtMailEnv&, char *buf, int len, void *clientData);
615     virtual void append(DtMailEnv &error, char *buf, int len);
616     virtual void create(DtMailEnv & error, mode_t = DTMAIL_DEFAULT_CREATE_MODE);
617     virtual void open(DtMailEnv &,
618                       DtMailBoolean auto_create = DTM_TRUE,
619                       int open_mode = DTMAIL_DEFAULT_OPEN_MODE,
620                       mode_t create_mode = DTMAIL_DEFAULT_CREATE_MODE,
621                       DtMailBoolean lock_flag = DTM_TRUE,
622                       DtMailBoolean auto_parse = DTM_TRUE);
623     virtual void lock();
624     virtual void unlock();
625     virtual void save();
626
627     virtual void                 callCallback(DtMailCallbackOp, void *);
628     virtual void                 disableMailRetrieval()
629                                      { _mr_allowed = DTM_FALSE; }
630     virtual void                 enableMailRetrieval()
631                                      { _mr_allowed = DTM_TRUE; }
632     virtual void                 checkForMail(
633                                         DtMailEnv &, 
634                                         const DtMailBoolean
635                                                 already_locked = DTM_FALSE); 
636     virtual void                 clearMessageSummary(DtMailHeaderLine &);
637     virtual void                 copyMessage(DtMailEnv &, DtMail::Message *);
638     virtual void                 copyMailBox(DtMailEnv &, DtMail::MailBox *);
639     virtual void                 createMailRetrievalAgent(char *passwd=NULL);
640     virtual void                 deleteMailRetrievalAgent();
641     virtual void                 expunge(DtMailEnv &);
642     virtual DtMail::Message     *getFirstMessage(DtMailEnv &);
643     virtual DtMailMessageHandle  getFirstMessageSummary(
644                                         DtMailEnv &,
645                                         const DtMailHeaderRequest &,
646                                         DtMailHeaderLine &);
647     virtual DtMail::Message     *getNextMessage(DtMailEnv &, DtMail::Message *);
648     virtual DtMailMessageHandle  getNextMessageSummary(
649                                         DtMailEnv &,
650                                         DtMailMessageHandle,
651                                         const DtMailHeaderRequest &,
652                                         DtMailHeaderLine &);
653     virtual DtMail::Message     *getMessage(DtMailEnv &, DtMailMessageHandle);
654     virtual void                 getMessageSummary(
655                                         DtMailEnv &,
656                                         DtMailMessageHandle,
657                                         const DtMailHeaderRequest &,
658                                         DtMailHeaderLine &);
659     virtual const char          *impl(DtMailEnv & error);
660 #ifdef DEAD_WOOD
661     virtual int                  messageCount(DtMailEnv &);
662 #endif /* DEAD_WOOD */
663     virtual DtMail::Message     *newMessage(DtMailEnv &);
664     virtual DtMailCallbackOp     retrieveNewMail(DtMailEnv&);
665     virtual void                 updateMailRetrievalPassword(char *passwd=NULL);
666
667     // This is not used by any clients!
668     struct MapRegion : public DtCPlusPlusAllocator
669     {
670         char *          map_region;
671         unsigned long   map_size;
672         char *          file_region; // Where the parsing begins.
673         unsigned long   file_size;
674         long            offset;
675     };
676
677     struct MessageCache : public DtCPlusPlusAllocator {
678         RFCMessage      *message;
679         DtMailBoolean   delete_pending;
680     };
681
682     // Methods below this point are specific to RFCMailBox.
683     void        markDirty(const int delta);
684     void        startAutoSave(DtMailEnv & error, DtMailBoolean start=DTM_TRUE);
685
686   protected:
687
688     struct NewMailData : public DtCPlusPlusAllocator
689     {
690         RFCMailBox *    self;
691         Condition *     object_valid;
692     };
693
694     // Content-Type: message/partial support.
695     struct _partialData
696     {
697         const char      * id;
698         unsigned int      number;
699         unsigned int      total;        // 0 == I do not know.
700         RFCMessage      * msg;
701     };
702
703     // Keep track of how many messages, and whether we've hit the
704     // EOF. The number of messages is a condition variable because
705     // we might have multiple threads trying to read the state
706     // while the parsing thread is reading the state.
707     //
708     Condition                   _at_eof;
709     char                        *_buffer;
710     SafeScalar<int>              _dirty;        // Write access/dirty state.
711     DtMailBoolean                _dot_lock_active;
712     DtMailBoolean                _errorLogging; // Extra logging done??
713     int                          _fd;
714     SafeScalar<unsigned long>    _file_size;
715     const char                  *_impl_name;    // Might be V3 or MIME.
716     int                          _last_check;   // For polling only.
717     time_t                       _last_poll;    // For polling only.
718     int                          _links;
719     DtMailBoolean                _lock_flag;
720     FileShare                   *_lock_obj;
721     DtMailBoolean                _lockf_active; // lockf() is being held
722     char *                       _lockFileName; // lock file name for mailbox
723     DtMailBoolean                _long_lock_active;
724     Thread                       _mbox_daemon;
725     void *                       _map_lock;
726     DtVirtArray<MapRegion *>     _mappings;
727     unsigned long                _object_signature;
728     Condition                   *_object_valid;
729     DtMailBoolean                _parsed;
730     char                        *_real_path;
731     DtMailBoolean                _mr_allowed;
732     char                        *_mra_command;
733     DtMailServer                *_mra_server;
734     char                        *_mra_serverpw;
735     DtVirtArray<MessageCache *>  _msg_list;
736     _partialData                **_partialList;
737     unsigned int                 _partialListCount;
738     struct stat                  _stinfo;
739     NewMailData                 *_thread_info;
740     DtMailBoolean                _tt_lock;
741     char *                       _uniqueLockId; // unique id for .lock files
742     int                          _uniqueLockIdLength;
743     DtMailBoolean                _use_dot_lock;
744
745 //  void        CheckPointEvent(DtMailEnv & error);
746     void        CheckPointEvent();
747     void        ExpungeEvent(DtMailBoolean closing = DTM_FALSE);
748     void        NewMailEvent(const DtMailBoolean already_locked = DTM_FALSE);
749     static DtMailBoolean
750                 PollEntry(void *);
751     static void *ThreadNewMailEntry(void *);
752     static void *ThreadParseEntry(void *);
753
754     RFCMessage  *_assemblePartial(DtMailEnv &error,RFCMessage *Message);
755     DtMailBoolean
756                 _isPartial(DtMailEnv &error, RFCMessage *message);
757     DtMailBoolean
758                 addressIsMapped(void *addressToCheck);
759 #if defined(__linux__)
760     void        alterPageMappingAdvice(MapRegion *map, int advice = 0);
761 #else
762     void        alterPageMappingAdvice(
763                         MapRegion       *map,
764                         int             advice = MADV_SEQUENTIAL);
765 #endif
766     int         createTemporaryMailboxFile(DtMailEnv &, char *tmp_name);
767     void        checkLockFileOwnership(DtMailEnv &);
768     void        dotDtmailLockFile(char *, int);
769     void        dotDtmailLock(DtMailEnv &);
770     void        dotDtmailUnlock(DtMailEnv &);
771     void        dumpMaps(const char *);
772     char        *generateLockFileName(void);
773     char        *generateUniqueLockId(void);
774     void        incorporate(
775                         DtMailEnv &,
776                         const DtMailBoolean already_locked = DTM_FALSE);
777     time_t      linkLockFile(DtMailEnv &, char *tempLockFileName);
778     void        lockFile(DtMailEnv &);
779     void        lockNewMailboxFile(int new_fd);
780     DTMBX_LONGLOCK
781                 longLock(DtMailEnv &);
782     void        longUnlock(DtMailEnv &);
783     int         lookupByMsg(RFCMessage * msg);
784     void        mailboxAccessHide(char *prefix);
785     void        mailboxAccessShow(time_t mtime, char *prefix);
786     void        makeHeaderLine(DtMailEnv & error, 
787                         int slot,
788                         const DtMailHeaderRequest & request,
789                         DtMailHeaderLine &);
790     int         mapFile(DtMailEnv & error,
791                         const DtMailBoolean already_locked = DTM_FALSE,
792                         mode_t create_mode = DTMAIL_DEFAULT_CREATE_MODE);
793     MapRegion   *mapNewRegion(DtMailEnv &, int fd, unsigned long bytesWritten);
794     int         nextNotDel(const int cur);
795     void        openRealFile(DtMailEnv &error, int mode, mode_t create_mode);
796     int         prevNotDel(const int cur);
797     void        parseFile(DtMailEnv & error, int slot);
798     off_t       realFileSize(DtMailEnv &error, struct stat *stat_buffer = NULL);
799     void        transferLock(int old_fd, int new_fd);
800     void        unlockOldMailboxFile(int old_fd);
801     void        unlockFile(DtMailEnv &, int fd);
802     void        waitForMsgs(int needed);
803     void        writeMailBox(DtMailEnv&, DtMailBoolean);
804     void        writeToDumpFile(const char* format, ...);
805 };
806
807 class RFCTransport : public DtMail::Transport {
808   public:
809     RFCTransport(DtMailEnv &, DtMail::Session *, DtMailStatusCallback, void *,
810                  const char * impl);
811     virtual ~RFCTransport(void);
812
813     virtual DtMailOperationId submit(DtMailEnv &,
814                                      DtMail::Message *,
815                                      DtMailBoolean log_msg);
816     
817     static void arpaPhrase(const char * list, DtMailAddressSeq & tokens);
818
819     // SendMsgDialog initiates a send.  It needs to set information
820     // needed to exec sendmail by calling these initialization functions.
821     // getSendmailReturnProc returns a handler so that SendMsgDialog
822     // can use it in XtAppAddInput.
823     virtual void initTransportData(int fds[2],
824         SubProcessFinishedProc proc, void *ptr);
825     virtual void *getSendmailReturnProc(void);
826
827
828   protected:
829     Condition *         _object_valid;
830     char *              _impl;
831
832     struct ThreadSimpleData : public DtCPlusPlusAllocator {
833         RFCTransport *          self;
834         const char *            to;
835         const char *            cc;
836         const char *            bcc;
837         const char *            subject;
838         const char *            text;
839     };
840     static void * ThreadSimpleEntry(void * arg);
841
842     void format(DtMailEnv &, DtMail::Message * msg, DtMailBoolean log_msg);
843     void formatSimple(DtMailEnv &,
844                       const char * to,
845                       const char * cc,
846                       const char * bcc,
847                       const char * subject,
848                       const char * text);
849
850     void deliver(DtMailEnv &,
851                  DtMailAddressSeq &,
852                  Buffer & headers,
853                  Buffer & bodies,
854                  DtMailBoolean log_msg,
855                  int **log_files,
856                  int & log_count);
857
858     void launchSendmail(DtMailEnv & error,
859                         Buffer & headers, 
860                         Buffer & boides,
861                         char ** argv);
862
863     char * concatValue(DtMailValueSeq &);
864     void appendAddrs(DtMailAddressSeq & to, DtMailAddressSeq & from);
865     void skinFiles(DtMailAddressSeq &);
866     char * addrToString(DtMailAddressSeq &);
867     int openLogFile(const char * path);
868     void closeLogFiles(int * files, int file_cnt);
869
870     // These functions are needed to exec sendmail
871     static void childHandler(void);
872     void signalRegister(void);
873     int startSubprocess(DtMailEnv &error, char * cmd, 
874         Buffer & headers, Buffer & bodies, char **argv);
875     static void sendmailReturnProc(void);
876
877     // Store info from SendMsgDialog
878     // ptr to SendMsgDialog::SendmaliErrorProc
879     SubProcessFinishedProc *_error_proc; 
880     // a pointer to SendMsgDialog
881     void *_smd;                         
882     // get the status from the low and hi bytes returned from wait()
883     inline static int lowByte  (int status) { return (status & 0377); }
884     inline static int highByte (int status) { return (lowByte(status >> 8)); }
885 };
886
887 extern const char * RFCDeleteHeader;
888
889 class RFCValue : public DtMailValue {
890   public:
891     RFCValue(const char * str, int size, DtMail::Session *s);
892     RFCValue(const char * str, int size);
893     ~RFCValue(void);
894
895     virtual operator const char *(void);
896
897     virtual const char * operator= (const char *);
898
899     virtual DtMailValueDate toDate(void);
900 #ifdef DEAD_WOOD
901     virtual void fromDate(const DtMailValueDate &) { }
902 #endif /* DEAD_WOOD */
903
904     virtual DtMailAddressSeq * toAddress(void);
905 #ifdef DEAD_WOOD
906     virtual void fromAddress(const DtMailAddressSeq &) { }
907 #endif /* DEAD_WOOD */
908     virtual const char * raw(void);
909
910   protected:
911         DtMail::Session *_session;
912     char *      _decoded;
913
914     void decodeValue(void);
915 };
916
917 #endif