home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmime / mimeebod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  13.7 KB  |  525 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. /* mimeext.c --- definition of the MimeExternalBody class (see mimei.h)
  20.    Created: Jamie Zawinski <jwz@netscape.com>, 15-May-96.
  21.  */
  22.  
  23.  
  24. #include "mimeebod.h"
  25. #include "xpgetstr.h"
  26.  
  27. #define MIME_SUPERCLASS mimeObjectClass
  28. MimeDefClass(MimeExternalBody, MimeExternalBodyClass,
  29.              mimeExternalBodyClass, &MIME_SUPERCLASS);
  30.  
  31. extern int MK_MSG_LINK_TO_DOCUMENT;
  32. extern int MK_MSG_DOCUMENT_INFO;
  33.  
  34. #if defined(XP_MAC) && !defined(MOZILLA_30)
  35. extern MimeObjectClass mimeMultipartAppleDoubleClass;
  36. #endif
  37.  
  38. static int MimeExternalBody_initialize (MimeObject *);
  39. static void MimeExternalBody_finalize (MimeObject *);
  40. static int MimeExternalBody_parse_line (char *, int32, MimeObject *);
  41. static int MimeExternalBody_parse_eof (MimeObject *, XP_Bool);
  42. static XP_Bool MimeExternalBody_displayable_inline_p (MimeObjectClass *class,
  43.                                                       MimeHeaders *hdrs);
  44.  
  45. #if 0
  46. #if defined(DEBUG) && defined(XP_UNIX)
  47. static int MimeExternalBody_debug_print (MimeObject *, FILE *, int32);
  48. #endif
  49. #endif /* 0 */
  50.  
  51. static int
  52. MimeExternalBodyClassInitialize(MimeExternalBodyClass *class)
  53. {
  54.   MimeObjectClass *oclass = (MimeObjectClass *) class;
  55.  
  56.   XP_ASSERT(!oclass->class_initialized);
  57.   oclass->initialize  = MimeExternalBody_initialize;
  58.   oclass->finalize    = MimeExternalBody_finalize;
  59.   oclass->parse_line  = MimeExternalBody_parse_line;
  60.   oclass->parse_eof  = MimeExternalBody_parse_eof;
  61.   oclass->displayable_inline_p = MimeExternalBody_displayable_inline_p;
  62.  
  63. #if 0
  64. #if defined(DEBUG) && defined(XP_UNIX)
  65.   oclass->debug_print = MimeExternalBody_debug_print;
  66. #endif
  67. #endif /* 0 */
  68.  
  69.   return 0;
  70. }
  71.  
  72.  
  73. static int
  74. MimeExternalBody_initialize (MimeObject *object)
  75. {
  76.   return ((MimeObjectClass*)&MIME_SUPERCLASS)->initialize(object);
  77. }
  78.  
  79. static void
  80. MimeExternalBody_finalize (MimeObject *object)
  81. {
  82.   MimeExternalBody *bod = (MimeExternalBody *) object;
  83.   if (bod->hdrs)
  84.     {
  85.       MimeHeaders_free(bod->hdrs);
  86.       bod->hdrs = 0;
  87.     }
  88.   FREEIF(bod->body);
  89.  
  90.   ((MimeObjectClass*)&MIME_SUPERCLASS)->finalize(object);
  91. }
  92.  
  93. static int
  94. MimeExternalBody_parse_line (char *line, int32 length, MimeObject *obj)
  95. {
  96.   MimeExternalBody *bod = (MimeExternalBody *) obj;
  97.   int status = 0;
  98.  
  99.   XP_ASSERT(line && *line);
  100.   if (!line || !*line) return -1;
  101.  
  102.   if (!obj->output_p) return 0;
  103.  
  104.   /* If we're supposed to write this object, but aren't supposed to convert
  105.      it to HTML, simply pass it through unaltered. */
  106.   if (obj->options &&
  107.       !obj->options->write_html_p &&
  108.       obj->options->output_fn)
  109.     return MimeObject_write(obj, line, length, TRUE);
  110.  
  111.  
  112.   /* If we already have a `body' then we're done parsing headers, and all
  113.      subsequent lines get tacked onto the body. */
  114.   if (bod->body)
  115.     {
  116.       int L = XP_STRLEN(bod->body);
  117.       char *new_str = XP_REALLOC(bod->body, L + length + 1);
  118.       if (!new_str) return MK_OUT_OF_MEMORY;
  119.       bod->body = new_str;
  120.       XP_MEMCPY(bod->body + L, line, length);
  121.       bod->body[L + length] = 0;
  122.       return 0;
  123.     }
  124.  
  125.   /* Otherwise we don't yet have a body, which means we're not done parsing
  126.      our headers.
  127.    */
  128.   if (!bod->hdrs)
  129.     {
  130.       bod->hdrs = MimeHeaders_new();
  131.       if (!bod->hdrs) return MK_OUT_OF_MEMORY;
  132.     }
  133.  
  134.   status = MimeHeaders_parse_line(line, length, bod->hdrs);
  135.   if (status < 0) return status;
  136.  
  137.   /* If this line is blank, we're now done parsing headers, and should
  138.      create a dummy body to show that.  Gag.
  139.    */
  140.   if (*line == CR || *line == LF)
  141.     {
  142.       bod->body = XP_STRDUP("");
  143.       if (!bod->body) return MK_OUT_OF_MEMORY;
  144.     }
  145.  
  146.   return 0;
  147. }
  148.  
  149.  
  150. char *
  151. MimeExternalBody_make_url(const char *ct,
  152.                           const char *at, const char *exp, const char *size,
  153.                           const char *perm, const char *dir, const char *mode,
  154.                           const char *name, const char *url, const char *site,
  155.                           const char *svr, const char *subj, const char *body)
  156. {
  157.   char *s;
  158.   if (!strcasecomp(at, "ftp") || !strcasecomp(at, "anon-ftp"))
  159.     {
  160.       if (!site || !name)
  161.         return 0;
  162.       s = (char *) XP_ALLOC(XP_STRLEN(name) + XP_STRLEN(site) +
  163.                             (dir  ? XP_STRLEN(dir) : 0) + 20);
  164.       if (!s) return 0;
  165.       XP_STRCPY(s, "ftp://");
  166.       XP_STRCAT(s, site);
  167.       XP_STRCAT(s, "/");
  168.       if (dir) XP_STRCAT(s, (dir[0] == '/' ? dir+1 : dir));
  169.       if (s[XP_STRLEN(s)-1] != '/')
  170.         XP_STRCAT(s, "/");
  171.       XP_STRCAT(s, name);
  172.       return s;
  173.     }
  174.   else if (!strcasecomp(at, "local-file") || !strcasecomp(at, "afs"))
  175.     {
  176.       char *s2;
  177.       if (!name)
  178.         return 0;
  179.  
  180. #ifdef XP_UNIX
  181.       if (!strcasecomp(at, "afs"))   /* only if there is a /afs/ directory */
  182.         {
  183.           XP_StatStruct st;
  184.           if (stat("/afs/.", &st))
  185.             return 0;
  186.         }
  187. #else  /* !XP_UNIX */
  188.       return 0;                        /* never, if not Unix. */
  189. #endif /* !XP_UNIX */
  190.  
  191.       s = (char *) XP_ALLOC(XP_STRLEN(name)*3 + 20);
  192.       if (!s) return 0;
  193.       XP_STRCPY(s, "file:");
  194.  
  195.       s2 = NET_Escape(name, URL_PATH);
  196.       if (s2) XP_STRCAT(s, s2);
  197.       FREEIF(s2);
  198.       return s;
  199.     }
  200.   else if (!strcasecomp(at, "mail-server"))
  201.     {
  202.       char *s2;
  203.       if (!svr)
  204.         return 0;
  205.       s = (char *) XP_ALLOC(XP_STRLEN(svr)*4 +
  206.                             (subj ? XP_STRLEN(subj)*4 : 0) +
  207.                             (body ? XP_STRLEN(body)*4 : 0) + 20);
  208.       if (!s) return 0;
  209.       XP_STRCPY(s, "mailto:");
  210.  
  211.       s2 = NET_Escape(svr, URL_XALPHAS);
  212.       if (s2) XP_STRCAT(s, s2);
  213.       FREEIF(s2);
  214.  
  215.       if (subj)
  216.         {
  217.           s2 = NET_Escape(subj, URL_XALPHAS);
  218.           XP_STRCAT(s, "?subject=");
  219.           if (s2) XP_STRCAT(s, s2);
  220.           FREEIF(s2);
  221.         }
  222.       if (body)
  223.         {
  224.           s2 = NET_Escape(body, URL_XALPHAS);
  225.           XP_STRCAT(s, (subj ? "&body=" : "?body="));
  226.           if (s2) XP_STRCAT(s, s2);
  227.           FREEIF(s2);
  228.         }
  229.       return s;
  230.     }
  231.   else if (!strcasecomp(at, "url"))        /* RFC 2017 */
  232.     {
  233.       if (url)
  234.         return XP_STRDUP(url);           /* it's already quoted and everything */
  235.       else
  236.         return 0;
  237.     }
  238.   else
  239.     return 0;
  240. }
  241.  
  242. #ifdef XP_MAC
  243. #ifdef DEBUG
  244. #pragma global_optimizer on
  245. #pragma optimization_level 1
  246. #endif /* DEBUG */
  247. #endif /* XP_MAC */
  248.  
  249. static int
  250. MimeExternalBody_parse_eof (MimeObject *obj, XP_Bool abort_p)
  251. {
  252.   int status = 0;
  253.   MimeExternalBody *bod = (MimeExternalBody *) obj;
  254.  
  255.   if (obj->closed_p) return 0;
  256.  
  257.   /* Run parent method first, to flush out any buffered data. */
  258.   status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
  259.   if (status < 0) return status;
  260.  
  261. #if defined(XP_MAC) && !defined(MOZILLA_30)
  262.   if (obj->parent && mime_typep(obj->parent, 
  263.       (MimeObjectClass*) &mimeMultipartAppleDoubleClass))
  264.       goto done;
  265. #endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
  266.  
  267.   if (!abort_p &&
  268.       obj->output_p &&
  269.       obj->options &&
  270.       obj->options->write_html_p)
  271.     {
  272.       XP_Bool all_headers_p = obj->options->headers == MimeHeadersAll;
  273.       MimeDisplayOptions newopt = *obj->options;  /* copy it */
  274.  
  275.       char *ct = MimeHeaders_get(obj->headers, HEADER_CONTENT_TYPE,
  276.                                  FALSE, FALSE);
  277.       char *at, *exp, *size, *perm;
  278.       char *url, *dir, *mode, *name, *site, *svr, *subj;
  279.       char *h = 0, *lname = 0, *lurl = 0, *body = 0;
  280.       MimeHeaders *hdrs = 0;
  281.  
  282.       if (!ct) return MK_OUT_OF_MEMORY;
  283.  
  284.       at   = MimeHeaders_get_parameter(ct, "access-type");
  285.       exp  = MimeHeaders_get_parameter(ct, "expiration");
  286.       size = MimeHeaders_get_parameter(ct, "size");
  287.       perm = MimeHeaders_get_parameter(ct, "permission");
  288.       dir  = MimeHeaders_get_parameter(ct, "directory");
  289.       mode = MimeHeaders_get_parameter(ct, "mode");
  290.       name = MimeHeaders_get_parameter(ct, "name");
  291.       site = MimeHeaders_get_parameter(ct, "site");
  292.       svr  = MimeHeaders_get_parameter(ct, "server");
  293.       subj = MimeHeaders_get_parameter(ct, "subject");
  294.       url  = MimeHeaders_get_parameter(ct, "url");
  295.       FREEIF(ct);
  296.  
  297.       /* the *internal* content-type */
  298.       ct = MimeHeaders_get(bod->hdrs, HEADER_CONTENT_TYPE,
  299.                            TRUE, FALSE);
  300.  
  301.       h = (char *) XP_ALLOC((at ? XP_STRLEN(at) : 0) +
  302.                             (exp ? XP_STRLEN(exp) : 0) +
  303.                             (size ? XP_STRLEN(size) : 0) +
  304.                             (perm ? XP_STRLEN(perm) : 0) +
  305.                             (dir ? XP_STRLEN(dir) : 0) +
  306.                             (mode ? XP_STRLEN(mode) : 0) +
  307.                             (name ? XP_STRLEN(name) : 0) +
  308.                             (site ? XP_STRLEN(site) : 0) +
  309.                             (svr ? XP_STRLEN(svr) : 0) +
  310.                             (subj ? XP_STRLEN(subj) : 0) +
  311.                             (url ? XP_STRLEN(url) : 0) + 100);
  312.       if (!h)
  313.         {
  314.           status = MK_OUT_OF_MEMORY;
  315.           goto FAIL;
  316.         }
  317.  
  318.       /* If there's a URL parameter, remove all whitespace from it.
  319.          (The URL parameter to one of these headers is stored with
  320.          lines broken every 40 characters or less; it's assumed that
  321.          all significant whitespace was URL-hex-encoded, and all the
  322.          rest of it was inserted just to keep the lines short.)
  323.        */
  324.       if (url)
  325.         {
  326.           char *in, *out;
  327.           for (in = url, out = url; *in; in++)
  328.             if (!XP_IS_SPACE(*in))
  329.               *out++ = *in;
  330.           *out = 0;
  331.         }
  332.  
  333.       hdrs = MimeHeaders_new();
  334.       if (!hdrs)
  335.         {
  336.           status = MK_OUT_OF_MEMORY;
  337.           goto FAIL;
  338.         }
  339.  
  340. # define FROB(STR,VAR) \
  341.       if (VAR) \
  342.         { \
  343.           XP_STRCPY(h, STR ": "); \
  344.           XP_STRCAT(h, VAR); \
  345.           XP_STRCAT(h, LINEBREAK); \
  346.           status = MimeHeaders_parse_line(h, XP_STRLEN(h), hdrs); \
  347.           if (status < 0) goto FAIL; \
  348.         }
  349.       FROB("Access-Type",    at);
  350.       FROB("URL",            url);
  351.       FROB("Site",            site);
  352.       FROB("Server",        svr);
  353.       FROB("Directory",        dir);
  354.       FROB("Name",            name);
  355.       FROB("Type",            ct);
  356.       FROB("Size",            size);
  357.       FROB("Mode",            mode);
  358.       FROB("Permission",    perm);
  359.       FROB("Expiration",    exp);
  360.       FROB("Subject",        subj);
  361. # undef FROB
  362.       XP_STRCPY(h, LINEBREAK);
  363.       status = MimeHeaders_parse_line(h, XP_STRLEN(h), hdrs);
  364.       if (status < 0) goto FAIL;
  365.  
  366.       lurl = MimeExternalBody_make_url(ct, at, exp, size, perm, dir, mode,
  367.                                        name, url, site, svr, subj, bod->body);
  368.       if (lurl)
  369.         {
  370.           lname = XP_STRDUP(XP_GetString(MK_MSG_LINK_TO_DOCUMENT));
  371.         }
  372.       else
  373.         {
  374.           lname = XP_STRDUP(XP_GetString(MK_MSG_DOCUMENT_INFO));
  375.           all_headers_p = TRUE;
  376.         }
  377.         
  378.       all_headers_p = TRUE;  /* #### just do this all the time? */
  379.  
  380.       if (bod->body && all_headers_p)
  381.         {
  382.           char *s = bod->body;
  383.           while (XP_IS_SPACE(*s)) s++;
  384.           if (*s)
  385.             {
  386.               char *s2;
  387.               const char *pre = "<P><PRE>";
  388.               const char *suf = "</PRE>";
  389.               int32 i;
  390.               for(i = XP_STRLEN(s)-1; i >= 0 && XP_IS_SPACE(s[i]); i--)
  391.                 s[i] = 0;
  392.               s2 = NET_EscapeHTML(s);
  393.               if (!s2) goto FAIL;
  394.               body = (char *) XP_ALLOC(XP_STRLEN(pre) + XP_STRLEN(s2) +
  395.                                        XP_STRLEN(suf) + 1);
  396.               if (!body)
  397.                 {
  398.                   XP_FREE(s2);
  399.                   goto FAIL;
  400.                 }
  401.               XP_STRCPY(body, pre);
  402.               XP_STRCAT(body, s2);
  403.               XP_STRCAT(body, suf);
  404.             }
  405.         }
  406.  
  407.       newopt.fancy_headers_p = TRUE;
  408.       newopt.headers = (all_headers_p ? MimeHeadersAll : MimeHeadersSome);
  409.  
  410.       {
  411.         char p[] = "<P>";
  412.         status = MimeObject_write(obj, p, 3, FALSE);
  413.         if (status < 0) goto FAIL;
  414.       }
  415.  
  416.       status = MimeHeaders_write_attachment_box (hdrs, &newopt, ct, 0,
  417.                                                  lname, lurl, body);
  418.       if (status < 0) goto FAIL;
  419.  
  420.       {
  421.         char p[] = "<P>";
  422.         status = MimeObject_write(obj, p, 3, FALSE);
  423.         if (status < 0) goto FAIL;
  424.       }
  425.  
  426.     FAIL:
  427.       if (hdrs)
  428.         MimeHeaders_free(hdrs);
  429.       FREEIF(h);
  430.       FREEIF(lname);
  431.       FREEIF(lurl);
  432.       FREEIF(body);
  433.       FREEIF(ct);
  434.       FREEIF(at);
  435.       FREEIF(exp);
  436.       FREEIF(size);
  437.       FREEIF(perm);
  438.       FREEIF(dir);
  439.       FREEIF(mode);
  440.       FREEIF(name);
  441.       FREEIF(url);
  442.       FREEIF(site);
  443.       FREEIF(svr);
  444.       FREEIF(subj);
  445.     }
  446.  
  447. #if defined(XP_MAC) && !defined(MOZILLA_30)
  448. done:
  449. #endif /* defined (XP_MAC) && !defined(MOZILLA_30) */
  450.  
  451.   return status;
  452. }
  453.  
  454. #ifdef XP_MAC
  455. #ifdef DEBUG
  456. #pragma global_optimizer reset
  457. #endif /* DEBUG */
  458. #endif /* XP_MAC */
  459.  
  460. #if 0
  461. #if defined(DEBUG) && defined(XP_UNIX)
  462. static int
  463. MimeExternalBody_debug_print (MimeObject *obj, FILE *stream, int32 depth)
  464. {
  465.   MimeExternalBody *bod = (MimeExternalBody *) obj;
  466.   int i;
  467.   char *ct, *ct2;
  468.   char *addr = mime_part_address(obj);
  469.  
  470.   if (obj->headers)
  471.     ct = MimeHeaders_get (obj->headers, HEADER_CONTENT_TYPE, FALSE, FALSE);
  472.   if (bod->hdrs)
  473.     ct2 = MimeHeaders_get (bod->hdrs, HEADER_CONTENT_TYPE, FALSE, FALSE);
  474.  
  475.   for (i=0; i < depth; i++)
  476.     fprintf(stream, "  ");
  477.   fprintf(stream,
  478.           "<%s %s\n"
  479.           "\tcontent-type: %s\n"
  480.           "\tcontent-type: %s\n"
  481.           "\tBody:%s\n\t0x%08X>\n\n",
  482.           obj->class->class_name,
  483.           addr ? addr : "???",
  484.           ct ? ct : "<none>",
  485.           ct2 ? ct2 : "<none>",
  486.           bod->body ? bod->body : "<none>",
  487.           (uint32) obj);
  488.   FREEIF(addr);
  489.   FREEIF(ct);
  490.   FREEIF(ct2);
  491.   return 0;
  492. }
  493. #endif
  494. #endif /* 0 */
  495.  
  496. static XP_Bool
  497. MimeExternalBody_displayable_inline_p (MimeObjectClass *class,
  498.                                        MimeHeaders *hdrs)
  499. {
  500.   char *ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, FALSE, FALSE);
  501.   char *at = MimeHeaders_get_parameter(ct, "access-type");
  502.   XP_Bool inline_p = FALSE;
  503.  
  504.   if (!at)
  505.     ;
  506.   else if (!strcasecomp(at, "ftp") ||
  507.            !strcasecomp(at, "anon-ftp") ||
  508.            !strcasecomp(at, "local-file") ||
  509.            !strcasecomp(at, "mail-server") ||
  510.            !strcasecomp(at, "url"))
  511.     inline_p = TRUE;
  512. #ifdef XP_UNIX
  513.   else if (!strcasecomp(at, "afs"))   /* only if there is a /afs/ directory */
  514.     {
  515.       XP_StatStruct st;
  516.       if (!stat("/afs/.", &st))
  517.         inline_p = TRUE;
  518.     }
  519. #endif /* XP_UNIX */
  520.  
  521.   FREEIF(ct);
  522.   FREEIF(at);
  523.   return inline_p;
  524. }
  525.