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

📄 mms_util.c

📁 手机端彩信的编解码、以及接收和发送。非常有用。
💻 C
📖 第 1 页 / 共 4 页
字号:
     {"image/gif",  "gif"},
     {"image/bmp",  "bmp"},
     {"image/vnd.wap.wbmp",  "wbmp"},
     {"image/x-bmp",  "bmp"},
     {"image/x-wmf",  "bmp"},
     {"image/vnd.wap.wpng",  "png"},
     {"image/x-up-wpng",  "png"},
     {"audio/mpeg",  "mp3"},
     {"audio/wav",  "wav"},
     {"audio/basic",  "au"},
     {"audio/amr",  "amr"},
     {"audio/x-amr",  "amr"},
     {"audio/amr-wb",  "amr"},
     {"audio/midi",  "mid"},
     {"audio/sp-midi",  "mid"},  
     {"application/smil", "smil"},
     {"application/vnd.wap.mms-message", "mms"},
     {"application/java-archive", "jar"},
     {"video/3gpp", "3gp2"},
     {"video/3gpp", "3gp"},

     {NULL, NULL}
};

Octstr *filename2content_type(char *fname)
{
     char *p = strrchr(fname, '.');
     int i;
     
     if (p) 
	  for (i = 0; exts[i].file_ext; i++)
	       if (strcasecmp(p+1, exts[i].file_ext) == 0)
		    return octstr_imm(exts[i].ctype);
     
     return octstr_imm("application/octet-stream");          
}

char *content_type2file_ext(Octstr *ctype)
{
     int i;     
     for (i = 0; exts[i].file_ext; i++)
	  if (octstr_str_case_compare(ctype, exts[i].ctype) == 0)
	    return exts[i].file_ext;
     
     return "dat";          
}

static int fetch_url_with_auth(HTTPCaller *c, int method, Octstr *url, List *request_headers, 
			       Octstr *body, Octstr *auth_hdr, List **reply_headers, Octstr **reply_body);

int mms_url_fetch_content(int method, Octstr *url, List *request_headers, 
			      Octstr *body, List **reply_headers, Octstr **reply_body)
{

     int status = 0;
     Octstr *furl = NULL;

     if (octstr_search(url, octstr_imm("data:"), 0) == 0) {
	  int i = octstr_search_char(url, ',',0);
	  Octstr *ctype = (i >= 0) ? octstr_copy(url, 5, i-5) : octstr_create("text/plain; charset=us-ascii");
	  Octstr *data = (i >= 0) ? octstr_copy(url, i+1, octstr_len(url)) : octstr_duplicate(url);

	  Octstr *n = NULL, *h = NULL;
	  
	  if (octstr_len(ctype) == 0)
	       octstr_append_cstr(ctype, "text/plain; charset=us-ascii");

	  split_header_value(ctype, &n, &h);
	  
	  if (h) {
	       List *ph = get_value_parameters(h);
	       Octstr *v = NULL;

	       if (ph && (v = http_header_value(ph, octstr_imm("base64"))) != NULL) { /* has base64 item */
		    Octstr *p = NULL;

		    octstr_base64_to_binary(data);
		    http_header_remove_all(ph, "base64");
		    
		    octstr_destroy(ctype);
		    
		    if (gwlist_len(ph) > 0) {
			 p = make_value_parameters(ph);
			 ctype = octstr_format("%S; %S",
					       n,p);
			 octstr_destroy(p);
		    } else 
			 ctype = octstr_format("%S", n);
	       }
	       
	       if (ph)
		    http_destroy_headers(ph);

	       octstr_destroy(v);
	       octstr_destroy(h);
	  }
	  
	  octstr_destroy(n);

	  *reply_body = data;
	  *reply_headers = http_create_empty_headers();
	  http_header_add(*reply_headers, "Content-Type", octstr_get_cstr(ctype));

	  octstr_destroy(ctype);
	  status = HTTP_OK;
     } else  if (octstr_search(url, octstr_imm("file://"), 0) == 0) {
	  char *file = octstr_get_cstr(url) + 6;
          Octstr *ctype = filename2content_type(file);
	  Octstr *data = octstr_read_file(file);

	  *reply_body = data;
	  *reply_headers = http_create_empty_headers();
	  http_header_add(*reply_headers, "Content-Type", octstr_get_cstr(ctype));

          status = data ? HTTP_OK : HTTP_NOT_FOUND;	  
	  octstr_destroy(ctype);	  
     } else {
	  HTTPCaller *c = http_caller_create();
	  http_start_request(c, method, url, request_headers, body, 1, NULL, NULL);	  
	  if (http_receive_result_real(c, &status, &furl, reply_headers, reply_body,1) == NULL)
	       status = -1;
	  if (status == HTTP_UNAUTHORIZED) { 
	       Octstr *v = http_header_value(*reply_headers, octstr_imm("WWW-Authenticate"));
	       
	       status = fetch_url_with_auth(c, method, url, request_headers, body, v, 
					    reply_headers, reply_body);

	       octstr_destroy(v);
	  }
	  http_caller_destroy(c);
     }

     octstr_destroy(furl);

     return status;
}

 Octstr *get_stripped_param_value(Octstr *value, Octstr *param)
{
     Octstr *x = http_get_header_parameter(value, param);

     if (x != NULL && 
	 octstr_get_char(x, 0) == '"' &&
	 octstr_get_char(x, octstr_len(x) - 1) == '"') {
	  octstr_delete(x, 0, 1);
	  octstr_delete(x, octstr_len(x) - 1, 1);
     }
     return x;    
}

