示例#1
0
文件: mime.c 项目: frese/mbuni
/*
 * Read some headers, i.e., until the first empty line (read and discard
 * the empty line as well). Return -1 for error, 0 for all headers read.
 */
static int read_mime_headers(ParseContext *context, List *headers)
{
    Octstr *line, *prev;

    if (gwlist_len(headers) == 0)
        prev = NULL;
    else
        prev = gwlist_get(headers, gwlist_len(headers) - 1);

    for (;;) {
        line = parse_get_line(context);
        if (line == NULL) {
	    	return -1;
        }
        if (octstr_len(line) == 0) {
            octstr_destroy(line);
            break;
        }
        if (isspace(octstr_get_char(line, 0)) && prev != NULL) {
            octstr_append(prev, line);
            octstr_destroy(line);
        } else {
            gwlist_append(headers, line);
            prev = line;
        }
    }

    return 0;
}
示例#2
0
文件: mms_queue.c 项目: frese/mbuni
/* 
 * Attempt to read an envelope from queue file:
 * - opens and locks the file. 
 * - if the lock succeeds, check that file hasn't changed since opening. If it has
 *   return NULL (i.e. file is being processed elsewhere -- race condition), otherwise read it.
 * - If should block is 1, then does a potentially blocking attempt to lock the file.
 */
static MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldblock)
{
     Octstr *fname;
     int fd;
     Octstr *qdata, *s;
     ParseContext *p;
     MmsEnvelope *e;
     int okfile = 0;
     char subdir[64];
     char realqf[QFNAMEMAX];
     char xqf[QFNAMEMAX+64];
     struct qfile_t *qfs;
     
     get_subdir(qf, subdir, realqf); /* break it down... */

     fname = octstr_format( "%.128s/%s%s", mms_queuedir, subdir, realqf);
     
     strncpy(xqf, octstr_get_cstr(fname), sizeof xqf);
     
#ifdef SunOS
     if ((fd = open(octstr_get_cstr(fname), O_RDWR)) < 0) {
#else
     if ((fd = open(octstr_get_cstr(fname), O_RDONLY)) < 0) {
#endif
		debug("",0,"mms_queue_readenvelope: could not open file %s", octstr_get_cstr(fname));
	  octstr_destroy(fname);
	  return NULL;
     } else if (mm_lockfile(fd, octstr_get_cstr(fname), shouldblock) != 0) {
		debug("",0,"mms_queue_readenvelope: could not lock file %s", octstr_get_cstr(fname));
	  unlock_and_close(fd);
	  octstr_destroy(fname);
	  return NULL;
     }

	debug("",0,"locked and opened file: %s", octstr_get_cstr(fname));
     
     e = mms_queue_create_envelope(NULL, NULL, 
				   NULL, 
				   NULL, NULL, 
				   0, 0, 
				   NULL, 
				   NULL, NULL, 
				   NULL, NULL, 
				   NULL,
				   0, 
				   NULL, 
				   NULL,
				   qf,
				   NULL,
				   sizeof (struct qfile_t), NULL);
     qfs = e->qfs_data;
     
     qfs->fd = fd;
     strncpy(qfs->name, realqf, sizeof qfs->name);
     strncpy(qfs->subdir, subdir, sizeof qfs->subdir);
     strncpy(qfs->dir, mms_queuedir, sizeof qfs->dir);

     qdata = octstr_read_file(octstr_get_cstr(fname));
     octstr_destroy(fname);
     if (qdata == NULL)
	  qdata = octstr_imm("");
     p = parse_context_create(qdata);
     
     for (s = parse_get_line(p); s;  
	  s = parse_get_line(p)) {
	  char *line = octstr_get_cstr(s);
	  int ch = line[0];
	  char *res = line + 1;
	  char *ptmp;

	  switch (ch) {
	       Octstr *t;
	       MmsEnvelopeTo *to;
	  case 'T':
	       t = octstr_create(res);
	       e->msgtype = mms_string_to_message_type(t);
	       octstr_destroy(t);
	       if (e->msgtype < 0) {
		    e->msgtype = 0;
		    error(0, "mms_queueread: Unknown MMS message type (%s) in file %s, skipped!\n",
			  res, xqf);
	       }
	       break;
	  case 'I':
	       e->msgId = octstr_create(res);	       
	       break;
	  case 'i':
	       strncpy(e->src_interface, res, sizeof e->src_interface);
	       break;
	  case 'F':
	       e->from = octstr_create(res);
	       if (mms_validate_address(e->from) != 0) {
		    warning(0, "mms_queueread: Mal-formed address [%s] in file %s! "
			    "Attempting fixup.", res, xqf);
		    _mms_fixup_address(&e->from, NULL, NULL, 1);
	       }
	       break;
	  case 'R':

	       t = octstr_create(res);
	       if (mms_validate_address(t) != 0) {
		    warning(0, "mms_queueread: Mal-formed address [%s] in file %s! " 
			    "Attempting fixup.", res, xqf);
		    _mms_fixup_address(&t, NULL, NULL, 1);
	       }
	       to = gw_malloc(sizeof *to);
	       to->rcpt = t;
	       to->process = 1;	       
	       gwlist_append(e->to, to);
	       break;
	  case 'C':
	       e->created = atol(res);
	       break;
	  case 'L':
	       e->lasttry = atol(res);
	       break;
	  case 'D':
	       e->sendt = atol(res);
	       break;
	  case 'X':
	       e->expiryt = atol(res);
	       break;
	  case 'N':
	       e->attempts = atol(res);
	       break;
	  case 'P':
	       e->fromproxy = octstr_create(res);
	       break;
	  case 'M':
	       e->mdata = octstr_create(res);
	       break;
	  case 'p':
	       e->viaproxy = octstr_create(res);
	       break;
	  case 'S':
	       e->msize = atol(res);
	    break;
	  case 's':
	       e->subject = octstr_create(res);
	       break;	
	  case 't':
	       e->token = octstr_create(res);
	       break;
	  case 'f':
	       e->lastaccess = atol(res);
	       break;
	  case 'b':
	       e->bill.billed = 1;
	       e->bill.amt = atof(res);
	    break;
	  case 'r':
	       e->dlr = 1;
	       break;
	  case 'V':
	       e->vaspid = octstr_create(res);
	       break;
	  case 'v':
	       e->vasid = octstr_create(res);
	       break;

	  case 'U':
	       e->url1 = octstr_create(res);
	       break;

	  case 'u':
	       e->url2 = octstr_create(res);
	       break;
	  case 'H':
	       if (e->hdrs == NULL)
		    e->hdrs = http_create_empty_headers();
	       if ((ptmp = index(res, ':')) == NULL)
		    error(0, "Incorrectly formatted line %s in queue file %s!",
			  line, xqf);
	       else {
		    char *value = ptmp + 1;
		    char hname[512];
		    int xlen = (ptmp - res < sizeof hname) ? ptmp - res : -1 + sizeof hname;
		    strncpy(hname, res, xlen);
		    hname[xlen] = 0; /* terminate it. */
		    http_header_add(e->hdrs, hname, value);
	       }
	       break;
	  case '.':
	       okfile = 1;
	       break;
	  default:
	       error(0, "Unknown QF header %c in file %s!", ch, xqf);
	       break;
	  }
	  octstr_destroy(s);
	  if (okfile) 
	       break; /* We are done. */
     }
     parse_context_destroy(p);
     octstr_destroy(qdata);

     /* We should properly validate the queue file here. */
     if (!okfile) {
	  free_envelope(e,0);
	  e = NULL;
	  error(0, "Corrupt queue control file: %s",  xqf);
     }
     return e;     
}

/* Updates envelope to queue file:
 * - opens temp file
 * - writes output to temp file, if not new else writes directly.
 * - renames temp file to queue file (if not new)
 * This function doesn't check that this envelope is useless (i.e. no recipients)
 * - If function returns -1, caller should check errno for error.
 */
static int writeenvelope(MmsEnvelope *e, int newenv)
{
     Octstr *tfname = NULL;
     char *s;
     char buf[512];
     int fd;
     int i, n;
     int res = 0;
     struct qfile_t *qfs = e ? e->qfs_data : NULL;
     
     gw_assert(e);
     
     if (newenv)
	  fd = qfs->fd;
     else {
	  tfname = octstr_format( 
	       "%s/%s%c%s.%d", qfs->dir, qfs->subdir,
	       MTF, qfs->name + 1, random());
	  fd = open(octstr_get_cstr(tfname),
		    O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	  if (fd < 0 ) {
	       error(0, "mms_queueadd: Failed to open temp file %s: error = %s\n",
		     octstr_get_cstr(tfname), strerror(errno));
	       res = -1;
	       goto done;
	  } else if (mm_lockfile(fd, octstr_get_cstr(tfname), 0) != 0) { /* Lock it. */
	       error(0, "mms_queueadd: Failed lock  temp file %s: error = %s\n", 
		     octstr_get_cstr(tfname), strerror(errno));
	       res = -1;	  
	       goto done;
	  }
     }
	  
     /* Write out. */

     s = (char *)mms_message_type_to_cstr(e->msgtype);
     if (!s) {
	  error(0, "mms_queuewrite: Unknown MMS message type %d! Skipped\n", e->msgtype);
	  s = "";
     }
     _putline(fd, "T", s);
     
     if (e->msgId) 
	  _putline(fd, "I", octstr_get_cstr(e->msgId));

     if (e->src_interface[0])
	  _putline(fd, "i", e->src_interface);
     
     if (e->from)
	  _putline(fd, "F", octstr_get_cstr(e->from));

     if (e->to)
	  n = gwlist_len(e->to);
     else
	  n = 0;

     for (i = 0; i < n; i++) {
	  MmsEnvelopeTo *to = gwlist_get(e->to, i);
	  
	  if (to->process)	       
	       _putline(fd, "R", octstr_get_cstr(to->rcpt));
     }

     /* Output headers if any. */
     n = (e->hdrs) ? gwlist_len(e->hdrs) : 0;
     for (i = 0; i < n; i++) {
	  Octstr *h = NULL, *v = NULL;

	  http_header_get(e->hdrs, i, &h, &v);
	  if (h && v) {
	       Octstr *x = octstr_format("%s:%s", octstr_get_cstr(h), 
					 octstr_get_cstr(v));
	       _putline(fd, "H", octstr_get_cstr(x));
	       octstr_destroy(x);	       
	  }
	  if (h) octstr_destroy(h);
	  if (v) octstr_destroy(v);

     }

     sprintf(buf, "%ld", e->created);
     _putline(fd, "C", buf);

     if (e->lasttry) {
	  sprintf(buf, "%ld", e->lasttry);
	  _putline(fd, "L", buf);
     }

     if (e->sendt) {
	  sprintf(buf, "%ld", e->sendt);
	  _putline(fd, "D", buf);
     }

     if (e->expiryt) {
	  sprintf(buf, "%ld", e->expiryt);
	  _putline(fd, "X", buf);
     }

     if (e->attempts) {
	  sprintf(buf, "%ld", e->attempts);
	  _putline(fd, "N", buf);
     }

     if (e->lastaccess) {
	  sprintf(buf, "%ld", e->lastaccess);
	  _putline(fd, "f", buf);
     }

     sprintf(buf, "%ld", e->msize);
     _putline(fd, "S", buf);


     if (e->fromproxy) 
	  _putline(fd, "P", octstr_get_cstr(e->fromproxy));


     if (e->mdata) 
	  _putline(fd, "M", octstr_get_cstr(e->mdata));

     if (e->subject)
	  _putline(fd, "s", octstr_get_cstr(e->subject));
     

     if (e->viaproxy) 
	  _putline(fd, "p", octstr_get_cstr(e->viaproxy));

     if (e->token) 
	  _putline(fd, "t", octstr_get_cstr(e->token));
     

      if (e->vaspid) 
	  _putline(fd, "V", octstr_get_cstr(e->vaspid));
     
      if (e->vasid) 
	  _putline(fd, "v", octstr_get_cstr(e->vasid));
     
      if (e->url1) 
	  _putline(fd, "U", octstr_get_cstr(e->url1));

      if (e->url2) 
	  _putline(fd, "u", octstr_get_cstr(e->url2));

     if (e->dlr) 
	  _putline(fd, "r", "Yes");

     if (e->bill.billed) {
	  sprintf(buf, "%.3f", e->bill.amt);
	  _putline(fd,"b", buf);
     }

     _putline(fd, "", ".");

     fsync(fd); /* Sync data. */
     
     if (!newenv) { /* An update */
	  Octstr *qfname;
	 
	  qfname = octstr_format("%s/%s%s", qfs->dir, qfs->subdir, qfs->name);
	
	  if (rename(octstr_get_cstr(tfname), octstr_get_cstr(qfname)) < 0) {
	       error(0, "mms_queuewrite: Failed to rename %s to %s: error = %s\n", 
		     octstr_get_cstr(qfname), octstr_get_cstr(tfname), strerror(errno));

	       unlock_and_close(fd); /* Close new one, keep old one. */
		   res = -1;
	  } else { /* On success, new descriptor replaces old one and we close old one. */
	       unlock_and_close(qfs->fd);
	       qfs->fd = fd;
	  }
	  octstr_destroy(qfname);
     }

 done:
     octstr_destroy(tfname);
     return res;
}
示例#3
0
文件: mime.c 项目: frese/mbuni
/*
 * This routine is used for mime_[http|octstr]_to_entity() in order to
 * reduce code duplication. Basically the only difference is how the headers
 * are parsed or passed to the resulting MIMEEntity representation.
 */
static MIMEEntity *mime_something_to_entity(Octstr *mime, List *headers)
{
    MIMEEntity *e;
    ParseContext *context;
    Octstr *value, *boundary, *start;
    int len = 0;

	debug("mime.parse",0,"mime_something_to_entity");
	octstr_dump(mime,0);

    gw_assert(mime != NULL);

    value = boundary = start = NULL;
    context = parse_context_create(mime);
    e = mime_entity_create();
    
    /* parse the headers up to the body. If we have headers already passed 
     * from our caller, then duplicate them and continue */
    if (headers != NULL) {
        /* we have some headers to duplicate, first ensure we destroy
         * the list from the previous creation inside mime_entity_create() */
        http_destroy_headers(e->headers);
        e->headers = http_header_duplicate(headers);
    } else {
        /* parse the headers out of the mime block */
        if ((read_mime_headers(context, e->headers) != 0) || e->headers == NULL) {
            debug("mime.parse",0,"Failed to read MIME headers in Octstr block:");
            octstr_dump(mime, 0);
            mime_entity_destroy(e);
            parse_context_destroy(context);
            return NULL;
        }
    }

    /* 
     * Now check if the body is a multipart. This is indicated by an 'boundary'
     * parameter in the 'Content-Type' value. If yes, call ourself for the 
     * multipart entities after parsing them.
     */
    value = http_header_value(e->headers, octstr_imm("Content-Type"));
	debug("mime.parse",0,"value: %s", octstr_get_cstr(value));
    boundary = http_get_header_parameter(value, octstr_imm("boundary"));
	debug("mime.parse",0,"boundary: %s", octstr_get_cstr(boundary));
    start = get_start_param(value);

    /* Beware that we need *unquoted* strings to compare against in the
     * following parsing sections. */
    if (boundary && (len = octstr_len(boundary)) > 0 &&
        octstr_get_char(boundary, 0) == '"' && octstr_get_char(boundary, len-1) == '"') {
        octstr_delete(boundary, 0, 1);
        octstr_delete(boundary, len-2, 1);
    }

	debug("mime.parse",0, "Boundrary is %s", octstr_get_cstr(boundary));

    if (boundary != NULL) {
        /* we have a multipart block as body, parse the boundary blocks */
        Octstr *entity, *seperator, *os;
        
        /* loop by all boundary blocks we have in the body */
        seperator = octstr_create("--");
        octstr_append(seperator, boundary);
        while ((entity = parse_get_seperated_block(context, seperator)) != NULL) {
            MIMEEntity *m;
            int del2 = 0;
	    
            /* we have still linefeeds at the beginning and end that we 
             * need to remove, these are from the separator. 
             * We check if it is LF only or CRLF! */
            del2 = (octstr_get_char(entity, 0) == '\r');
            if (del2) 
                octstr_delete(entity, 0, 2);	      
            else
                octstr_delete(entity, 0, 1);

            /* we assume the same mechanism applies to beginning and end -- 
             * seems reasonable! */
            if (del2)
                octstr_delete(entity, octstr_len(entity) - 2, 2);
            else
                octstr_delete(entity, octstr_len(entity) - 1, 1);

            debug("mime.parse",0,"MIME multipart: Parsing entity:");
            octstr_dump(entity, 0);

            /* call ourself for this MIME entity and inject to list */
            if ((m = mime_octstr_to_entity(entity))) {
                gwlist_append(e->multiparts, m);
		 
                /* check if this entity is our start entity (in terms of related)
                 * and set our start pointer to it */
                if (cid_matches(m->headers, start)) {
                    /* set only if none has been set before */
                    e->start = (e->start == NULL) ? m : e->start;
                }
            }

            octstr_destroy(entity);
        }
        /* ok, we parsed all blocks, we expect to see now the end boundary */
        octstr_append_cstr(seperator, "--");
        os = parse_get_line(context);
        if (os != NULL && octstr_compare(os, seperator) != 0) {
            debug("mime.parse",0,"Failed to see end boundary, parsed line is '%s'.",
                  octstr_get_cstr(os));
        }

        octstr_destroy(seperator);
        octstr_destroy(os);
    }
    else {

        /* we don't have boundaries, so this is no multipart block, 
         * pass the body to the MIME entity. */
        e->body = parse_get_rest(context);

    }

    parse_context_destroy(context);
    octstr_destroy(value);
    octstr_destroy(boundary);
    octstr_destroy(start);

    return e;
}
示例#4
0
int parse_input(const char *file_in, int set_used)
{
  FILE *f;
  char *s;
  int c, length = 0;
  parse_result pc;

  if(strcmp(file_in, "-") == 0)
    f = stdin;
  else
    f = fopen(file_in, "r");
  
  if(!f)
    return -1; /* error opening file */
  
  /* we now read in the file and parse */
  /* note: 40 is just a starter length, it is not a maximum */
  length = 40;
  s = (char *)malloc(length + 1);
  do{
    c = parse_get_line(f, &s, &length);
    if(*s){
      if(strncmp("include ", s, 8) == 0 ){ /* include another file */
	/* wipe out leading 'include' with blanks */
	strncpy(s, "       ", 7);
	str_trim(s);
	if(!disable_write)
	  fprintf(fout, "# including file '%s'\n", s);
	c = parse_input(s, 0);
	if(c != 0) {
	  fprintf(stderr, "Parser error: cannot open included file '%s'.\n", s);
	  exit(1);
	}
      } else if(*s == '%'){ /* we have a block */
	*s = ' ';
	str_trim(s);
	if(getsym(s) != NULL){ /* error */
	  fprintf(stderr, "Parser warning: %s \"%s\" %s.\n", "Block", s, "already defined");
	  do{ /* skip block */
	    c = parse_get_line(f, &s, &length);
	  }while(c != EOF && *s != '%');
	}else{ /* parse block */
	  symrec *rec;
	  rec = putsym(s, S_BLOCK);
	  rec->value.block = (sym_block *)malloc(sizeof(sym_block));
	  rec->value.block->n = 0;
	  rec->value.block->lines = NULL;
	  do{
	    c = parse_get_line(f, &s, &length);
	    if(*s && *s != '%'){
	      char *s1, *tok;
	      int l, col;
	      
	      l = rec->value.block->n;
	      rec->value.block->n++;
	      rec->value.block->lines = (sym_block_line *)
		realloc((void *)rec->value.block->lines, sizeof(sym_block_line)*(l+1));
	      rec->value.block->lines[l].n = 0;
	      rec->value.block->lines[l].fields = NULL;
	      
	      /* parse columns */
	      for(s1 = s; (tok = strtok(s1, "|\t")) != NULL; s1 = NULL){
		char *tok2 = strdup(tok);
		str_trim(tok2);
		
		col = rec->value.block->lines[l].n;
		rec->value.block->lines[l].n++;
		rec->value.block->lines[l].fields = (char **)
		  realloc((void *)rec->value.block->lines[l].fields, sizeof(char *)*(col+1));
		rec->value.block->lines[l].fields[col] = tok2;
	      }
	    }
	  }while(c != EOF && *s != '%');
	}
      }else{ /* we can parse it np */
	parse_exp(s, &pc);
      }
    }
  }while(c != EOF);
  
  free(s);
  if(f != stdin)
    fclose(f);

  if(set_used == 1)
    sym_mark_table_used();

  return 0;
}
示例#5
0
int parse_input(char *file_in)
{
  FILE *f;
  char *s;
  int c, length = 0;
  
  if(strcmp(file_in, "-") == 0)
    f = stdin;
  else
    f = fopen(file_in, "r");
  
  if(!f)
    return -1; /* error opening file */
  
  /* we now read in the file and parse */
  length = 40;
  s = (char *)malloc(length + 1);
  do{
    c = parse_get_line(f, &s, &length);
    if(*s){
      if(*s == '%'){ /* we have a block */
	*s = ' ';
	str_trim(s);
	if(getsym(s) != NULL){ /* error */
	  fprintf(stderr, "%s \"%s\" %s", "Block", s, "already defined");
	  do{ /* skip block */
	    c = parse_get_line(f, &s, &length);
	  }while(c != EOF && *s != '%');
	}else{ /* parse block */
	  symrec *rec;
	  rec = putsym(s, S_BLOCK);
	  rec->value.block = (sym_block *)malloc(sizeof(sym_block));
	  rec->value.block->n = 0;
	  rec->value.block->lines = NULL;
	  do{
	    c = parse_get_line(f, &s, &length);
	    if(*s && *s != '%'){
	      char *s1, *tok;
	      int l, col;
	      
	      l = rec->value.block->n;
	      rec->value.block->n++;
	      rec->value.block->lines = (sym_block_line *)
		realloc((void *)rec->value.block->lines, sizeof(sym_block_line)*(l+1));
	      rec->value.block->lines[l].n = 0;
	      rec->value.block->lines[l].fields = NULL;
	      
	      /* parse columns */
	      for(s1 = s; (tok = strtok(s1, "|\t")) != NULL; s1 = NULL){
		char *tok2 = strdup(tok);
		str_trim(tok2);
		
		col = rec->value.block->lines[l].n;
		rec->value.block->lines[l].n++;
		rec->value.block->lines[l].fields = (char **)
		  realloc((void *)rec->value.block->lines[l].fields, sizeof(char *)*(col+1));
		rec->value.block->lines[l].fields[col] = tok2;
	      }
	    }
	  }while(c != EOF && *s != '%');
	}
      }else{ /* we can parse it np */
	parse_result c;
	parse_exp(s, &c);
      }
    }
  }while(c != EOF);
  
  free(s);
  if(f != stdin)
    fclose(f);
  
#define OCT_ENV_HEADER "OCT_"

  /*now read options from environment variables (by X) */

  if( getenv("OCT_PARSE_ENV")!=NULL ) {
    
    /* environ is an array of C strings with all the environment
       variables, the format of the string is NAME=VALUE, which
       is directly recognized by parse_exp */
    
    char **env = environ;    
    while(*env) {
      /* Only consider variables that begin with OCT_ */
      if( strncmp(OCT_ENV_HEADER, *env, strlen(OCT_ENV_HEADER)) == 0 ){	
	parse_result c;
	parse_exp( (*env) + strlen(OCT_ENV_HEADER), &c);
      }
      
      env++;
    }
  }
  
  sym_clear_reserved();

  return 0;
}