static char rcsid[] = "@(#)$Id: mailto.c,v 1.6 2006/06/25 10:41:05 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.6 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *      or  Kari Hurtta <elm@elmme-mailer.org>
 *****************************************************************************/

#include "def_url.h"
#include "s_me.h"

DEBUG_VAR(Debug,__FILE__,"url");

static unsigned char * s2us P_((char *str));
static unsigned char * s2us(str)
     char *str;
{
    return (unsigned char *)str;
}

static char *us2s P_((unsigned char *str));
static char *us2s(str)
     unsigned char *str;
{
    return (char *)str;
}

static CONST unsigned char *cs2us P_((const char *str));
static CONST unsigned char *cs2us(str)
     CONST char *str;
{
    return (CONST unsigned char *)str;
}



#define URL_mailto_magic	0xEC06

struct url_mailto {

    unsigned short        magic;     /* URL_mailto_magic */

    struct url_element  * addr;


    struct url_header {
	header_ptr            header_name;
	struct url_element  * header_body;

    }                   * hdrs;
    int                   hdrs_count;

    struct url_element  * body;

};


#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif

S_(uh_init_url uh_init_mailto)
static void uh_init_mailto  P_((struct url *url));
static void uh_init_mailto(url)
     struct url *url;
{
    url->u.mailto = safe_malloc (sizeof (*  url->u.mailto));

    /* bzero is defined hdrs/defs.h */
    bzero((void *)url->u.mailto,sizeof (* url->u.mailto));

    url->u.mailto->magic = URL_mailto_magic;
    url->u.mailto->addr  = NULL;

    url->u.mailto->hdrs       = NULL;
    url->u.mailto->hdrs_count = 0;

    url->u.mailto->body       = NULL;
}

S_(uh_free_url uh_free_mailto)
static void uh_free_mailto  P_((struct url *url));
static void uh_free_mailto(url)
     struct url *url;
{
    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_free_mailto",
	      "bad  magic number",0);

    if (url->u.mailto->addr)
	free_url_element(& (url->u.mailto->addr));


    if (url->u.mailto->hdrs) {
	int i;

	for (i = 0; i < url->u.mailto->hdrs_count; i++) {
	    if (url->u.mailto->hdrs[i].header_body)
		free_url_element(& (url->u.mailto->hdrs[i].header_body));
	    url->u.mailto->hdrs[i].header_name = NULL;
	}

	free(url->u.mailto->hdrs);
	url->u.mailto->hdrs = NULL;
    }
    url->u.mailto->hdrs_count = 0;

    if (url->u.mailto->body)
	free_url_element(& (url->u.mailto->body));

    url->u.mailto->magic = 0;  /* Invalidate */
    free(url->u.mailto);
    url->u.mailto = NULL;
}

/* RFC 2368:

   Following the syntax conventions of RFC 1738 [RFC1738], a "mailto"
   URL has the form:

     mailtoURL  =  "mailto:" [ to ] [ headers ]
     to         =  #mailbox
     headers    =  "?" header *( "&" header )
     header     =  hname "=" hvalue
     hname      =  *urlc
     hvalue     =  *urlc

   "#mailbox" is as specified in RFC 822 [RFC822]. This means that it
   consists of zero or more comma-separated mail addresses, possibly
   including "phrase" and "comment" components. Note that all URL
   reserved characters in "to" must be encoded: in particular,
   parentheses, commas, and the percent sign ("%"), which commonly occur
   in the "mailbox" syntax.

   "hname" and "hvalue" are encodings of an RFC 822 header name and
   value, respectively. As with "to", all URL reserved characters must
   be encoded.

   The special hname "body" indicates that the associated hvalue is the
   body of the message. The "body" hname should contain the content for
   the first text/plain body part of the message. The mailto URL is
   primarily intended for generation of short text messages that are
   actually the content of automatic processing (such as "subscribe"
   messages for mailing lists), not general MIME bodies.

   Within mailto URLs, the characters "?", "=", "&" are reserved.

*/


