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

📄 mms_msg.c

📁 手机端彩信的编解码、以及接收和发送。非常有用。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Mbuni - Open  Source MMS Gateway 
 * 
 * MMS 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 <time.h>
#include <ctype.h>
#include "mms_msg.h"
#include "mms_util.h"

struct MmsMsg {
     int message_type; 
     Octstr *msgId;
     List *headers; /* Of type HTTPHeader. */
     mms_encoding enc;
     unsigned char ismultipart;
     union {
	  List *l;
	  Octstr *s;
     } body; /* list of MIMEEntity (for multipart), text otherwise.*/
};


#define SIZHINT 47


static int encode_msgheaders(Octstr *os, List *hdrs);
static int decode_msgheaders(ParseContext *context, List *hdr, Octstr *from, int stop_on_ctype);


static inline void pack_short_integer(Octstr *s, int ch)
{
     unsigned long c = ((unsigned)ch)&0x7f;
     wsp_pack_short_integer(s, c);
}

#if 0
static void encode_uint(Octstr *os, unsigned int l)
{
     char xbuf[5];
     int i = 0; 
     
     do {
	  xbuf[i++] = l&0x7f;
	  l>>=7;
     } while (i < 5 && l);

     while (--i > 0) {
	  xbuf[i] |= 0x80;
	  octstr_append_data(os, &xbuf[i], 1);
     }

     octstr_append_data(os, &xbuf[0], 1);
}
#endif

int mms_validate_address(Octstr *s)
{

     int i = octstr_search_char(s, '/', 0);
     int l = octstr_len(s);
     
     if (octstr_search_char(s, '@', 0) > 0)
	  return 0;
     else if (i >= 0)	
	  if (octstr_case_search(s, octstr_imm("PLMN"), 0) + 4 == l ||
	      octstr_case_search(s, octstr_imm("IPv4"), 0) + 4 == l ||
	      octstr_case_search(s, octstr_imm("IPv6"), 0) + 4 == l)
	       return 0;
	  else
	       return -1;
     else
	  return -1;
     
}


static int decode_multipart(ParseContext *context, List *body)
{
     int i=0, n;
     
     n = parse_get_uintvar(context);
     
     for  (i = 0; i<n && parse_octets_left(context) > 0 ; i++) {
	  int dlen, hlen;
	  MIMEEntity *x = mime_entity_create();	 
	  List *headers;
	  
	  Octstr *hs;
	  Octstr *content;
	  Octstr *content_type;


	  hlen = parse_get_uintvar(context);
	  dlen = parse_get_uintvar(context);
	  
	  parse_limit(context, hlen);

	  hs = parse_get_octets(context, parse_octets_left(context));

	  headers = wsp_headers_unpack(hs, 1);
	  octstr_destroy(hs);

	  strip_boundary_element(headers,NULL);
	  mime_replace_headers(x, headers);	  
	  
	  parse_skip_to_limit(context);
	  parse_pop_limit(context);
	  
	  content_type = http_header_value(headers, octstr_imm("Content-Type"));	  
	  content = parse_get_octets(context, dlen);

	  http_destroy_headers(headers);

	  if (!content || !content_type) { 
	       int pleft = parse_octets_left(context);
	       warning(0, "Parse error reading mime body [hlen=%d, dlen=%d, left=%d]!",
		       hlen,dlen, pleft);
	       mime_entity_destroy(x);
	       if (content_type) 
		    octstr_destroy(content_type);
	       if (content) 
		    octstr_destroy(content);
	       return -1;
	  }

	  if (octstr_case_compare(content_type, 
				 octstr_imm("application/vnd.wap.multipart.related")) == 0 ||
	      octstr_case_compare(content_type, 
				 octstr_imm("application/vnd.wap.multipart.alternative")) == 0 ||
	      octstr_case_compare(content_type, 
				 octstr_imm("application/vnd.wap.multipart.mixed")) == 0) { /* Body is multipart. */
	       ParseContext *p = parse_context_create(content);
	       List *ml =  gwlist_create();	       
	       int res = decode_multipart(p, ml);

	       parse_context_destroy(p);
	       if (res == 0) {
		    /* Put body parts into mime object. */
		    int j, m  = gwlist_len(ml);
		    for (j = 0; j < m; j++)
			 mime_entity_add_part(x, gwlist_get(ml,i));		    
	       }

	       gwlist_destroy(ml, (gwlist_item_destructor_t *)mime_entity_destroy);
	       if (res < 0) {
		    if (content_type) 
			 octstr_destroy(content_type);	
		    if (content) 
			 octstr_destroy(content);		    
		    return -1;
	       }
	  } else 
	       mime_entity_set_body(x,content);
	  octstr_destroy(content);
	  octstr_destroy(content_type);
	  gwlist_append(body, x);
     }
     return 0;         
}