#define HASHLEN 16
static Octstr *make_url(HTTPURLParse *h);

/* Fetch a url with authentication as necessary. */
static int fetch_url_with_auth(HTTPCaller *c, int method, Octstr *url, List *request_headers, 
			       Octstr *body, Octstr *auth_hdr,  List **reply_headers, Octstr **reply_body)
{
     Octstr *xauth_value = auth_hdr ? octstr_duplicate(auth_hdr) : octstr_create("");
     Octstr *domain = NULL, *nonce = NULL, *opaque = NULL, *algo = NULL, *auth_type = NULL, *x;
     Octstr *realm = NULL, *xurl = NULL;
     Octstr *cnonce = NULL;
     char *nonce_count = "00000001";
     Octstr *A1 = NULL, *A2 = NULL, *rd = NULL;
     List *qop = NULL, *l = NULL;
     int i, status = HTTP_UNAUTHORIZED, has_auth = 0, has_auth_int = 0;
     HTTPURLParse *h = parse_url(url);
     unsigned char mdbuf[1+HASHLEN*4], *xs;
     char *m_qop = NULL;
     time_t t  = time(NULL);
     
     /* Check that there is a username and password in the URL! */

     if (h == NULL || h->user == NULL || octstr_len(h->user) == 0) 
	  goto done;
          
     /* First we get the auth type: */
     
     if ((i = octstr_search_char(xauth_value, ' ', 0)) < 0) {
	  warning(0, "Mal-formed WWW-Authenticate header (%s) received while fetching %s!",
		  octstr_get_cstr(xauth_value), url ? octstr_get_cstr(url) : "");
	  status = -1;
	  goto done;
     }
     auth_type = octstr_copy(xauth_value, 0, i);
     octstr_delete(xauth_value, 0, i+1);

     if (octstr_str_case_compare(auth_type, "Basic") == 0) {
	  status = HTTP_UNAUTHORIZED; /* suported by default by GWLIB so if we get here, means bad passwd. */
	  goto done;
     } /* else digest. */

     /* Put back some fake data so what we have can be parsed easily. */
     if ((l =  http_header_split_auth_value(xauth_value)) != NULL) {
	  Octstr *x = gwlist_get(l, 0);
	  octstr_insert(x, octstr_imm("_none; "), 0); /* make it easier to parse. */
	  octstr_destroy(xauth_value);
	  xauth_value = octstr_duplicate(x);
	  
	  gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy);
     } else 
	  warning(0, "Mal-formed Digest header (%s) while fetching (%s)!", 
		  octstr_get_cstr(xauth_value), url ? octstr_get_cstr(url) : "");
     
     realm = get_stripped_param_value(xauth_value, octstr_imm("realm"));
     domain = get_stripped_param_value(xauth_value, octstr_imm("domain"));
     nonce = get_stripped_param_value(xauth_value, octstr_imm("nonce"));
     opaque = get_stripped_param_value(xauth_value, octstr_imm("opaque"));     
     algo = get_stripped_param_value(xauth_value, octstr_imm("algorithm"));

     if ((x = get_stripped_param_value(xauth_value, octstr_imm("qop"))) != NULL) {
	  int i;
	  qop = octstr_split(x, octstr_imm(","));
	  octstr_destroy(x);
	  for (i = 0; i<gwlist_len(qop); i++) { /* find qop options. */
	       Octstr *s = gwlist_get(qop, i);
	       if (!s) continue;
	       if (octstr_str_case_compare(s, "auth") == 0)
		    has_auth = 1;
	       else if (octstr_str_case_compare(s, "auth-int") == 0)
		    has_auth_int = 1;
	  }
     }
     
     /* from here on, libssl is required. */
#ifdef HAVE_LIBSSL
     if (qop || 
	 (algo != NULL && octstr_str_case_compare(algo, "MD5-sess") == 0)) {
	  unsigned char *x = MD5((void *)&t, sizeof t, (void *)mdbuf);
	  cnonce = octstr_create_from_data((void *)x, 4);
	  octstr_binary_to_hex(cnonce,0);
     }

     /* Make A1 */
     x = octstr_format("%S:%S:%S",
		       h->user, realm, h->pass ? h->pass : octstr_imm(""));
     xs = MD5((void *)octstr_get_cstr(x), octstr_len(x), (void *)mdbuf);
     A1 = octstr_create_from_data((char *)xs, HASHLEN);
     octstr_destroy(x);

     if (algo != NULL && octstr_str_case_compare(algo, "MD5-sess") == 0) {
	  x = octstr_format("%S:%S:%S", 
			    A1, nonce, cnonce);
	  xs = MD5((void *)octstr_get_cstr(x), octstr_len(x), (void *)mdbuf);
	  octstr_destroy(A1);
	  A1 = octstr_create_from_data((char *)xs, HASHLEN);
	  octstr_destroy(x);	  
     }
     octstr_binary_to_hex(A1,0);

     /* Make A2. */
     x = octstr_format("%s:%S",
		       http_method2name(method), 
		       h->path);
     if (qop != NULL && has_auth_int && !has_auth) { /* if qop, and qop=auth-int */
	  Octstr *y; 
	  m_qop = "auth-int";
	  
	  xs = MD5((void *)octstr_get_cstr(body), octstr_len(body), (void *)mdbuf);
	  y = octstr_create_from_data((char *)xs, HASHLEN);
	  octstr_binary_to_hex(y,0);

	  octstr_append_char(x, ':');
	  octstr_append(x, y);

	  octstr_destroy(y);
     } else if (qop)
	  m_qop = "auth";

     xs = MD5((void *)octstr_get_cstr(x), octstr_len(x), (void *)mdbuf);
     A2 = octstr_create_from_data((char *)xs, HASHLEN);
     octstr_destroy(x);
     octstr_binary_to_hex(A2,0);
     
     /* Finally make the digest response */
     if (qop) 
	  x = octstr_format("%S:%S:%s:%S:%s:%S",
			    A1, nonce, nonce_count, cnonce,
			    m_qop, A2);
     else 
	  x = octstr_format("%S:%S:%S", A1, nonce, A2);

     xs = MD5((void *)octstr_get_cstr(x), octstr_len(x), (void *)mdbuf);
     octstr_destroy(x);

     rd = octstr_create_from_data((char *)xs, HASHLEN);
     octstr_binary_to_hex(rd, 0);
     
     
     /* make the header value */
     x = octstr_format("Digest username=\"%S\", realm=\"%S\", response=\"%S\", nonce=\"%S\", uri=\"%S\"",
		       h->user, realm, rd, nonce, h->path);

     if (opaque) 
	  octstr_format_append(x, ", opaque=\"%S\"", opaque);
     
     if (cnonce) 
	  octstr_format_append(x, ", cnonce=\"%S\", nc=%s", cnonce, nonce_count);
     if (m_qop)
	  octstr_format_append(x,", qop=%s", m_qop);
     if (algo)
	  octstr_format_append(x,", algorithm=%S", algo);

     http_header_remove_all(request_headers, "Authorization");
     http_header_add(request_headers, "Authorization", octstr_get_cstr(x));
     octstr_destroy(x);

     /* Remove username, password, then remake URL */
     if (h->user) octstr_destroy(h->user);
     h->user = NULL;
	 
     if (h->pass) octstr_destroy(h->pass);
     h->pass = NULL;

     xurl = make_url(h);
     x = NULL;
     http_start_request(c, method, xurl, request_headers, body, 1, NULL, NULL);	  
     if (http_receive_result_real(c, &status, &x, reply_headers, reply_body,1) == NULL)
	  status = -1;
     if (x)
	  octstr_destroy(x);
#else
     mdbuf[0] = 0; /* keep the compiler quiet. */
     error(0, "Digest authentication requested on url (%s), but SSL not compiled!", 
	   octstr_get_cstr(url));     
#endif     
 done:
     octstr_destroy(xauth_value);     
     octstr_destroy(realm);     
     octstr_destroy(domain);
     octstr_destroy(nonce);
     octstr_destroy(opaque);
     octstr_destroy(algo);
     octstr_destroy(xurl);
     octstr_destroy(cnonce);
     gwlist_destroy(qop, (gwlist_item_destructor_t *)octstr_destroy);     
     if (h)
	  http_urlparse_destroy(h);
     
     return status;
}


static Octstr *make_url(HTTPURLParse *h)
{
     Octstr *url = octstr_duplicate(h->scheme);
     
     if (h->user) {
	  octstr_format_append(url, "%S", h->user);
	  
	  if (h->pass)
	       octstr_format_append(url, ":%S", h->pass);	       
	  octstr_format_append(url, "@");
     }
     octstr_format_append(url, "%S:%d%S", h->host, h->port, h->path);
     
     if (h->query)
	  octstr_format_append(url, "?%S", h->query);

     if (h->fragment)
	  octstr_format_append(url, "#%S", h->fragment);
     return url;
}

static int is_separator_char(int c)
{
    switch (c) {
    case '(':
    case ')':
    case '<':
    case '>':
    case '@':
    case ',':
    case ';':
    case ':':
    case '\\':
    case '"':
    case '/':
    case '[':
    case ']':
    case '?':
    case '=':
    case '{':
    case '}':
    case 32:  /* SP */
    case 9:   /* HT */
        return 1;
    default:
        return 0;
    }
}

/* Is this char part of a 'token' as defined by HTTP? */
static int is_token_char(int c)
{
    return c >= 32 && c < 127 && !is_separator_char(c);
}

/* Is this string a 'token' as defined by HTTP? */
int  mms_is_token(Octstr *token)
{
    return octstr_len(token) > 0 &&
           octstr_check_range(token, 0, octstr_len(token), is_token_char);
}

⌨️ 快捷键说明

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