S_(uh_parse_url_not_path  uh_parse_mailto_not_path)
static int uh_parse_mailto_not_path  P_((struct url *url, 
					 struct string *scheme_pesifix,
					 struct header_errors **header_error));

static int uh_parse_mailto_not_path(url,scheme_pesifix,header_error)
     struct url *url;
     struct string *scheme_pesifix;
     struct header_errors **header_error;
{
    CONST struct string * X = NULL;
    int len,x;

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_not_path",
	      "bad  magic number",0);


    url->u.mailto->addr = element_from_raw(scheme_pesifix);

    X = parsed_from_element(url->u.mailto->addr,header_error);
    if (!X) {
	DPRINT(Debug,10,(&Debug, 
			"uh_parse_mailto_not_path: parsed_from_element failed\n"));
	return 0;
    }

    len = string_len(X);
    for (x = 0; x < len; x++) {
	uint16 ch = give_unicode_from_string(X,x);
		

	if (0x0040 /* @ */  == ch)
	    goto found;

    }

    process_header_error(header_error,
			 CATGETS(elm_msg_cat, MeSet,
				 MeURLMailToAt,
				 "At (@) character required on URL mailto address: %S"),
			 X);


    DPRINT(Debug,10,(&Debug, 
		    "uh_parse_mailto_not_path: No @ -character\n"));

    return 0;

 found:
    return 1;
}

S_(uh_dup_url_not_path uh_dup_mailto_not_path)
static int uh_dup_mailto_not_path  P_((struct url *url,
				       struct url *source));
static int uh_dup_mailto_not_path(url,source)
     struct url *url;
     struct url *source;
{
    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_not_path",
	      "bad  magic number (url)",0);

    if (URL_mailto_magic != source->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_not_path",
	      "bad  magic number (source)",0);

    if (source->u.mailto->addr)
	url->u.mailto->addr = dup_url_element(url->u.mailto->addr);

    return 0;
}

S_(uh_parse_url_params uh_parse_mailto_params)
static int uh_parse_mailto_params  P_((struct url *url, 
				       struct string *scheme_pesifix,
				       struct header_errors **header_error));
static int uh_parse_mailto_params(url,scheme_pesifix,header_error)
     struct url *url;
     struct string *scheme_pesifix;
     struct header_errors **header_error;
{
    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_params",
	      "bad  magic number",0);

    /* No params? */

    return 0;
}

S_(uh_dup_url_params uh_dup_mailto_params)
static int uh_dup_mailto_params  P_((struct url *url,
				       struct url *source));
static int uh_dup_mailto_params(url,source)
     struct url *url;
     struct url *source;
{
    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_params",
	      "bad  magic number (url)",0);

    if (URL_mailto_magic != source->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_params",
	      "bad  magic number (source)",0);

    /* No params? */

    return 0;
}

S_(uh_parse_url_query uh_parse_mailto_query)
static int uh_parse_mailto_query  P_((struct url *url, 
				      struct string *scheme_pesifix,
				      struct header_errors **header_error));
