⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mms_mm7soap.c

📁 一个非常实用的手机mms开发包,能够满足大部分不同品牌和型号手机的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Mbuni - Open  Source MMS Gateway 
 * 
 * MM7/SOAP message encoder/decoder and helper functions
 * 
 * Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
 *
 * Paul Bagyenda <bagyenda@dsmagic.com>
 * 
 * This program is free software, distributed under the terms of
 * the GNU General Public License, with a few exceptions granted (see LICENSE)
 */

#include "mms_mm7soap.h"

/* function to traverse SOAP env:Body extracting useful headers. */

#define dfltstr(e) ((e) ? ((char *)(e)) : "")

#define content(n) ((n)->xmlChildrenNode ? dfltstr(((n)->xmlChildrenNode)->content) : dfltstr((n)->content))

struct MSoapMsg_t {
     List *envelope; /* of http headers. */
     MIMEEntity *msg; /* XXX - be sure to copy some headers to this from envelope before convert...*/
};

/* We expect ISO formatted time, or interval. */

static Octstr *parse_time(char *s)
{
     time_t t = time(NULL);
     Octstr *p = octstr_create(s);
     int i = 0, secs = 0;

     octstr_strip_blanks(p);

     if (s && s[0] != 'P') {
	  struct universaltime tt;
	  if (date_parse_iso(&tt, p) >= 0)
	       t = date_convert_universal(&tt);
	  goto done;
     } else 
	  i++;

     while (i < octstr_len(p)) {
	  long n = 0;
	  int ch;
	  
	  if (octstr_get_char(p, i) == 'T') {
	       secs = 1;
	       i++;
	  }
	  
	  i = octstr_parse_long(&n, p, i, 10);
	  
	  if (i < 0)
	       break;
	  ch = octstr_get_char(p, i);
	  i++;
	  switch(ch) {
	  case 'Y': /* years. approx to 365 1/4 days. */
	       t += (365.25*24*3600*n);
	       break;
	  case 'M': /* month or minutes. approx month = 30 days. */
	       if (secs)
		    t += n*60;
	       else 
		    t += 30*24*3600*n; 
	       break;
	  case 'D':
	       t += n*24*3600;
	       break;
	  case 'H': /* hours. */
	       t += n*3600;
	       break;
	  case 'S':
	       t += n;
	       break;
	  default:
	       break;
	  }
     }     

 done:
     octstr_destroy(p);
     return date_format_http(t);
}