static int encode_multipart(Octstr *os, List *body)
{
     int i, j, n, m;

     n = gwlist_len(body);
     octstr_append_uintvar(os, n);

     i = 0;
     while (i<n) {
	  Octstr *mhdr, *mbody = octstr_create("");
	  MIMEEntity *x = gwlist_get(body, i);
	  List *headers = mime_entity_headers(x);
	  Octstr *s;
	  
	  strip_boundary_element(headers,NULL);
	  mhdr = wsp_headers_pack(headers, 1, WSP_1_3);
	  http_destroy_headers(headers);

	  if ((m = mime_entity_num_parts(x)) > 0) {  /* This is a multi-part, 
						      * go down further. 
						      */
	       List *l = gwlist_create();

	       for (j = 0; j < m; j++)
		    gwlist_append(l, mime_entity_get_part(x, j));
	       encode_multipart(mbody, l);
	       gwlist_destroy(l, (gwlist_item_destructor_t *)mime_entity_destroy);
	  } else if ((s = mime_entity_body(x)) != NULL) {
	       octstr_append(mbody, s);
	       octstr_destroy(s);
	  }
	  
	  octstr_append_uintvar(os, octstr_len(mhdr));
	  octstr_append_uintvar(os, octstr_len(mbody));

	  octstr_append(os, mhdr);
	  octstr_append(os, mbody);

	  octstr_destroy(mhdr);
	  octstr_destroy(mbody);

	  i++;
     }
     return 0;         
}

static int decode_msgbody(ParseContext *context, MmsMsg *msg)
{
     int res = 0;
     if (msg->ismultipart) {
	  msg->body.l = gwlist_create();
	  res = decode_multipart(context, msg->body.l);
     } else 
	  msg->body.s = parse_get_rest(context);

     return res;     
}

static void encode_msgbody(Octstr *os, MmsMsg *msg)
{
     if (msg->ismultipart) 
	  encode_multipart(os, msg->body.l);    
     else
	  octstr_append(os, msg->body.s);
}

/* If ret < 0 then we need to get a field value, else we use what's passed. */
static Octstr *decode_encoded_string_value(int ret, ParseContext *context, unsigned char *hname)
{
     int val;
     int ret2;
     Octstr *res = NULL;
     
     ret2 = (ret < 0) ?  wsp_field_value(context, &val) : ret;
     
     if (ret2 == WSP_FIELD_VALUE_DATA) { /* expect charset text. */
	  long charset; /* Get it and ignore it. */
	  wsp_secondary_field_value(context, &charset);
	  res = parse_get_nul_string(context); /* XXX Currently we ignore charset */

	  if (ret < 0) {
	       parse_skip_to_limit(context);
	       parse_pop_limit(context);
	  }

     } else if (ret2 != WSP_FIELD_VALUE_NUL_STRING) {
	  warning(0, "Faulty header value for %s! [ret=%d,ret2=%d]\n", hname,ret,ret2);
	  res = octstr_imm("");
     } else 
	  res = parse_get_nul_string(context);
     
     return res;
}

/* Decodes it, adds to 'unpacked' which is the header list. 
 * returns the first value token got when parsing value -- 
 * useful for unpacking msg type 
 */