static int uh_parse_mailto_query(url,scheme_pesifix,header_error)
     struct url *url;
     struct string *scheme_pesifix;
     struct header_errors **header_error;
{
    int len = string_len(scheme_pesifix);
    int X = 0;
    char * buffer;
    int ret = 0;
    int count = 1;

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_query",
	      "bad  magic number",0);

    if (len < 1)
	return 1;   /* Silently accept */


    for (X = 0; X < len; X++) {
	uint16 ch = give_unicode_from_string(scheme_pesifix,X);
	
	if (0x0026 /* & */ == ch)
	    count++;
    }

    DPRINT(Debug,9,(&Debug,
		    "uh_parse_mailto_query: %d headers\n",count));

    url->u.mailto->hdrs = safe_malloc(count * sizeof (url->u.mailto->hdrs[0]));

    /* bzero is defined hdrs/defs.h */
    bzero((void *) url->u.mailto->hdrs,
	  count * sizeof (url->u.mailto->hdrs[0]));


    /* This code assumes that code charset is ASCII */
    buffer = malloc(len);


    X = 0;
    while (X < len) {
	uint16 ch = 0;
	int startpos = X;

	struct string * raw_header_name = NULL;
	struct string * raw_header_value = NULL;
	struct string * decoded_header_name = NULL;
	int L;
	int have_failed = 0;
	int Y,L1;
	
	/* Scan for name */

	/* check for header name */
	for (; X < len; X++) {
	    ch = give_unicode_from_string(scheme_pesifix,X);

	    if (0x003A /* : */ == ch ||
		0x0026 /* & */ == ch ||
		0x0080         <= ch) {
		
		DPRINT(Debug,2,(&Debug,
				"uh_parse_mailto_query: Failed to parse mailto headers: %S",
				scheme_pesifix));
		process_header_error(header_error,
				     CATGETS(elm_msg_cat, MeSet,
					     MeURLMailToHeaders,
					     "Failed to parse mailto headers: %S"),
				     scheme_pesifix);

		goto fail_headers;
	    }

	    if (0x003D /* = */ == ch)
		break;

	}


	if (0x003D /* = */ != ch) {
	
	    DPRINT(Debug,2,(&Debug,
			    "uh_parse_mailto_query: Failed to parse mailto headers: %S",
			    scheme_pesifix));
	    process_header_error(header_error,
				 CATGETS(elm_msg_cat, MeSet,
					 MeURLMailToHeaders,
					 "Failed to parse mailto headers: %S"),
				 scheme_pesifix);

	    goto fail_headers;

	}


	L = X - startpos;

	
	DPRINT(Debug,9,(&Debug,
			"uh_parse_mailto_query: %d - %d (len=%d) header name found\n",
			X,startpos,L));
	    
	raw_header_name = clip_from_string(scheme_pesifix,&startpos,L);
	    
	if (startpos != X)
	    panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_query",
		  "Clipping Error (header name -part)",0);
	
	DPRINT(Debug,11,(&Debug,
			 "uh_parse_mailto_query: raw header name=%S\n",raw_header_name));
	

	startpos = ++X; 
	ch = 0;

	/* check for header value */	
	for (; X < len; X++) {
	    ch = give_unicode_from_string(scheme_pesifix,X);

	    if (0x0026 /* & */ == ch ||
		0x003D /* = */ == ch)
		break;

	}

	if (X < len && 
	    0x0026 /* & */ != ch) {
	    DPRINT(Debug,2,(&Debug,
			    "uh_parse_mailto_query: Failed to parse mailto headers: %S",
			    scheme_pesifix));
	    process_header_error(header_error,
				 CATGETS(elm_msg_cat, MeSet,
					 MeURLMailToHeaders,
					 "Failed to parse mailto headers: %S"),
				 scheme_pesifix);

	    goto fail_headers;
	}

	L = X - startpos;

	
	DPRINT(Debug,9,(&Debug,
			"uh_parse_mailto_query: %d - %d (len=%d) header value found\n",
			X,startpos,L));
	    
	raw_header_value = clip_from_string(scheme_pesifix,&startpos,L);
	    
	if (startpos != X)
	    panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_query",
		  "Clipping Error (header value -part)",0);
	
	DPRINT(Debug,11,(&Debug,
			 "uh_parse_mailto_query: raw header value=%S\n",raw_header_value));


	decoded_header_name = raw_to_parsed(raw_header_name,header_error);
	if (!decoded_header_name) {

	    DPRINT(Debug,2,(&Debug,
			    "uh_parse_mailto_query: Failed to parse mailto headers: %S",
			    scheme_pesifix));
	    
	    process_header_error(header_error,
				 CATGETS(elm_msg_cat, MeSet,
					 MeURLMailToHeaders,
					 "Failed to parse mailto headers: %S"),
				 scheme_pesifix);
	    
	    goto fail_headers;
	}

	L1 = string_len(decoded_header_name);
	if (!L1) {
	    DPRINT(Debug,2,(&Debug,
			    "uh_parse_mailto_query: Failed to parse mailto headers: %S",
			    scheme_pesifix));
	    
	    process_header_error(header_error,
				 CATGETS(elm_msg_cat, MeSet,
					 MeURLMailToHeaders,
					 "Failed to parse mailto headers: %S"),
				 scheme_pesifix);
	    
	    goto fail_headers;
	}
	
	for (Y = 0; Y < L1; Y++) {
	    uint16 ch1 = give_unicode_from_string(decoded_header_name,Y);

	    if (0x0061 /* a */ <= ch1 && ch1 <= 0x007A /* z */  ||
		0x0030 /* 0 */ <= ch1 && ch1 <= 0x0039 /* 9 */  ||
		0x002B /* + */ == ch1 ||
		0x002E /* . */ == ch1 ||
		0x002D /* - */ == ch1 ||
		0x0041 /* A */ <= ch1 && ch1 <= 0x005A /* Z */)
		buffer[Y] = ch1;
	    else {
		DPRINT(Debug,9,(&Debug,
				"uh_parse_mailto_query: [%d] ch=%04x not valid for header = decoded =%S\n",
				Y,ch1,decoded_header_name));
		
		process_header_error(header_error,
				     CATGETS(elm_msg_cat, MeSet,
					     MeURLMailToHeaders,
					     "Failed to parse mailto headers: %S"),
				     scheme_pesifix);
	    
		goto fail_headers;
	    }
	}
	buffer[Y] = '\0';


	if (0 == istrcmp(buffer,"body")) {

	    if (url->u.mailto->body) {

		DPRINT(Debug,2,(&Debug,
				"uh_parse_mailto_query: Duplicate mail body on mailto ignored: %S",
			      scheme_pesifix));
		
		process_header_error(header_error,
				     CATGETS(elm_msg_cat, MeSet,
					     MeURLMailToDuplicateBody,
					     "Duplicate mail body on mailto ignored: %S"),
				     scheme_pesifix);
		
	    } else
		url->u.mailto->body = element_from_raw(raw_header_value);

	} else {
	    header_ptr hdr = find_header(buffer,0);

	    if (! hdr  ||
		0 == strincmp(buffer,"Resent-",7) ||
		0 == istrcmp(buffer,"Return-path") ||
		0 == istrcmp(buffer,"Reply-To") ||
		0 == istrcmp(buffer,"From") ||
		0 == istrcmp(buffer,"Sender") ||
		! is_mailing_header(hdr)) {
		
		DPRINT(Debug,2,(&Debug,
				"uh_parse_mailto_query: Header %s on mailto ignored: %S",
				buffer,scheme_pesifix));
		       
		process_header_error(header_error,
				     CATGETS(elm_msg_cat, MeSet,
					     MeURLMailToIgnoredHeader,
					     "Header %s on mailto ignored: %S"),
				     buffer,scheme_pesifix);


	    } else {

		if (url->u.mailto->hdrs_count >= count)
		    panic("URL PANIC",__FILE__,__LINE__,"uh_parse_mailto_query",
			  "header index overflow",0);
		    

		url->u.mailto->hdrs[url->u.mailto->hdrs_count].header_name = hdr;
		url->u.mailto->hdrs[url->u.mailto->hdrs_count].header_body = 
		    element_from_raw(raw_header_value);
		url->u.mailto->hdrs_count++;

	    }
	}

	if (0) {
	fail_headers:
	    have_failed = 1;
	}
       

	if (decoded_header_name)
	    free_string(& decoded_header_name);
	if (raw_header_name)
	    free_string(& raw_header_name);
	if (raw_header_value)
	    free_string(& raw_header_value);
	
	if (have_failed)
	    goto fail;

	/* Skip & */
	X++;

    }
    ret = 1;

    DPRINT(Debug,9,(&Debug,
		    "uh_parse_mailto_query: %d headers parsed\n",
		    url->u.mailto->hdrs_count));

 fail:
    free(buffer);

    return ret;
}