static int parse_header(xmlNodePtr node, List *headers, int *sigparent)
{
     int skip = 0;
     int tag;
     char *hname;
     unsigned char *s = NULL;
     char *nvalue;
     Octstr *value = NULL, *tmp;
     
     
     if (!node || node->type != XML_ELEMENT_NODE)
	  return -1;

     /* look at each node in turn, extract meaning.
      * we ignore some tags: senderidentification, etc because we don't need them.
      * we are also not strict on syntax (when receiving): we will be on sending!
      */
     
     hname = (char *)node->name;
     nvalue = content(node);

     tmp = octstr_create(hname);
     tag = mms_string_to_mm7tag(tmp);
     octstr_destroy(tmp);

     switch(tag) {
     case MM7_TAG_CancelReq:
     case MM7_TAG_CancelRsp:
     case MM7_TAG_DeliverReq:
     case MM7_TAG_DeliverRsp:
     case MM7_TAG_DeliveryReportReq:
     case MM7_TAG_DeliveryReportRsp:
     case MM7_TAG_RSErrorRsp:
     case MM7_TAG_ReadReplyReq:
     case MM7_TAG_ReadReplyRsp:
     case MM7_TAG_ReplaceReq:
     case MM7_TAG_ReplaceRsp:
     case MM7_TAG_SubmitReq:
     case MM7_TAG_SubmitRsp:
     case MM7_TAG_VASPErrorRsp:
	  hname = "MessageType";
	  value = mms_mm7tag_to_string(tag);
	  break;
     case MM7_TAG_SenderIdentification:
     case MM7_TAG_Recipients:

       skip = 1;
       break;

     case MM7_TAG_Recipient:
	  *sigparent = MM7_TAG_To; /* make it a To field. */

	  break;
     case MM7_TAG_To:
     case MM7_TAG_Cc:
     case MM7_TAG_Bcc:
     case MM7_TAG_Sender:	  
     case MM7_TAG_SenderAddress:	  
	  skip = 1;
	  
	  *sigparent = tag; /* We wait for number and stuff below. */
	  break;
     case MM7_TAG_Content: 	  
       if ((s = xmlGetProp(node, (unsigned char *)"href")) != NULL) {
	    value = octstr_create((char *)s); 
	       xmlFree(s);
	  }
	  /* we keep 'cid:' bit.  ignore the bit about adaptation. */
	  break;
     case MM7_TAG_ShortCode:
     case MM7_TAG_Number: /* we will not normalise number here, that's for upper level. */
	  value = octstr_format("%s/TYPE=PLMN", nvalue);

	  /* -- fall through. -- */
     case MM7_TAG_RFC2822Address:
	  if (!value)
	       value = octstr_create(nvalue);
	  hname = (char *)mms_mm7tag_to_cstr(*sigparent); /* real tag is parent. */
	  
	  s = xmlGetProp(node, (unsigned char *)"displayOnly");
	  if (s && strcasecmp((char *)s, "true") == 0) /* a '-' indicates don't use this to send. */
	       octstr_insert(value, octstr_imm("- "), 0);
	  else 
	       octstr_insert(value, octstr_imm("+ "), 0);
	  if (s)
	       xmlFree(s);
 	  break;

     case MM7_TAG_EarliestDeliveryTime:
     case MM7_TAG_ExpiryDate:
     case MM7_TAG_TimeStamp:
     case MM7_TAG_Date:
	  value = parse_time(nvalue);
	  break;
	  
     case MM7_TAG_ReplyCharging:
	  value = octstr_create("Requested");
	  
	  if ((s = xmlGetProp(node, (unsigned char *)"replyChargingSize")) != NULL) {
	       http_header_add(headers, "replyChargingSize", (char *)s);
	       xmlFree(s);
	  }
	  if ((s = xmlGetProp(node, (unsigned char *)"replyDeadline")) != NULL) {
	       Octstr *t = parse_time((char *)s);	       
	       http_header_add(headers, "replyDeadline", octstr_get_cstr(t));
	       xmlFree(s);
	       octstr_destroy(t);
	  }
	  break;	  
     default:
	  break;
     }
     
     if (!value) 
	  value = octstr_create(nvalue);
     octstr_strip_blanks(value);

     if (!skip && tag >= 0 && hname != NULL) {
	  http_header_add(headers, hname, octstr_get_cstr(value));     
#if 1
	  info(0, "parse.soap, h=%s, v=%s!", hname, octstr_get_cstr(value));
#endif 
     }
     octstr_destroy(value);

     return 0;
}

static int parse_headers(xmlNodePtr start, List *h, int sigparent)
{
     xmlNodePtr x;

     for (x = start; x; x = x->next) 
	  if (x->type != XML_COMMENT_NODE) {
	       parse_header(x, h, &sigparent);	       
	       parse_headers(x->xmlChildrenNode, h, sigparent);
	  }
     return 0;
}

MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body)
{
     MIMEEntity  *mime = mime_http_to_entity(headers, body), *start = NULL;
     Octstr *xml = NULL, *cloc;
     xmlDocPtr doc;
     MIMEEntity *msg = NULL;
     List *h;
     int s = -1;     
     MSoapMsg_t *smsg = NULL;
     
     if (!mime) 
	  return NULL;
     /* Find the start element: 
      * - either the mime entity is multipart and has start param (or implicitly first element) ...
      * - or entity is not multipart, so body is xml
      */
          
     if ((start = mime_multipart_start_elem(mime)) != NULL) 
	  xml = mime_entity_body(start);
     else
	  xml = mime_entity_body(mime);
     
     if (!xml) 
	  goto done;
#if  1
     info(0, "XML sent is: %s!", octstr_get_cstr(xml));
#endif
     doc = xmlParseMemory(octstr_get_cstr(xml), octstr_len(xml));
     if (!doc || !doc->xmlChildrenNode)
	  goto done;
     
     h = http_create_empty_headers();

     parse_headers(doc->xmlChildrenNode, h, s);
     xmlFreeDoc(doc);
     
     if (!h)
	  goto done;
     
     cloc = http_header_value(h, octstr_imm("Content"));
     
     if (cloc) {
	  /* XXXX only support content that is inline.  easy to add external. */
	  MIMEEntity *c = NULL;
	  int i, n;
	  char *loc = octstr_get_cstr(cloc);
	  
	  if (octstr_case_search(cloc, octstr_imm("cid:"), 0) == 0) /* skip 'cid:' part. */
	       loc += 4; /* XXX This should always be there, but some MMC don't put it there. */
	  
	  for (i = 0, n = mime_entity_num_parts(mime); i<n; i++) {
	       MIMEEntity *x = mime_entity_get_part(mime, i);
	       List *headers = mime_entity_headers(x); 
	       Octstr *y = headers ? http_header_value(headers, octstr_imm("Content-ID")) : NULL;
	       char *cid = (y && octstr_get_char(y, 0) == '<') ? octstr_get_cstr(y) + 1 : (y ? octstr_get_cstr(y) : "");
	       int cid_len = (y && octstr_get_char(y, 0) == '<') ? octstr_len(y) - 2 : (y ? octstr_len(y) : 0);
	       
	       if (y && 
		   (strncmp(loc, cid, cid_len) == 0 ||
		    octstr_compare(y, cloc) == 0)) /* XXX seems wrong, but some MMC out there behave badly, so we support it */
		    c = mime_entity_duplicate(x);
	       
	       if (y) 
		    octstr_destroy(y);
	       http_destroy_headers(headers);
	       mime_entity_destroy(x);
	       if (c) 
		    break;
	  } 
	  if (c)
	       msg = c; /* this is already a copy. */	  
	  octstr_destroy(cloc);	  
     } else {
	       /* XXX Sigh! Broken MMC don't set this parameter. Lets try to be kind to them! */
	       int i, n = mime_entity_num_parts(mime);
	       int found = 0;
	       for (i = 0; !found && i < n; i++) {
		    MIMEEntity *x = mime_entity_get_part(mime,i);
		    List *hx = NULL;
		    Octstr *xctype = NULL, *xparams = NULL;
		    if (!x)
			 goto loop;
		    hx = mime_entity_headers(x);
		    get_content_type(hx, &xctype, &xparams);
		    
		    if (xctype && octstr_case_compare(xctype, octstr_imm("text/xml")) != 0) {
			 /* Found something that might be the body, since its not XML. 
			  * Perhaps we compare bodies? For broken ones anyway, so no bother!
			  */
			 found = 1;
			 msg = x;
		    }
	       loop:
		    if (x && !found) mime_entity_destroy(x);
		    if (hx) http_destroy_headers(hx);
		    octstr_destroy(xctype);
		    octstr_destroy(xparams);
	       }
     }
          
     smsg = gw_malloc(sizeof *smsg);
     smsg->envelope = h;
     smsg->msg = msg;

 done:
     if (mime)
	  mime_entity_destroy(mime);
     if (start)
	  mime_entity_destroy(start);
     if (xml)
	  octstr_destroy(xml);
     return smsg;
}

static int append_address(Octstr *p, Octstr *addr_spec)
{
     Octstr *v = addr_spec;
     char *y;
     int j, ch = octstr_get_char(v, 0);
     if (ch == '-')
	  y = " displayOnly=\"true\"";
     else 
	  y = "";
     j = octstr_case_search(v, octstr_imm("/TYPE=PLMN"),0);
     if (j >= 0) {
	  Octstr *z = octstr_copy(v, 2, j-2); /* skip the initial char that is only for info purposes. */
	  octstr_format_append(p, "<mm7:Number%s>%S</mm7:Number>\n", y, z);
	  octstr_destroy(z);
     } else 
	  octstr_format_append(p, "<mm7:RFC2822Address%s>%s</mm7:RFC2822Address>\n", 
			       y, octstr_get_cstr(v) + 2); /* as above... */
     return 0;
}

static void output_rcpt(char *hdr, List *hdrs, Octstr *p)
{
     List *l = http_header_find_all(hdrs, hdr);
     char x[32];
     int i, n;

     for (i = 0, n = gwlist_len(l), x[0]=0; i < n; i++) {
	  Octstr *h = NULL, *v  = NULL;
	  http_header_get(l, i, &h, &v);

	  if (octstr_str_compare(h, x) != 0) {
	       if (x[0])
		    octstr_format_append(p, "</mm7:%s>\n", x);
	       strncpy(x, octstr_get_cstr(h), sizeof x);
	       octstr_format_append(p, "<mm7:%S>\n", h);
	  }
	  octstr_destroy(h);
	  append_address(p, v); /* put the address in */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -