Back to home page

MITgcm

 
 

    


File indexing completed on 2018-03-02 18:44:59 UTC

view on githubraw file Latest commit e768bd12 on 2008-02-26 17:05:00 UTC
ec6cf3b09d Ed H*0001 /*
                0002  * Read MIME body-part, stopping on boundaries.
                0003  */
                0004 /* (C) Copyright 1994 by Carnegie Mellon University
                0005  * All Rights Reserved.
                0006  *
                0007  * Permission to use, copy, modify, distribute, and sell this software
                0008  * and its documentation for any purpose is hereby granted without
                0009  * fee, provided that the above copyright notice appear in all copies
                0010  * and that both that copyright notice and this permission notice
                0011  * appear in supporting documentation, and that the name of Carnegie
                0012  * Mellon University not be used in advertising or publicity
                0013  * pertaining to distribution of the software without specific,
                0014  * written prior permission.  Carnegie Mellon University makes no
                0015  * representations about the suitability of this software for any
                0016  * purpose.  It is provided "as is" without express or implied
                0017  * warranty.
                0018  *
                0019  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0020  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0021  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0022  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0023  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0024  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0025  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                0026  * SOFTWARE.
                0027  */
                0028 
                0029 #include <stdio.h>
e768bd1221 Jean*0030 #include <stdlib.h>
ec6cf3b09d Ed H*0031 #include <string.h>
                0032 
                0033 #include "part.h"
                0034 #include "xmalloc.h"
                0035 
                0036 #define BUFSIZE 1024 /* must be > PART_MAX_BOUNDARY_LEN */
                0037 #define GROWBOUNDARY 20
                0038 
                0039 static int pendingboundary(struct part *part);
                0040 
                0041 /*
                0042  * Create, initialize, and return a new struct part pointer
                0043  * for the input file 'infile'.
                0044  */
                0045 struct part *part_init(FILE *infile)
                0046 {
                0047     static struct part zeropart;
                0048     struct part *newpart;
                0049 
                0050     newpart = (struct part *)xmalloc(sizeof(struct part));
                0051     *newpart = zeropart;
                0052     newpart->infile = infile;
                0053     newpart->buf = (unsigned char *)xmalloc(BUFSIZE);
                0054     newpart->buf_alloc = BUFSIZE;
                0055 
                0056     return newpart;
                0057 }
                0058 
                0059 /*
                0060  * Close and free 'part'.
                0061  */
e768bd1221 Jean*0062 void part_close(struct part *part)
ec6cf3b09d Ed H*0063 {
                0064     fclose(part->infile);
                0065     if (part->buf) free(part->buf);
                0066     if (part->boundary) free(part->boundary);
                0067 }
                0068 
                0069 /*
                0070  * Return the multipart depth of 'part'.  Top-level is '0'.
                0071  */
                0072 int
                0073 part_depth(struct part *part)
                0074 {
                0075     return part->boundary_num;
                0076 }
                0077 
                0078 /*
                0079  * Add to 'part' the multipart boundary 'boundary'.
                0080  */
e768bd1221 Jean*0081 void part_addboundary(struct part *part, char *boundary)
ec6cf3b09d Ed H*0082 {
                0083     /* Grow boundary array if necessary */
                0084     if (part->boundary_num == part->boundary_alloc) {
                0085     part->boundary_alloc += GROWBOUNDARY;
                0086     part->boundary = (char (*)[PART_MAX_BOUNDARY_LEN+1])
                0087         xrealloc((char *)part->boundary,
                0088              part->boundary_alloc * (PART_MAX_BOUNDARY_LEN+1));
                0089     part->boundary_length = (int *)
                0090         xrealloc((char *)part->boundary_length,
                0091              part->boundary_alloc * sizeof(int));
                0092     }
                0093 
                0094     strncpy(part->boundary[part->boundary_num], boundary,
                0095         PART_MAX_BOUNDARY_LEN);
                0096     part->boundary[part->boundary_num][PART_MAX_BOUNDARY_LEN] = '\0';
                0097     part->boundary_length[part->boundary_num] =
                0098     strlen(part->boundary[part->boundary_num]);
                0099     part->boundary_num++;
                0100     if (part->boundary_seen+1 == part->boundary_num) {
                0101     part->boundary_seen++;
                0102     }
                0103 }
                0104 
                0105 /*
                0106  * Private function that is only called from the part_getc() macro.
                0107  *
                0108  * Fills the input buffer for 'part' if necessary.  Returns the next
                0109  * input character or EOF if at a boundary or end of file.
                0110  */
                0111 int
                0112 part_fill(struct part *part)
                0113 {
                0114     /* part_getc() decremented this before calling us, put it back */
                0115     part->cnt++;
                0116 
                0117     /* Return EOF if we saw a boundary */
                0118     if (part->boundary_seen < part->boundary_num) return EOF;
                0119 
                0120     /* Fill buffer if it is empty */
                0121     if (part->cnt == 0) {
                0122     part->ptr = part->buf;
                0123     part->cnt = fread(part->buf, 1, part->buf_alloc, part->infile);
                0124     if (part->cnt == 0) {
                0125         part->boundary_seen = 0;
                0126         return EOF;
                0127     }
                0128     }
                0129 
                0130     /* If there is a newline, see if it is followed by a boundary */
                0131     if (part->ptr[0] == '\n' && pendingboundary(part)) {
                0132     return EOF;
                0133     }
                0134 
                0135     part->cnt--;
                0136     return *part->ptr++;
                0137 }
                0138 
                0139 /*
                0140  * Read a line into the array 's', of size 'n', from 'part'.
                0141  * Reads until 'n'-1 characters are read, a newline is read, or
                0142  * an EOF is encountered.  The array is then nul-terminated and returned.
                0143  * If the first character read is an EOF, then a null pointer is instead
                0144  * returned.
                0145  */
                0146 char *
                0147 part_gets(char *s, int n, struct part *part)
                0148 {
                0149     int c;
                0150     char *p = s;
                0151     
                0152     if (n == 0) return 0;
                0153     n--;
                0154     while (n-- && (c = part_getc(part)) != EOF) {
                0155     *p++ = c;
                0156     if (c == '\n') break;
                0157     }
                0158     if (p == s) return 0;
                0159     *p++ = '\0';
                0160     return s;
                0161 }
                0162 
                0163 /*
                0164  * Push back the string 's' into the input buffer of 'part'.
                0165  * Leaves room in the input buffer to push back an additional single
                0166  * character using the prot_ungetc() macro.
                0167  */