S_(uh_dup_url_query uh_dup_mailto_query)
static int uh_dup_mailto_query  P_((struct url *url,
				       struct url *source));
static int uh_dup_mailto_query(url,source)
     struct url *url;
     struct url *source;
{
    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_query",
	      "bad  magic number (url)",0);

    if (URL_mailto_magic != source->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_dup_mailto_query",
	      "bad  magic number (source)",0);

    if (source->u.mailto->hdrs &&
	source->u.mailto->hdrs_count > 0) {
	int i;

	url->u.mailto->hdrs = safe_malloc( source->u.mailto->hdrs_count *
					   sizeof (url->u.mailto->hdrs[0]));

	for (i = 0; i < source->u.mailto->hdrs_count; i++) {
	    if (source->u.mailto->hdrs[i].header_body) 
		url->u.mailto->hdrs[i].header_body = 
		    dup_url_element(source->u.mailto->hdrs[i].header_body);
	    else
		source->u.mailto->hdrs[i].header_body = NULL;
	    url->u.mailto->hdrs[i].header_name = 
		source->u.mailto->hdrs[i].header_name;	    
	}
	url->u.mailto->hdrs_count = i;
    }

    if (source->u.mailto->body)
	url->u.mailto->body = dup_url_element(source->u.mailto->body);

    return 1;
}

S_(uh_set_mailing_headers_from_url uh_set_mailing_headers_from_mailto)
static int uh_set_mailing_headers_from_mailto P_((struct mailing_headers *hdrs,
						  const struct url *url,
						  struct mailer_info 
						  *mailer_info));
static int uh_set_mailing_headers_from_mailto(hdrs,url,mailer_info)
     struct mailing_headers *hdrs;
     CONST struct url *url;
     struct mailer_info  *mailer_info;
{
    CONST struct string * X = NULL;
    int i;
    int ok;

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,
	      "uh_set_mailing_headers_from_mailto",
	      "bad  magic number (url)",0);

    if (! url->u.mailto->addr) {
	DPRINT(Debug,7,(&Debug, 
			" uh_set_mailing_headers_from_mailto: No address\n"));
	return 0;
    }
    X = parsed_from_element(url->u.mailto->addr,NULL);
    if (!X) {
	DPRINT(Debug,7,(&Debug, 
			" uh_set_mailing_headers_from_mailto: parsed_from_element failed\n"));

	return 0;
    }

    /* FIXME -- this also split addresses on spaces */
    update_expanded_from_edit_buffer(& (hdrs->to),X,mailer_info,
				     NULL /* Do not expand aliases */);

    ok = 1;
    for (i = 0; i < url->u.mailto->hdrs_count; i++) {
	CONST struct string * decoded = NULL;
	unsigned char * stream = NULL;


	if (! url->u.mailto->hdrs[i].header_body) {
	    ok = 0;
	    continue;
	}

	decoded = parsed_from_element(url->u.mailto->hdrs[i].header_body,
				      NULL);
	if (! decoded) {
	    ok = 0;
	    continue;
	}

	stream = stream_from_string(decoded,0,NULL);

	if (! add_to_mailing_header(hdrs,
				    url->u.mailto->hdrs[i].header_name,
				    us2s(stream),
				    1,
				    decoded->string_type,
				    0)) {

	    lib_error(CATGETS(elm_msg_cat, MeSet,
			      MeFailedAddMailHeader,
			      "Failed to add mail header: %s: %S"),
		      give_header_name(url->u.mailto->hdrs[i].header_name),
		      decoded);

	    ok = 0;
	}

	free(stream);
    }
    
    return ok;
}

S_(uh_get_body_string_from_url uh_get_body_string_from_mailto)
static CONST struct string * uh_get_body_string_from_mailto P_((const struct 
								url *url,
								int *errors));
static CONST struct string * uh_get_body_string_from_mailto(url,errors)
     CONST struct url *url;
     int *errors;
{
    CONST struct string * ret;

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,
	      "uh_get_body_string_from_mailto",
	      "bad  magic number (url)",0);

    if (! url->u.mailto->body)
	return NULL;

    ret = parsed_from_element(url->u.mailto->body,NULL);

    if (!ret)
	*errors = 1;

    return ret;
}


