home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libnet / mkmailbx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  24.6 KB  |  855 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*
  19.  * state machine to handle mailbox URL 
  20.  */
  21.  
  22. #include "mkutils.h"
  23. #include "mkgeturl.h"
  24. #include "mktcp.h"
  25. #include "mkparse.h"
  26. #include "mkmailbx.h"
  27. #include "msgcom.h"
  28. #include "msgnet.h"
  29. #include "msg_srch.h"
  30. #include "libmime.h"
  31. #include "merrors.h"
  32. #include "mkimap4.h"
  33.  
  34.  
  35. /* for XP_GetString() */
  36. #include "xpgetstr.h"
  37. extern int XP_MAIL_READING_FOLDER;
  38. extern int XP_MAIL_READING_MESSAGE;
  39. extern int XP_COMPRESSING_FOLDER;
  40. extern int XP_MAIL_DELIVERING_QUEUED_MESSAGES;
  41. extern int XP_READING_MESSAGE_DONE;
  42. extern int XP_MAIL_READING_FOLDER_DONE;
  43. extern int XP_MAIL_COMPRESSING_FOLDER_DONE;
  44. extern int XP_MAIL_DELIVERING_QUEUED_MESSAGES_DONE;
  45. extern int XP_MAIL_SEARCHING;
  46.  
  47.  
  48. extern int MK_OUT_OF_MEMORY;
  49.  
  50. /* definitions of states for the state machine design
  51.  */
  52. typedef enum _MailboxStates {
  53.     MAILBOX_OPEN_FOLDER,
  54.     MAILBOX_FINISH_OPEN_FOLDER,
  55.     MAILBOX_OPEN_MESSAGE,
  56.     MAILBOX_OPEN_STREAM,
  57.     MAILBOX_READ_MESSAGE,
  58.     MAILBOX_COMPRESS_FOLDER,
  59.     MAILBOX_FINISH_COMPRESS_FOLDER,
  60.     MAILBOX_BACKGROUND,
  61.     MAILBOX_DELIVER_QUEUED,
  62.     MAILBOX_FINISH_DELIVER_QUEUED,
  63.     MAILBOX_DONE,
  64.     MAILBOX_ERROR_DONE,
  65.     MAILBOX_FREE,
  66.     MAILBOX_COPY_MESSAGES,
  67.     MAILBOX_FINISH_COPY_MESSAGES
  68. } MailboxStates;
  69.  
  70.  
  71.  
  72. /* structure to hold data pertaining to the active state of
  73.  * a transfer in progress.
  74.  *
  75.  */
  76. typedef struct _MailboxConData {
  77.     MSG_Pane        *pane;
  78.  
  79.     int              next_state;     /* the next state or action to be taken */
  80.     int              initial_state;  /* why we are here */
  81.     Bool             pause_for_read; /* Pause now for next read? */
  82.     void            *folder_ptr;
  83.     void            *msg_ptr;
  84.     void            *compress_folder_ptr;
  85.     void            *deliver_queued_ptr;
  86.     void            *mailbox_search_ptr;
  87.     char            *folder_name;
  88.     char            *msg_id;
  89.     int32             msgnum;    /* -1 if none specified. */
  90.     NET_StreamClass *stream;
  91.  
  92.     XP_Bool  destroy_graph_progress;       /* do we need to destroy 
  93.                                             * graph progress? */    
  94.     int32  original_content_length; /* the content length at the time of
  95.                                      * calling graph progress */
  96.     char            *input_buffer;
  97.     int32            input_buffer_size;
  98.  
  99. } MailboxConData;
  100.  
  101. #define COMPLETE_STREAM   (*cd->stream->complete)(cd->stream)
  102. #define ABORT_STREAM(s)   (*cd->stream->abort)(cd->stream, s)
  103. #define PUT_STREAM(buf, size)   (*cd->stream->put_block) \
  104.                           (cd->stream, buf, size)
  105.  
  106. /* forward decl */
  107. PRIVATE int32 net_ProcessMailbox (ActiveEntry *ce);
  108.  
  109. PRIVATE int32
  110. net_MailboxLoad (ActiveEntry * ce)
  111. {
  112.     /* get memory for Connection Data */
  113.     MailboxConData * cd;
  114.     char *path;
  115.     char *search;
  116.     char *part;
  117.     char *wholeUrl;
  118.  
  119.     /* temp, until imap urls have their own identifier */
  120.     if (!XP_STRNCASECMP(ce->URL_s->address, "mailbox://", 10) )
  121.         return NET_IMAP4Load(ce);
  122.  
  123.     if (XP_STRCASECMP(ce->URL_s->address, "mailbox:displayattachments") == 0) {
  124.         MIME_DisplayAttachmentPane(ce->window_id);
  125.         return -1;
  126.     }
  127.  
  128.  
  129.     cd = XP_NEW(MailboxConData);
  130.     path = NET_ParseURL(ce->URL_s->address, GET_PATH_PART);
  131.     search = NET_ParseURL(ce->URL_s->address, GET_SEARCH_PART);
  132.     part = search;
  133.  
  134.     ce->con_data = cd;
  135.     if(!ce->con_data)
  136.       {
  137.         ce->URL_s->error_msg = NET_ExplainErrorDetails(MK_OUT_OF_MEMORY);
  138.         ce->status = MK_OUT_OF_MEMORY;
  139.         return (ce->status);
  140.       }
  141.  
  142.     /* init */
  143.     XP_MEMSET(cd, 0, sizeof(MailboxConData));
  144.     cd->msgnum = -1;
  145.  
  146.     wholeUrl = XP_STRDUP(ce->URL_s->address);
  147.  
  148. #ifndef XP_MAC /* #### Giant Evil Mac Pathname Hack */
  149.     NET_UnEscape (path);
  150.     NET_UnEscape (wholeUrl);
  151. #endif /* !XP_MAC */
  152.  
  153.     cd->pane = ce->URL_s->msg_pane;
  154.     if (!cd->pane)
  155.     {
  156. #ifdef DEBUG_phil
  157.         XP_Trace ("NET_MailboxLoad: url->msg_pane NULL for URL: %s\n", ce->URL_s->address);
  158. #endif
  159.         /* If we're displaying a message, there'll be a '?' in the url */
  160.         if (XP_STRCHR(wholeUrl, '?'))
  161.         {
  162.           if (XP_STRSTR(wholeUrl, "?compress-folder") || XP_STRSTR(wholeUrl, "?deliver-queued"))
  163.             cd->pane = MSG_FindPane(ce->window_id, MSG_FOLDERPANE); /* ###phil tar to the tarpit */
  164.           else
  165.           {
  166.               /* find a pane, just to get back to the MSG_Master */
  167.              MSG_Pane *someRandomPane = MSG_FindPane (ce->window_id, MSG_ANYPANE);
  168.              if (someRandomPane)
  169.              {
  170.                 cd->pane = MSG_FindPaneFromUrl(someRandomPane, wholeUrl, MSG_MESSAGEPANE);
  171.                 /*
  172.                 ** jrm and dmb, 97/02/06: temporary fix, because we MUST have a thread pane
  173.                 ** in order for certain operations to succeed.  The macintosh UI can
  174.                 ** forward from the thread pane, with no message pane available, and this
  175.                 ** routine was setting cd->pane to a folderpane, which is a kind of
  176.                 ** pane that really doesn't work.  The permanent fix will be to change the
  177.                 ** behavior of MSG_FindPane.
  178.                 */
  179.                 if (!cd->pane)
  180.                    cd->pane = MSG_FindPaneFromUrl(someRandomPane, wholeUrl, MSG_THREADPANE);
  181.              }
  182.           }
  183.         }
  184.         else
  185.           cd->pane = MSG_FindPane(ce->window_id, MSG_FOLDERPANE);
  186.  
  187.         if (cd->pane == NULL)
  188.         {
  189.            /* find a pane, just to get back to the MSG_Master */
  190.             MSG_Pane *someRandomPane = MSG_FindPane (ce->window_id, MSG_ANYPANE);
  191.             if (someRandomPane)
  192.                 cd->pane = MSG_FindPaneFromUrl (someRandomPane, wholeUrl, MSG_MESSAGEPANE);
  193.         }
  194.  
  195.         /* ###dmb so there! This whole FindPane stuff is too adhoc. */
  196.         if (cd->pane == NULL)
  197.             cd->pane = MSG_FindPane(ce->window_id, MSG_FOLDERPANE); 
  198.         /* km!  I agree! */
  199.         if (cd->pane == NULL)
  200.             cd->pane = MSG_FindPane(ce->window_id, MSG_THREADPANE);
  201.     /*    ###whs this isn't really true the way things are set up. */
  202.     /*    XP_ASSERT(cd->pane && MSG_GetContext(cd->pane) == ce->window_id); */
  203.     }
  204.     if (cd->pane == NULL) 
  205.     {
  206.         FREEIF(wholeUrl);
  207.         return -1; /* ### */
  208.     }
  209.  
  210.     if (XP_STRCASECMP(wholeUrl, "mailbox:copymessages") == 0)
  211.         cd->next_state = MAILBOX_COPY_MESSAGES;
  212.     else
  213.     {
  214.         cd->folder_name = path;
  215.         cd->next_state = MAILBOX_OPEN_FOLDER;
  216.     }
  217.  
  218.     if (part && *part == '?') part++;
  219.     while (part) {
  220.       char* amp = XP_STRCHR(part, '&');
  221.       if (amp) *amp++ = '\0';
  222.       if (XP_STRNCMP(part, "id=", 3) == 0) {
  223.         cd->msg_id = XP_STRDUP (NET_UnEscape (part+3));
  224.       } else if (XP_STRNCMP(part, "number=", 7) == 0) {
  225.         cd->msgnum = atol(part + 7);
  226.         if (cd->msgnum == 0 && part[7] != '0') cd->msgnum = -1;
  227.       } else if (XP_STRNCMP(part, "uidl=", 5) == 0) {
  228.         /* ### Vile hack time.  If a UIDL was specified, then tell libmsg about
  229.            it, giving it a chance to arrange so that when this URL is all done,
  230.            MSG_GetNewMail gets called. */
  231.         MSG_PrepareToIncUIDL(cd->pane, ce->URL_s, NET_UnEscape(part + 5));
  232.       } else if (ce->URL_s->internal_url &&
  233.                  XP_STRNCMP(part, "compress-folder", 15) == 0) {
  234.         cd->next_state = MAILBOX_COMPRESS_FOLDER;
  235.       } else if (ce->URL_s->internal_url &&
  236.                  XP_STRNCMP(part, "deliver-queued", 14) == 0) {
  237.         cd->next_state = MAILBOX_DELIVER_QUEUED;
  238.       } else if (ce->URL_s->internal_url &&
  239.                  XP_STRNCMP(part, "background", 10) == 0) {
  240.         cd->next_state = MAILBOX_BACKGROUND;
  241.       }
  242.       part = amp;
  243.     }
  244.     FREEIF(search);
  245.     FREEIF(wholeUrl);
  246.  
  247.     cd->initial_state = cd->next_state;
  248.  
  249.     /* don't cache mailbox url's */
  250.     ce->format_out = CLEAR_CACHE_BIT(ce->format_out);
  251.  
  252.        ce->local_file = TRUE;
  253.        ce->socket = NULL;
  254.     NET_SetCallNetlibAllTheTime(ce->window_id, "mkmailbx");
  255.  
  256.     return(net_ProcessMailbox(ce));
  257. }
  258.  
  259.  
  260. /* This doesn't actually generate HTML - but it is our hook into the 
  261.    message display code, so that we can get some values out of it
  262.    after the headers-to-be-displayed have been parsed.
  263.  */
  264. static char *
  265. mail_generate_html_header_fn (const char *dest, void *closure,
  266.                               MimeHeaders *headers)
  267. {
  268.   ActiveEntry *ce = (ActiveEntry *) closure;
  269.   MailboxConData * cd = (MailboxConData *)ce->con_data;
  270.   MSG_ActivateReplyOptions (cd->pane, headers);
  271.   return 0;
  272. }
  273.  
  274.  
  275. static char *
  276. mail_generate_html_footer_fn (const char *dest, void *closure,
  277.                               MimeHeaders *headers)
  278. {
  279.   ActiveEntry *cur_entry = (ActiveEntry *) closure;
  280.   MailboxConData * cd = (MailboxConData *)cur_entry->con_data;
  281.  
  282.   char *uidl = (headers
  283.                 ? MimeHeaders_get(headers, HEADER_X_UIDL, FALSE, FALSE)
  284.                 : 0);
  285.   if (uidl)
  286.     {
  287.       XP_FREE(uidl);
  288.       return MSG_GeneratePartialMessageBlurb (cd->pane,
  289.                                               cur_entry->URL_s,
  290.                                               closure, headers);
  291.     }
  292.   return 0;
  293. }
  294.  
  295.  
  296. static char *
  297. mail_generate_reference_url_fn (const char *dest, void *closure,
  298.                                 MimeHeaders *headers)
  299. {
  300.   ActiveEntry *cur_entry = (ActiveEntry *) closure;
  301.   char *addr = cur_entry->URL_s->address;
  302.   char *search = (addr ? XP_STRCHR (addr, '?') : 0);
  303.   char *id2;
  304.   char *new_dest;
  305.   char *result;
  306.  
  307.   if (!dest || !*dest) return 0;
  308.   id2 = XP_STRDUP (dest);
  309.   if (!id2) return 0;
  310.   if (id2[XP_STRLEN (id2)-1] == '>')
  311.     id2[XP_STRLEN (id2)-1] = 0;
  312.   if (id2[0] == '<')
  313.     new_dest = NET_Escape (id2+1, URL_PATH);
  314.   else
  315.     new_dest = NET_Escape (id2, URL_PATH);
  316.  
  317.   FREEIF (id2);
  318.   result = (char *) XP_ALLOC ((search ? search - addr : 0) +
  319.                               (new_dest ? XP_STRLEN (new_dest) : 0) +
  320.                               40);
  321.   if (result && new_dest)
  322.     {
  323.       if (search)
  324.         {
  325.           XP_MEMCPY (result, addr, search - addr);
  326.           result[search - addr] = 0;
  327.         }
  328.       else if (addr)
  329.         XP_STRCPY (result, addr);
  330.       else
  331.         *result = 0;
  332.       XP_STRCAT (result, "?id=");
  333.       XP_STRCAT (result, new_dest);
  334.  
  335.       if (search && XP_STRSTR (search, "&headers=all"))
  336.         XP_STRCAT (result, "&headers=all");
  337.     }
  338.   FREEIF (new_dest);
  339.   return result;
  340. }
  341.  
  342.  
  343. static int
  344. net_make_mail_msg_stream (ActiveEntry *ce)
  345. {
  346.   MailboxConData * cd = (MailboxConData *)ce->con_data;
  347.  
  348.   StrAllocCopy(ce->URL_s->content_type, MESSAGE_RFC822);
  349.  
  350.   if (ce->format_out == FO_PRESENT || ce->format_out == FO_CACHE_AND_PRESENT)
  351.     {
  352.       MimeDisplayOptions *opt = XP_NEW (MimeDisplayOptions);
  353.       if (!opt) return MK_OUT_OF_MEMORY;
  354.       XP_MEMSET (opt, 0, sizeof(*opt));
  355.  
  356.       opt->generate_reference_url_fn      = mail_generate_reference_url_fn;
  357.       opt->generate_header_html_fn          = 0;
  358.       opt->generate_post_header_html_fn      = mail_generate_html_header_fn;
  359.       opt->generate_footer_html_fn          = mail_generate_html_footer_fn;
  360.       opt->html_closure                      = ce;
  361.       ce->URL_s->fe_data = opt;
  362.     }
  363.   cd->stream = NET_StreamBuilder(ce->format_out, ce->URL_s, ce->window_id);
  364.   if (!cd->stream)
  365.     return MK_UNABLE_TO_CONVERT;
  366.   else
  367.     return 0;
  368. }
  369.  
  370.  
  371. /*
  372.  * returns negative if the transfer is finished or error'd out
  373.  *
  374.  * returns zero or more if the transfer needs to be continued.
  375.  */
  376. PRIVATE int32
  377. net_ProcessMailbox (ActiveEntry *ce)
  378. {
  379.     MailboxConData * cd = (MailboxConData *)ce->con_data;
  380.  
  381.     /* temp, until imap urls have their own identifier */
  382.     if ((!XP_STRNCASECMP(ce->URL_s->address, "mailbox://", 10) ) ||
  383.         (!XP_STRNCASECMP(ce->URL_s->address, "view-source:mailbox://",22)))
  384.         return NET_ProcessIMAP4(ce);
  385.  
  386.     cd->pause_for_read = FALSE; /* already paused; reset */
  387.  
  388.     while(!cd->pause_for_read)
  389.       {
  390. #ifdef DEBUG_username
  391.         XP_Trace("NET_ProcessMailbox: at top of loop, state %d, status %d", cd->next_state, ce->status);
  392. #endif
  393.  
  394.         switch(cd->next_state) {
  395.  
  396.         case MAILBOX_OPEN_FOLDER:
  397.             if (!ce->URL_s->load_background) {
  398.               char *fmt = XP_GetString( XP_MAIL_READING_FOLDER );
  399.               char *folder = cd->folder_name;
  400.               char *s = XP_STRRCHR (folder, '/');
  401.               if (s)
  402.                 folder = s+1;
  403.               s = (char *) XP_ALLOC(XP_STRLEN(fmt) + XP_STRLEN(folder) + 20);
  404.               if (s)
  405.                 {
  406.                   XP_SPRINTF (s, fmt, folder);
  407.                   NET_Progress(ce->window_id, s);
  408.                   XP_FREE(s);
  409.                 }
  410.             }
  411.             ce->status = MSG_BeginOpenFolderSock(cd->pane,
  412.                                                  cd->folder_name, 
  413.                                                  cd->msg_id,
  414.                                                  cd->msgnum,
  415.                                                  &cd->folder_ptr);
  416.  
  417.             if(ce->status == MK_CONNECTED)
  418.               {
  419. #ifdef DEBUG_username
  420.                 XP_Trace ("NET_ProcessMailBox: next state is MAILBOX_OPEN_MESSAGE");
  421. #endif
  422.                 cd->next_state = MAILBOX_OPEN_MESSAGE;
  423.               }
  424.             else if(ce->status > -1)
  425.               {
  426. #ifdef DEBUG_username
  427.                 XP_Trace ("NET_ProcessMailBox: next state is MAILBOX_FINISH_OPEN_FOLDER");
  428. #endif
  429.                 cd->pause_for_read = TRUE;
  430.                 cd->next_state = MAILBOX_FINISH_OPEN_FOLDER;
  431.               }
  432. #ifdef DEBUG_username
  433.             XP_Trace ("NET_ProcessMailBox: MAILBOX_OPEN_FOLDER got error %d", ce->status);
  434. #endif
  435.             break;
  436.  
  437.         case MAILBOX_FINISH_OPEN_FOLDER:
  438.             ce->status = MSG_FinishOpenFolderSock(cd->pane,
  439.                                                   cd->folder_name, 
  440.                                                   cd->msg_id,
  441.                                                   cd->msgnum,
  442.                                                   &cd->folder_ptr);
  443.  
  444.             if(ce->status == MK_CONNECTED)
  445.               {
  446.                 cd->next_state = MAILBOX_OPEN_MESSAGE;
  447.               }
  448.             else
  449.               {
  450.                 cd->pause_for_read = TRUE;
  451.               }
  452.             break;
  453.  
  454.        case MAILBOX_OPEN_MESSAGE:
  455.             if(cd->msg_id == NULL && cd->msgnum < 0)
  456.               {
  457.                 /* only open the message if we are actuall
  458.                  * asking for a message
  459.                   */
  460.                 cd->next_state = MAILBOX_DONE;
  461.               }
  462.             else
  463.               {
  464.                 if (!ce->URL_s->load_background)
  465.                     NET_Progress(ce->window_id,
  466.                                  XP_GetString( XP_MAIL_READING_MESSAGE ) );
  467.                 ce->status = MSG_OpenMessageSock(cd->pane,
  468.                                                  cd->folder_name,
  469.                                                  cd->msg_id,
  470.                                                  cd->msgnum,
  471.                                                  cd->folder_ptr, 
  472.                                                  &cd->msg_ptr,
  473.                                                  &ce->URL_s->content_length);
  474.                 cd->next_state = MAILBOX_OPEN_STREAM;
  475.               }
  476.             break;
  477.  
  478.        case MAILBOX_OPEN_STREAM:
  479.          {
  480.             ce->status = net_make_mail_msg_stream (ce);
  481.             if (ce->status < 0)
  482.               {
  483.                 ce->URL_s->error_msg = NET_ExplainErrorDetails(ce->status);
  484.                 return(ce->status);
  485.                 }
  486.             else
  487.               {
  488.                 XP_ASSERT (cd->stream);
  489.                 cd->next_state = MAILBOX_READ_MESSAGE;
  490.               }
  491.  
  492.             if (!ce->URL_s->load_background) {
  493.                 FE_GraphProgressInit(ce->window_id, ce->URL_s,
  494.                                      ce->URL_s->content_length);
  495.                 cd->destroy_graph_progress = TRUE;
  496.             }
  497.             cd->original_content_length = ce->URL_s->content_length;
  498.          }
  499.          break;
  500.  
  501.        case MAILBOX_READ_MESSAGE:
  502.             {
  503.                 int32 read_size;
  504.     
  505.                 cd->pause_for_read  = TRUE;
  506.                 read_size = (*cd->stream->is_write_ready)
  507.                                             (cd->stream);
  508.  
  509.                 if (cd->input_buffer == NULL) {
  510.                     cd->input_buffer_size = 10240;
  511. #ifdef DEBUG_ricardob
  512.                     cd->input_buffer_size *= 2;
  513. #endif
  514.                     while (cd->input_buffer == NULL) {
  515.                         cd->input_buffer =
  516.                             (char*) XP_ALLOC(cd->input_buffer_size);
  517.                         if (!cd->input_buffer) {
  518.                             cd->input_buffer_size /= 2;
  519.                             if (cd->input_buffer_size < 512) {
  520.                                 ce->status = MK_OUT_OF_MEMORY;
  521.                                 break;
  522.                             }
  523.                         }
  524.                     }
  525.                     if (cd->input_buffer == NULL) break;
  526.                 }
  527.  
  528.                 if(!read_size)
  529.                     {
  530.                     return(0);  /* wait until we are ready to write */
  531.                     }
  532.                 else
  533.                     {
  534.                     read_size = MIN(read_size, cd->input_buffer_size);
  535.                     }
  536.  
  537.                 ce->status = MSG_ReadMessageSock(cd->pane,
  538.                                                  cd->folder_name,
  539.                                                  cd->msg_ptr,
  540.                                                  cd->msg_id,
  541.                                                  cd->msgnum,
  542.                                                  cd->input_buffer,
  543.                                                  read_size);
  544.  
  545.                 if(ce->status > 0)
  546.                   {
  547.                     ce->bytes_received += ce->status;
  548.                     if (!ce->URL_s->load_background)
  549.                         FE_GraphProgress(ce->window_id, ce->URL_s,
  550.                                          ce->bytes_received, ce->status,
  551.                                          ce->URL_s->content_length);
  552.  
  553.                     ce->status = PUT_STREAM(cd->input_buffer, ce->status);
  554.                   }
  555.                 else if(ce->status == 0)
  556.                     cd->next_state = MAILBOX_DONE;
  557.             }
  558.             break;
  559.  
  560.         case MAILBOX_COMPRESS_FOLDER:
  561.             if ((cd->initial_state == MAILBOX_COMPRESS_FOLDER) &&
  562.                 (!ce->URL_s->load_background)) {
  563.                 char *fmt= XP_GetString( XP_COMPRESSING_FOLDER );
  564.                 char *folder = cd->folder_name;
  565.                 char *s = XP_STRRCHR (folder, '/');
  566.                 if (s)
  567.                   folder = s+1;
  568.                 s = (char *)XP_ALLOC (XP_STRLEN(fmt) + XP_STRLEN(folder) + 20);
  569.                 if (s)
  570.                   {
  571.                     XP_SPRINTF (s, fmt, folder);
  572.                     NET_Progress(ce->window_id, s);
  573.                     XP_FREE(s);
  574.                   }
  575.               }
  576.             ce->status = MSG_BeginCompressFolder(cd->pane, ce->URL_s,
  577.                                                  cd->folder_name,
  578.                                                  &cd->compress_folder_ptr);
  579.             if (ce->status == MK_CONNECTED) {
  580.               cd->next_state = MAILBOX_DONE;
  581.             } else {
  582.               cd->pause_for_read = TRUE;
  583.               cd->next_state = MAILBOX_FINISH_COMPRESS_FOLDER;
  584.             }
  585.             break;
  586.           
  587.         case MAILBOX_FINISH_COMPRESS_FOLDER:
  588.             ce->status = MSG_FinishCompressFolder(cd->pane, ce->URL_s,
  589.                                                   cd->folder_name,
  590.                                                   cd->compress_folder_ptr);
  591.             if (ce->status == MK_CONNECTED) {
  592.               cd->next_state = MAILBOX_DONE;
  593.             } else {
  594.               cd->pause_for_read = TRUE;
  595.             }
  596.             break;
  597.  
  598.         case MAILBOX_BACKGROUND:
  599.             ce->status = MSG_ProcessBackground(ce->URL_s);
  600.             if (ce->status == MK_CONNECTED) {
  601.               cd->next_state = MAILBOX_DONE;
  602.             } else {
  603.               cd->pause_for_read = TRUE;
  604.             }
  605.             break;
  606.  
  607.         case MAILBOX_DELIVER_QUEUED:
  608.             if (!ce->URL_s->load_background)
  609.                 NET_Progress(ce->window_id,
  610.                              XP_GetString( XP_MAIL_DELIVERING_QUEUED_MESSAGES ) );
  611.             ce->status = MSG_BeginDeliverQueued(cd->pane, ce->URL_s,
  612.                                                 &cd->deliver_queued_ptr);
  613.             if (ce->status == MK_CONNECTED) {
  614.               cd->next_state = MAILBOX_DONE;
  615.             } else {
  616.               cd->pause_for_read = TRUE;
  617.               cd->next_state = MAILBOX_FINISH_DELIVER_QUEUED;
  618.             }
  619.             break;
  620.  
  621.         case MAILBOX_FINISH_DELIVER_QUEUED:
  622.             ce->status = MSG_FinishDeliverQueued(cd->pane, ce->URL_s,
  623.                                                  cd->deliver_queued_ptr);
  624.             if (ce->status == MK_CONNECTED) {
  625.               cd->next_state = MAILBOX_DONE;
  626.             } else {
  627.               cd->pause_for_read = TRUE;
  628.             }
  629.             break;
  630.         
  631.         case MAILBOX_COPY_MESSAGES:
  632.             ce->status = MSG_BeginCopyingMessages(ce->window_id);
  633.             if (ce->status == MK_CONNECTED) 
  634.                 cd->next_state = MAILBOX_DONE;
  635.             else
  636.             {
  637.                 cd->pause_for_read = TRUE;
  638.                 cd->next_state = MAILBOX_FINISH_COPY_MESSAGES;
  639.             }
  640.             break;
  641.  
  642.         case MAILBOX_FINISH_COPY_MESSAGES:
  643.             ce->status = MSG_FinishCopyingMessages(ce->window_id);
  644.             if (ce->status == MK_CONNECTED) 
  645.                 cd->next_state = MAILBOX_DONE;
  646.             else 
  647.                 cd->pause_for_read = TRUE;
  648.             break;
  649.  
  650.         case MAILBOX_DONE:
  651.             if(cd->stream)
  652.               {
  653.                 COMPLETE_STREAM;
  654.                 FREE(cd->stream);
  655.               }
  656.             cd->next_state = MAILBOX_FREE;
  657.             break;
  658.         
  659.         case MAILBOX_ERROR_DONE:
  660.             if(cd->stream)
  661.               {
  662.                 ABORT_STREAM(ce->status);
  663.                 FREE(cd->stream);
  664.               }
  665.             cd->next_state = MAILBOX_FREE;
  666.  
  667.             if (ce->status < -1 && !ce->URL_s->error_msg)
  668.               ce->URL_s->error_msg = NET_ExplainErrorDetails(ce->status);
  669.  
  670.             break;
  671.         
  672.         case MAILBOX_FREE:
  673.               NET_ClearCallNetlibAllTheTime(ce->window_id, "mkmailbx");
  674.  
  675.             if (cd->input_buffer) {
  676.                 XP_FREE(cd->input_buffer);
  677.                 cd->input_buffer = NULL;
  678.             }
  679.  
  680.             if(cd->destroy_graph_progress)
  681.               FE_GraphProgressDestroy(ce->window_id, 
  682.                                       ce->URL_s, 
  683.                                       cd->original_content_length,
  684.                                       ce->bytes_received);
  685.  
  686.             if(cd->msg_ptr)
  687.               {
  688.                 MSG_CloseMessageSock(cd->pane, cd->folder_name,
  689.                                      cd->msg_id, cd->msgnum, cd->msg_ptr);
  690.                 cd->msg_ptr = NULL;
  691.                 if (!ce->URL_s->load_background)
  692.                     NET_Progress(ce->window_id,
  693.                                  XP_GetString( XP_READING_MESSAGE_DONE ) );
  694.               }
  695.  
  696.             if(cd->folder_ptr)
  697.               {
  698.                 MSG_CloseFolderSock(cd->pane, cd->folder_name,
  699.                                     cd->msg_id, cd->msgnum, cd->folder_ptr);
  700.                 if ((cd->msg_id == NULL && cd->msgnum < 0) &&
  701.                     (!ce->URL_s->load_background))
  702.                   /* If we read a message, don't hide the previous message
  703.                      with this one. */
  704.                     NET_Progress(ce->window_id,
  705.                                  XP_GetString( XP_MAIL_READING_FOLDER_DONE ) );
  706.               }
  707.  
  708.             if(cd->compress_folder_ptr)
  709.               {
  710.                 MSG_CloseCompressFolderSock(cd->pane, ce->URL_s,
  711.                                             cd->compress_folder_ptr);
  712.                 cd->compress_folder_ptr = NULL;
  713.                 if ((cd->initial_state == MAILBOX_COMPRESS_FOLDER) &&
  714.                     (!ce->URL_s->load_background))
  715.                   NET_Progress(ce->window_id,
  716.                              XP_GetString( XP_MAIL_COMPRESSING_FOLDER_DONE ) );
  717.               }
  718.             if(cd->deliver_queued_ptr)
  719.               {
  720.                 MSG_CloseDeliverQueuedSock(cd->pane, ce->URL_s,
  721.                                            cd->deliver_queued_ptr);
  722.                 cd->deliver_queued_ptr = NULL;
  723.                 if (!ce->URL_s->load_background)
  724.                     NET_Progress(ce->window_id,
  725.                                  XP_GetString( XP_MAIL_DELIVERING_QUEUED_MESSAGES_DONE ) );
  726.               }
  727.             FREEIF(cd->folder_name);
  728.             FREEIF(cd->msg_id);
  729.             FREE(cd);
  730.  
  731.             return(-1); /* final end */
  732.         
  733.         default: /* should never happen !!! */
  734.             TRACEMSG(("MAILBOX: BAD STATE!"));
  735.             XP_ASSERT(0);
  736.             cd->next_state = MAILBOX_ERROR_DONE;
  737.             break;
  738.         }
  739.  
  740.         /* check for errors during load and call error 
  741.          * state if found
  742.          */
  743.         if(ce->status < 0 && cd->next_state != MAILBOX_FREE)
  744.           {
  745.             cd->next_state = MAILBOX_ERROR_DONE;
  746.             /* don't exit! loop around again and do the free case */
  747.             cd->pause_for_read = FALSE;
  748.           }
  749.       } /* while(!cd->pause_for_read) */
  750.     
  751. #ifdef DEBUG_username
  752.       XP_Trace ("Leaving NET_ProcessMailbox with status %d", ce->status);
  753. #endif
  754.  
  755.     return(ce->status);
  756. }
  757.  
  758. /* abort the connection in progress
  759.  */
  760. PRIVATE int32
  761. net_InterruptMailbox(ActiveEntry * ce)
  762. {
  763.     MailboxConData * cd = (MailboxConData *)ce->con_data;
  764.  
  765.     /* temp until imap urls have their own identifier */
  766.     if (!XP_STRNCASECMP(ce->URL_s->address, "mailbox://", 10) )
  767.         return NET_InterruptIMAP4(ce);
  768.  
  769.     cd->next_state = MAILBOX_ERROR_DONE;
  770.     ce->status = MK_INTERRUPTED;
  771.  
  772.     return(net_ProcessMailbox(ce));
  773. }
  774.  
  775. /* Free any memory that might be used in caching etc.
  776.  */
  777. PRIVATE void
  778. net_CleanupMailbox(void)
  779. {
  780.     /* nothing so far needs freeing */
  781.     return;
  782. }
  783.  
  784. MODULE_PRIVATE void
  785. NET_InitMailboxProtocol(void)
  786. {
  787.     static NET_ProtoImpl mailbox_proto_impl;
  788.  
  789.     mailbox_proto_impl.init = net_MailboxLoad;
  790.     mailbox_proto_impl.process = net_ProcessMailbox;
  791.     mailbox_proto_impl.interrupt = net_InterruptMailbox;
  792.     mailbox_proto_impl.cleanup = net_CleanupMailbox;
  793.  
  794.     NET_RegisterProtocolImplementation(&mailbox_proto_impl, MAILBOX_TYPE_URL);
  795. }
  796.  
  797. /* Since each search may be composed of multiple distinct URLs to
  798.  * process, use a "search:" URL as a meta-URL which schedules the
  799.  * subparts for processing
  800.  */
  801. PRIVATE int32 
  802. net_ProcessMsgSearch (ActiveEntry *ce)
  803. {
  804. /*    MailboxConData *cd = (MailboxConData *) ce->con_data;*/
  805.     int retVal = MSG_ProcessSearch (ce->window_id);
  806.     ce->status = 0;
  807.     
  808.     if (0 != retVal)
  809.     {
  810.         /* stop this crazy thing */
  811.            NET_ClearCallNetlibAllTheTime(ce->window_id, "mkmailbx");
  812.     }
  813.     return retVal;
  814. }
  815.  
  816. PRIVATE int32
  817. net_MsgSearchLoad (ActiveEntry *ce)
  818. {
  819.     /* don't cache search urls */
  820.     ce->format_out = CLEAR_CACHE_BIT(ce->format_out);
  821.  
  822.        ce->local_file = TRUE;
  823.        ce->socket = NULL;
  824.     NET_SetCallNetlibAllTheTime(ce->window_id, "mkmailbx");
  825.     return 0; 
  826. }
  827.  
  828. PRIVATE int32
  829. net_InterruptMsgSearch (ActiveEntry *ce)
  830. {
  831.     return MSG_InterruptSearch (ce->window_id);
  832. }
  833.  
  834. /* Free any memory that might be used in caching etc.
  835.  */
  836. PRIVATE void
  837. net_CleanupMsgSearch(void)
  838. {
  839.     /* nothing so far needs freeing */
  840.     return;
  841. }
  842.  
  843. MODULE_PRIVATE void
  844. NET_InitMsgSearchProtocol(void)
  845. {
  846.     static NET_ProtoImpl msgsearch_proto_impl;
  847.  
  848.     msgsearch_proto_impl.init = net_MsgSearchLoad;
  849.     msgsearch_proto_impl.process = net_ProcessMsgSearch;
  850.     msgsearch_proto_impl.interrupt = net_InterruptMsgSearch;
  851.     msgsearch_proto_impl.cleanup = net_CleanupMsgSearch;
  852.  
  853.     NET_RegisterProtocolImplementation(&msgsearch_proto_impl, MSG_SEARCH_TYPE_URL);
  854. }
  855.