home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / mpack-1.3-amiga_src.lha / encode.c < prev    next >
C/C++ Source or Header  |  1994-05-10  |  7KB  |  229 lines

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