S_(uh_not_path_to_raw_url uh_not_path_to_raw_mailto)
static struct string * uh_not_path_to_raw_mailto P_((const struct url *url));
static struct string * uh_not_path_to_raw_mailto(url) 
     CONST struct url *url;
{
    CONST struct string *S;

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_not_path_to_raw_mailto",
	      "bad  magic number",0);

    if (! url->u.mailto->addr)
	return NULL;

    S = raw_from_element(url->u.mailto->addr);

    if (!S) {
	DPRINT(Debug,12,(&Debug,
			 "uh_not_path_to_raw_mailto: Failed to get addr\n"));
	return NULL;
    }

    return dup_string(S);
}

S_(uh_params_to_raw_url uh_params_to_raw_mailto)
static int uh_params_to_raw_mailto P_((const struct url *url, 
				       struct string **result));
static int uh_params_to_raw_mailto(url,result)
     CONST struct url *url; 
     struct string **result;
{
    *result = NULL;

    return 0;
}

S_(uh_query_to_raw_url uh_query_to_raw_mailto)
static int uh_query_to_raw_mailto P_((const struct url *url, 
				      struct string **result));
static int uh_query_to_raw_mailto(url,result)
     CONST struct url *url; 
     struct string **result;
{
    int i;
    charset_t ascii_ptr = MIME_name_to_charset("US-ASCII",0);

    if (URL_mailto_magic != url->u.mailto->magic)
	panic("URL PANIC",__FILE__,__LINE__,"uh_query_to_raw_mailto",
	      "bad  magic number",0);

    if (!ascii_ptr)
	panic("CHARSET PANIC",__FILE__,__LINE__,"uh_query_to_raw_mailto",
	      "US-ASCII not found",0);


    *result = NULL;

    if (url->u.mailto->body) {
	CONST struct string * S = raw_from_element(url->u.mailto->body);
	
	if (!S) {
	    DPRINT(Debug,12,(&Debug,
			     "uh_query_to_raw_mailto: Failed to get body\n"));
	    goto failure;
	}

	*result = new_string(ascii_ptr);
	add_ascii_to_string(*result,s2us("body="));
	append_string(result,S);
    }

    for (i = 0; i < url->u.mailto->hdrs_count; i++) {
	CONST struct string * S = raw_from_element(url->u.mailto->hdrs[i].
						   header_body);

	if (!S) {
	    DPRINT(Debug,12,(&Debug,
			     "uh_query_to_raw_mailto: Failed to get header\n"));
	    goto failure;
	}

	if (*result)
	    add_ascii_to_string(*result,s2us("&"));
	else
	    *result = new_string(ascii_ptr);

	add_ascii_to_string(*result,
			    cs2us(give_header_name(url->u.mailto->hdrs[i].
						  header_name)));
	add_ascii_to_string(*result,s2us("="));
	append_string(result,S);
    }
    
    return 1;

 failure:
    if (*result)
	free_string(result);
    return 0;
}

S_(uh_get_folder_from_url uh_get_folder_from_mailto)
static struct folder_info * uh_get_folder_from_mailto P_((const struct url *url,
							  verify_remote_url_f    * verify_remote));
static struct folder_info * uh_get_folder_from_mailto(url,verify_remote)
     const struct url *url;
     verify_remote_url_f    * verify_remote;
{
    return NULL;
}

struct url_handler URL_mailto_handler = {
    URL_handler_magic,
    URLFLAG_query,
    url_mailing,
    uh_init_mailto,
    uh_free_mailto,
    uh_parse_mailto_not_path,
    uh_dup_mailto_not_path,
    uh_parse_mailto_params,
    uh_dup_mailto_params,
    uh_parse_mailto_query,
    uh_dup_mailto_query,
    uh_set_mailing_headers_from_mailto,
    uh_get_body_string_from_mailto,
    uh_not_path_to_raw_mailto,
    uh_params_to_raw_mailto,
    uh_query_to_raw_mailto,
    uh_get_folder_from_mailto,
    get_url_type_default
};



/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1