e768bd1221 Jean*0168 void part_ungets(char *s, struct part *part)
ec6cf3b09d Ed H*0169 {
                0170     int len = strlen(s);
                0171     int i;
                0172 
                0173     /* Grow buffer if necessary */
                0174     if (part->cnt + len + 1 > part->buf_alloc) {
                0175     i = part->ptr - part->buf;
                0176     part->buf_alloc = part->cnt + len + 1;
                0177     part->buf = (unsigned char *)
                0178         xrealloc((char *)part->buf, part->buf_alloc);
                0179     part->ptr = part->buf + i;
                0180     }
                0181 
                0182     /* Move current data down to make room for new data if necessary */
                0183     if (len + 1 > part->ptr - part->buf) {
                0184     for (i = part->cnt-1; i >= 0; i--) {
                0185         part->buf[len+1+i] = part->ptr[i];
                0186     }
                0187     part->ptr = part->buf + len + 1;
                0188     }
                0189 
                0190     /* Copy in the new data */
                0191     part->ptr -= len;
                0192     part->cnt += len;
                0193     for (i = 0; i < len; i++) {
                0194     part->ptr[i] = s[i];
                0195     }
                0196 }
                0197 
                0198 /*
                0199  * Reset the saw-boundary state of 'part' and set up to read next
                0200  * body-part Returns nonzero iff the pending boundary was a final
                0201  * boundary of the current multipart.
                0202  */
                0203 int
                0204 part_readboundary(struct part *part)
                0205 {
                0206     int c;
                0207     int sawfinal = 0;
                0208 
                0209     if (part->boundary_seen < part->boundary_num-1) {
                0210     /* We saw an enclosing boundary.  Signal end of multipart, but
                0211      * don't skip over the boundary.
                0212      */
                0213     part->boundary_num--;
                0214     return 1;
                0215     }
                0216 
                0217     /* Deal with EOF on input stream */
                0218     if (part->cnt == 0) return 1;
                0219 
                0220     /* Skip over delimiter, reset the "saw boundary" state */
                0221     part->ptr += part->boundary_length[part->boundary_seen] + 3;
                0222     part->cnt -= part->boundary_length[part->boundary_seen] + 3;
                0223     part->boundary_seen = part->boundary_num;
                0224     
                0225     /* Check for two dashes, which indicate a final delimiter */
                0226     c = part_getc(part);
                0227     if (c == '-') {
                0228     c = part_getc(part);
                0229     if (c == '-') {
                0230         sawfinal = 1;
                0231         part->boundary_num--;
                0232     }
                0233     }
                0234 
                0235     /* Eat rest of the boundary line */
                0236     while (c != '\n' && c != EOF) {
                0237     c = part_getc(part);
                0238     }
                0239     
                0240     return sawfinal;
                0241 }    
                0242 
                0243         
                0244 /*
                0245  * Return nonzero and set the saw-boundary state iff 'part'
                0246  * is positioned at a boundary.
                0247  */
                0248 static int
                0249 pendingboundary(struct part *part)
                0250 {
                0251     int bufleft;
                0252     int i;
                0253 
                0254     /* Fill buffer if we don't have enough to do our look ahead */
                0255     if (part->cnt < 3 ||
                0256     (part->cnt < PART_MAX_BOUNDARY_LEN+3 && part->ptr[1] == '-' &&
                0257      part->ptr[2] == '-')) {
                0258         
                0259     bufleft = part->buf_alloc - part->cnt - (part->ptr - part->buf);
                0260 
                0261     /* If not enough room, move everything to beginning of buffer */
                0262     if (part->ptr!=part->buf && bufleft + part->cnt < PART_MAX_BOUNDARY_LEN+3) {
                0263         for (i = 0; i < part->cnt; i++) {
                0264         part->buf[i] = part->ptr[i];
                0265         }
                0266         part->ptr = part->buf;
                0267         bufleft = part->buf_alloc - part->cnt;
                0268     }
                0269 
                0270     /* Read in more data */
                0271     part->cnt += fread(part->ptr+part->cnt, 1, bufleft, part->infile);
                0272     }
                0273 
                0274     /* If no "--", it's not a boundary */
                0275     if (part->cnt < 3 || part->ptr[1] != '-' || part->ptr[2] != '-') {
                0276     return 0;
                0277     }
                0278 
                0279     for (i = 0; i < part->boundary_num; i++) {
                0280     if (part->cnt - 3 >= part->boundary_length[i] &&
                0281         !strncmp((char *)part->ptr+3, part->boundary[i],
                0282              part->boundary_length[i])) {
                0283         break;
                0284     }
                0285     }
                0286 
                0287     if (i == part->boundary_num) return 0;
                0288 
                0289     /* Saw boundary, index 'i' */ 
                0290     part->boundary_seen = i;
                0291     return 1;
                0292 }