home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / mpackPPC.lha / mpackPPC / src / encode.c < prev    next >
C/C++ Source or Header  |  1998-04-08  |  7KB  |  246 lines

  1. /* (C) Copyright 1993,1994 by Carnegie Mellon University
  2.  * All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without
  6.  * fee, provided that the above copyright notice appear in all copies
  7.  * and that both that copyright notice and this permission notice
  8.  * appear in supporting documentation, and that the name of Carnegie
  9.  * Mellon University not be used in advertising or publicity
  10.  * pertaining to distribution of the software without specific,
  11.  * written prior permission.  Carnegie Mellon University makes no
  12.  * representations about the suitability of this software for any
  13.  * purpose.  It is provided "as is" without express or implied
  14.  * warranty.
  15.  *
  16.  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  17.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  19.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  21.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  22.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23.  * SOFTWARE.
  24.  */
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. extern char *magic_look();
  29. extern char *os_genid();
  30. extern char *md5digest();
  31.  
  32. #define NUMREFERENCES 4
  33.  
  34. /*
  35.  * Encode a file into one or more MIME messages, each
  36.  * no larger than 'maxsize'.  A 'maxsize' of zero means no size limit.
  37.  * If 'applefile' is non-null, it is the first part of a multipart/appledouble
  38.  * pair.
  39.  */
  40. int encode(infile, applefile, fname, descfile, subject, headers, maxsize, typeoverride, outfname)
  41. FILE *infile, *applefile, *descfile;
  42. char *fname, *subject, *headers;
  43. long maxsize;
  44. char *typeoverride, *outfname;
  45. {
  46.     char *type;
  47.     FILE *outfile;
  48.     char *cleanfname, *p;
  49.     char *digest, *appledigest;
  50.     long filesize, l, written;
  51.     int thispart, numparts = 1;
  52.     int wrotefiletype = 0;
  53.     char *multipartid, *msgid, *referenceid[NUMREFERENCES];
  54.     char buf[1024];
  55.     int i;
  56.  
  57.     /* Clean up fname for printing */
  58.     cleanfname = fname;
  59. #ifdef __riscos
  60.     /* This filename-cleaning knowledge will probably
  61.      * be moved to the os layer in a future version.
  62.      */
  63.     if (p = strrchr(cleanfname, '.')) cleanfname = p+1;
  64. #else
  65.     if (p = strrchr(cleanfname, '/')) cleanfname = p+1;
  66.     if (p = strrchr(cleanfname, '\\')) cleanfname = p+1;
  67. #endif
  68.     if (p = strrchr(cleanfname, ':')) cleanfname = p+1;
  69.  
  70.     /* Find file type */
  71.     if (typeoverride) {
  72.     type = typeoverride;
  73.     }
  74.     else {
  75.     type = magic_look(infile);
  76.     }
  77.  
  78.     /* Compute MD5 digests */
  79.     digest = md5digest(infile, &filesize);
  80.     if (applefile) {
  81.     appledigest = md5digest(applefile, &l);
  82.     filesize += l;
  83.     }
  84.  
  85.     /* See if we have to do multipart */
  86.     if (maxsize) {
  87.     filesize = (filesize / 54) * 73; /* Allow for base64 expansion */
  88.  
  89.     /* Add in size of desc file */
  90.     if (descfile) {
  91.         free(md5digest(descfile, &l));     /* XXX */
  92.         filesize += l;
  93.     }
  94.  
  95.     numparts = (filesize-1000)/maxsize + 1;
  96.     if (numparts < 1) numparts = 1;
  97.     }
  98.  
  99.     multipartid = os_genid();
  100.     for (i=0; i<NUMREFERENCES; i++) {
  101.     referenceid[i] = 0;
  102.     }
  103.  
  104.     for (thispart=1; thispart <= numparts; thispart++) {
  105.     written = 0;
  106.  
  107.     /* Open output file */
  108.     if (numparts == 1) {
  109.         outfile = fopen(outfname, "w");
  110.         if (!outfile) os_perror(outfname);
  111.     }
  112.     else {
  113. #ifdef __riscos
  114.         /* Arrgh, riscos uses '.' as directory separator */
  115.         sprintf(buf, "%s/%02d", outfname, thispart);
  116. #else
  117.         sprintf(buf, "%s.%02d", outfname, thispart);
  118. #endif
  119.         outfile = fopen(buf, "w");
  120.         if (!outfile) os_perror(buf);
  121.     }
  122.     if (!outfile) return 1;
  123.     
  124.     msgid = os_genid();
  125.     fprintf(outfile, "Message-ID: <%s>\n", msgid);
  126.     fprintf(outfile, "Mime-Version: 1.0\n");
  127.     if (headers) fputs(headers, outfile);
  128.     if (numparts > 1) {
  129.         fprintf(outfile, "Subject: %s (%02d/%02d)\n", subject,
  130.             thispart, numparts);
  131.         if (thispart == 1) {
  132.         referenceid[0] = msgid;
  133.         }
  134.         else {
  135.         /* Put out References: header pointing to previous parts */
  136.         fprintf(outfile, "References: <%s>\n", referenceid[0]);
  137.         for (i=1; i<NUMREFERENCES; i++) {
  138.             if (referenceid[i]) fprintf(outfile, "\t <%s>\n",
  139.                         referenceid[i]);
  140.         }
  141.         for (i=2; i<NUMREFERENCES; i++) {
  142.             referenceid[i-1] = referenceid[i];
  143.         }
  144.         referenceid[NUMREFERENCES-1] = msgid;
  145.         }
  146.         fprintf(outfile,
  147.             "Content-Type: message/partial; number=%d; total=%d;\n",
  148.             thispart, numparts);
  149.         fprintf(outfile, "\t id=\"%s\"\n", multipartid);
  150.         fprintf(outfile, "\n");
  151.     }
  152.  
  153.     if (thispart == 1) {
  154.         if (numparts > 1) {
  155.         fprintf(outfile, "Message-ID: <%s>\n", multipartid);
  156.         fprintf(outfile, "MIME-Version: 1.0\n");
  157.         }
  158.         fprintf(outfile, "Subject: %s\n", subject);
  159.         fprintf(outfile,
  160.             "Content-Type: multipart/mixed; boundary=\"-\"\n");
  161.         fprintf(outfile,
  162. "\nThis is a MIME encoded message.  Decode it with \"munpack\"\n");
  163.         fprintf(outfile,
  164. "or any other MIME reading software.  Mpack/munpack is available\n");
  165.         fprintf(outfile,
  166. "via anonymous FTP in ftp.andrew.cmu.edu:pub/mpack/\n");
  167.         written = 300;
  168.  
  169.         /* Spit out description section */
  170.         if (descfile) {
  171.         fprintf(outfile, "---\n\n");
  172.         while (fgets(buf, sizeof(buf), descfile)) {
  173.             /* Strip multiple leading dashes as they may become MIME
  174.              * boundaries
  175.              */
  176.             p = buf;
  177.             if (*p == '-') {
  178.             while (p[1] == '-') p++;
  179.             }
  180.  
  181.             fputs(p, outfile);
  182.             written += strlen(p);
  183.         }
  184.         fprintf(outfile, "\n");
  185.         }
  186.     
  187.         fprintf(outfile, "---\n");
  188.  
  189.         if (applefile) {
  190.         fprintf(outfile,
  191.     "Content-Type: multipart/appledouble; boundary=\"=\"; name=\"%s\"\n",
  192.             cleanfname);
  193.         fprintf(outfile,
  194.             "Content-Disposition: inline; filename=\"%s\"\n",
  195.             cleanfname);
  196.         fprintf(outfile, "\n\n--=\n");
  197.         fprintf(outfile, "Content-Type: application/applefile\n");
  198.         fprintf(outfile, "Content-Transfer-Encoding: base64\n");
  199.         fprintf(outfile, "Content-MD5: %s\n\n", appledigest);
  200.         free(appledigest);
  201.         written += 100;
  202.         }
  203.  
  204.     }
  205.  
  206.     if (applefile && !feof(applefile)) {
  207.         if (written == maxsize) written--; /* avoid a nasty fencepost error */
  208.         written += to64(applefile, outfile,
  209.                 (thispart == numparts) ? 0 : (maxsize-written));
  210.  
  211.         if (!feof(applefile)) {
  212.         fclose(outfile);
  213.         continue;
  214.         }
  215.  
  216.         fprintf(outfile, "\n--=\n");
  217.     }
  218.  
  219.  
  220.     if (!wrotefiletype++) {
  221.         fprintf(outfile, "Content-Type: %s; name=\"%s\"\n", type,
  222.             cleanfname);
  223.         fprintf(outfile, "Content-Transfer-Encoding: base64\n");
  224.         fprintf(outfile, "Content-Disposition: inline; filename=\"%s\"\n",
  225.             cleanfname);
  226.         fprintf(outfile, "Content-MD5: %s\n\n", digest);
  227.         free(digest);
  228.         written += 80;
  229.     }
  230.  
  231.     if (written == maxsize) written--; /* avoid a nasty fencepost error */
  232.  
  233.     written += to64(infile, outfile,
  234.             (thispart == numparts) ? 0 : (maxsize-written));
  235.  
  236.     if (thispart == numparts) {
  237.         if (applefile) fprintf(outfile, "\n--=--\n");
  238.         fprintf(outfile, "\n-----\n");
  239.     }
  240.     
  241.     fclose(outfile);    
  242.     }
  243.  
  244.     return 0;
  245. }
  246.