static int mms_unpack_well_known_field(List *unpacked, int field_type,
					ParseContext *context, 
				       Octstr *xfrom, int msgtype)
{
     int val, ret;
     unsigned char *hname = NULL;

     Octstr *decoded = NULL;
     unsigned char *ch = NULL;

     ret = wsp_field_value(context, &val);

     if (parse_error(context)) {
	  warning(0, "Faulty header [code = %d], skipping remaining headers.", field_type);
	  parse_skip_to_limit(context);
	  return -1;
     }

     hname = mms_header_to_cstr(field_type);

     if (ret == WSP_FIELD_VALUE_NUL_STRING) 
	  decoded = parse_get_nul_string(context);
     
     switch (field_type) {
	  
     case MMS_HEADER_TO:
     case MMS_HEADER_CC:
     case MMS_HEADER_BCC:
	  if (ret == WSP_FIELD_VALUE_DATA) 
	       decoded = decode_encoded_string_value(ret, context, hname);

	  if (mms_validate_address(decoded))
	       warning(0, "Faulty address [%s] format in field %s!", 
		       octstr_get_cstr(decoded), hname);
	  break;
     case MMS_HEADER_SUBJECT:
     case MMS_HEADER_RETRIEVE_TEXT:
	  
     case MMS_HEADER_STORE_STATUS_TEXT:
	  if (ret == WSP_FIELD_VALUE_DATA) 
	       decoded = decode_encoded_string_value(ret, context, hname);
	  break;

     case MMS_HEADER_RESPONSE_TEXT:    
	  if (msgtype == MMS_MSGTYPE_MBOX_DELETE_REQ && 
	      ret == WSP_FIELD_VALUE_DATA) {
	       int ret2;

	       decoded = wsp_unpack_integer_value(context);

	       ret2= wsp_field_value(context, &val);
	       octstr_append(decoded, decode_encoded_string_value(ret2, context, hname));
	       
	       if (ret2 == WSP_FIELD_VALUE_DATA) { /* we need to skip to end of inner value-data. */
		    parse_skip_to_limit(context);
		    parse_pop_limit(context);		    
	       } 
	  } else if (ret == WSP_FIELD_VALUE_DATA) 
	       decoded = decode_encoded_string_value(ret, context, hname);
    
	  break;
     case MMS_HEADER_TRANSACTION_ID:
     case MMS_HEADER_MESSAGE_ID:
     case MMS_HEADER_REPLY_CHARGING_ID:
	  if (ret != WSP_FIELD_VALUE_NUL_STRING)
	       warning(0, "Unexpected field value type %d for header %s\n",
		       ret, hname);
	  
	  break;	       

	  /* MMS v1.2 mandates slightly different format,
	   * when used in m-mbox-delete.conf
	   */
     case MMS_HEADER_CONTENT_LOCATION:
	  if (ret == WSP_FIELD_VALUE_DATA) {
	       Octstr *t;
	       decoded = wsp_unpack_integer_value(context);
	       t = parse_get_nul_string(context);
	       octstr_append(decoded, t);
	       octstr_destroy(t);
	  } else if (ret != WSP_FIELD_VALUE_NUL_STRING)
	       warning(0, "Unexpected field value type %d for header %s\n",
		       ret, hname);	  
	  break;
     case MMS_HEADER_MMS_VERSION:
	  if (ret == WSP_FIELD_VALUE_ENCODED)
	       decoded = wsp_unpack_version_value(val);
	  break;
	  /* integer/octet values */
     case MMS_HEADER_DELIVERY_REPORT:	 
     case MMS_HEADER_REPORT_ALLOWED:
     case MMS_HEADER_READ_REPORT:

     case MMS_HEADER_DISTRIBUTION_INDICATOR:
     case MMS_HEADER_QUOTAS:

     case MMS_HEADER_STORE:
     case MMS_HEADER_STORED:
     case MMS_HEADER_TOTALS:
	  
	  ch = mms_reports_to_cstr(val);
	  break;
     case MMS_HEADER_MESSAGE_TYPE:
	  ch = mms_message_type_to_cstr(val);
	  break;
     case MMS_HEADER_PRIORITY:
	  ch = mms_priority_to_cstr(val);
	  break;
     case MMS_HEADER_READ_STATUS:
	  ch = mms_read_status_to_cstr(val);
	  break;	  
     case MMS_HEADER_REPLY_CHARGING:
	  ch = mms_reply_charging_to_cstr(val);
	  break;

     case MMS_HEADER_RESPONSE_STATUS:
	  if (ret == WSP_FIELD_VALUE_DATA) {
	       unsigned char *x;
	       int val;
	       decoded = wsp_unpack_integer_value(context);
	       wsp_field_value(context, &val);
	       x = mms_response_status_to_cstr(val|0x80);
	       
	       octstr_append_cstr(decoded, (char *)x);
	       
	  } else 
	       ch = mms_response_status_to_cstr(val|0x80);
	  break;
     case MMS_HEADER_RETRIEVE_STATUS:
	  ch = mms_retrieve_status_to_cstr(val|0x80);
	  break;
     case MMS_HEADER_STATUS:
	  ch = mms_status_to_cstr(val);
	  break;
     case MMS_HEADER_SENDER_VISIBILITY:
	  ch = mms_visibility_to_cstr(val);
	  break;
     case MMS_HEADER_MESSAGE_CLASS: 	  
	  if (ret != WSP_FIELD_VALUE_NUL_STRING) 
	       ch = mms_message_class_to_cstr(val);	              
	  break;
	  
     case MMS_HEADER_DATE: /* Date values. */	       
	  parse_skip(context, -1); 
	  decoded = wsp_unpack_date_value(context);
	  break;	  

     case MMS_HEADER_MESSAGE_SIZE:
     case MMS_HEADER_REPLY_CHARGING_SIZE:
     case MMS_HEADER_START:

     case MMS_HEADER_LIMIT:
     case MMS_HEADER_MESSAGE_COUNT:

	  parse_skip(context, -1); 
	  decoded = wsp_unpack_integer_value(context);
	  break;
	  
     case MMS_HEADER_CONTENT_TYPE:
	  if (ret == WSP_FIELD_VALUE_ENCODED)
	       ch  = wsp_content_type_to_cstr(val);

⌨️ 快捷键说明

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