/* $Id: mime_conf.cpp,v 1.12 2004/01/02 04:05:36 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of the XFMail email client.                          *
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU General Public License as published by      *
 *   the Free Software Foundation; either version 2 of the License, or         *
 *   (at your option) any later version.                                       *
 *                                                                             *
 *   This program is distributed in the hope that it will be useful,           *
 *   but WITHOUT ANY WARRANTY, without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *   GNU General Public License for more details.                              *
 *                                                                             *
 *   You should have received a copy of the GNU General Public License         *
 *   along with this program; if not, write to the Free Software               *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA.  *
 *                                                                             *
 *   Additional Permission granted:                                            *
 *                                                                             *
 *   This program is designed to use the XForms library, so we consider        *
 *   permission to link to that non-GPL-compatible library is implicit.        *
 *   However, in case this is not considered so, we explicitly state:          *
 *                                                                             *
 *   "As a special exception, the Archimedes Project, with the permission      *
 *    of all earlier copyright holders, formally gives permission to link      *
 *    this program with the XForms library, and distribute the resulting       *
 *    executable without the source code for XForms in the source              *
 *    distribution".                                                           *
 *                                                                             *
 ******************************************************************************/


#include <glib.h>

#include <fmail.h>
#include <umail.h>
#include <choose_folder.h>

static FD_Attach *att_obj;
static FD_config_mime *mime_obj;
static FD_mcap *mcap_obj;
static int ready = 0;
void display_mailcap();

void Att_Type_Call(FL_OBJECT * obj, long param) {
}

void Att_Subtype_Call(FL_OBJECT * obj, long param) {
}

void Att_Charset_Call(FL_OBJECT * obj, long param) {
}

void set_encode(u_int encode) {
	fl_set_button(att_obj->Att_8bit, 0);
	fl_set_button(att_obj->Att_7bit, 0);
	fl_set_button(att_obj->Att_Base64, 0);
	fl_set_button(att_obj->Att_qprt, 0);

	switch(encode) {
		case CE_NONE:
			fl_set_button(att_obj->Att_8bit, 1);
			break;

		case CE_7BIT:
			fl_set_button(att_obj->Att_7bit, 1);
			break;

		case CE_BASE64:
			fl_set_button(att_obj->Att_Base64, 1);
			break;

		case CE_QPRT:
			fl_set_button(att_obj->Att_qprt, 1);
			break;

		default:
			fl_set_button(att_obj->Att_Base64, 1);
			break;
	}
}

u_int get_encode() {
	if(fl_get_button(att_obj->Att_8bit))
		return CE_NONE;
	else if(fl_get_button(att_obj->Att_7bit))
		return CE_7BIT;
	else if(fl_get_button(att_obj->Att_Base64))
		return CE_BASE64;
	else if(fl_get_button(att_obj->Att_qprt))
		return CE_QPRT;
	else
		return CE_BASE64;
}

void Att_Type_Choose_Call(FL_OBJECT * obj, long param) {
	char *type;
	int i, enc;

	if(obj == NULL)
		type = (char *) fl_get_input(att_obj->Att_Type);
	else {
		type = (char *) fl_get_menu_text(obj);
		fl_set_input(att_obj->Att_Type, type);
	}
	fl_set_input(att_obj->Att_Subtype, "");
	fl_clear_menu(att_obj->Att_Subtype_Choose);

	i = 0;
	enc = CE_BASE64;
	while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
		if(mailcap[i].subtype_code == CSUBTYPE_DEFAULT) {
			i++;
			continue;
		}

		if(!strcmp(type, mailcap[i].type_text)) {
			if(strlen(fl_get_input(att_obj->Att_Subtype)) < 1) {
				fl_set_input(att_obj->Att_Subtype,
							 mailcap[i].subtype_text);
				enc = mailcap[i].encode;
			}
			fl_addto_menu(att_obj->Att_Subtype_Choose,
						  mailcap[i].subtype_text);
		}
		i++;
	}

	set_encode(enc);

	return;
}

void Att_Subtype_Choose_Call(FL_OBJECT * obj, long param) {
	struct _mime_mailcap *mcap;
	char *subtype, *type;

	subtype = (char *) fl_get_menu_text(obj);
	fl_set_input(att_obj->Att_Subtype, subtype);

	type = (char *) fl_get_input(att_obj->Att_Type);
	if((mcap = find_mailcap(type, subtype, 1)) == NULL)
		return;

	set_encode(mcap->encode);
	discard_mcap(mcap);
	return;
}

void Att_File_Call(FL_OBJECT * obj, long param) {
}

void Att_Descr_Call(FL_OBJECT * obj, long param) {
}

void Att_File_Choose_Call(FL_OBJECT * obj, long param) {
	char *attach;
	char *ext;
	int i;

	fl_set_fselector_title("Choose file to attach");
	attach = (char *) fl_show_fselector("Attach", "", "*", "");
	if(attach)
		fl_set_input(att_obj->Att_File, attach);
	else
		return;

	if((ext = strrchr(attach, '/')) != NULL)
		ext++;
	else
		ext = attach;

	fl_set_input(att_obj->Att_Descr, ext);

	i = 0;
	if((ext = strrchr(ext, '.')) != NULL) {
		ext++;
		if(strlen(ext) <= 4) {
			while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
				if(!strcasecmp(ext, mailcap[i].ext)) {
					fl_set_input(att_obj->Att_Type, mailcap[i].type_text);
					Att_Type_Choose_Call(NULL, 0);
					fl_set_input(att_obj->Att_Subtype,
								 mailcap[i].subtype_text);
					i = -1;
					break;
				}
				i++;
			}

		}
	}

	if(i != -1) {
		i = 0;
		while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
			if((mailcap[i].type_code == CTYPE_APPLICATION) &&
			   (mailcap[i].subtype_code == CSUBTYPE_OSTREAM)) {
				fl_set_input(att_obj->Att_Type, mailcap[i].type_text);
				Att_Type_Choose_Call(NULL, 0);
				break;
			}
			i++;
		}
	}

}

void Att_8bit_Call(FL_OBJECT * obj, long param) {
}

void Att_7bit_Call(FL_OBJECT * obj, long param) {
}

void Att_Base64_Call(FL_OBJECT * obj, long param) {
}

void Att_qprt_Call(FL_OBJECT * obj, long param) {
}


struct _mime_msg *compose_attachment(struct _mime_msg *omime) {
	int i, type_num, chline;
	int enc, mtype, msubtype;
	struct _mime_msg *mime;
	struct _mime_mailcap *mcap;
	char *mfile, *mdescr;
	char *name;
	char buf[255], buf1[127];
	struct stat sb;
	u_int size;

	if(ready) {
		XRaiseWindow(fl_display, att_obj->Attach->window);
		display_msg(MSG_WARN, "Attach",
					"Dialog is currently in use, close it and open again");
		return NULL;
	}

	if(omime) {
		if(omime->mailcap->type_code == CTYPE_MULTIPART) {
			display_msg(MSG_WARN, "Attach",
						"Multipart attachment can not be edited");
			return NULL;
		}

		if(omime->mailcap->type_code == CTYPE_EXTERNAL) {
			display_msg(MSG_WARN, "Attach",
						"External attachment can not be edited");
			return NULL;
		}

		mtype =
		(omime->mailcap->type_code ==
		 CTYPE_UNSUPPORTED) ? CTYPE_APPLICATION : omime->mailcap->
		type_code;
		msubtype =
		(omime->mailcap->subtype_code ==
		 CSUBTYPE_UNSUPPORTED) ? CSUBTYPE_OSTREAM : omime->mailcap->
		subtype_code;
	} else {
		mtype = CTYPE_APPLICATION;
		msubtype = CSUBTYPE_OSTREAM;
	}

	ready = 1;

	att_obj = create_form_Attach();

	fl_deactivate_object(att_obj->Att_Type);
	fl_clear_menu(att_obj->Att_Type_Choose);

	i = 0;
	type_num = 0;
	while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
		if(mailcap[i].type_code == CTYPE_MULTIPART) {
			i++;
			continue;
		}

		if(mailcap[i].type_code == CTYPE_EXTERNAL) {
			i++;
			continue;
		}

		if(mailcap[i].type_code > type_num) {
			if((mailcap[i].type_code == mtype) &&
			   (mailcap[i].subtype_code == msubtype))
				fl_set_input(att_obj->Att_Type, mailcap[i].type_text);

			fl_addto_menu(att_obj->Att_Type_Choose, mailcap[i].type_text);
			type_num = mailcap[i].type_code;
		}

		i++;
	}

	Att_Type_Choose_Call(NULL, 0);
	if(omime) {
		set_encode(omime->encoding->c_trans_enc);
		name = get_mime_fname(omime);
		if(name)
			fl_set_input(att_obj->Att_File, name);

		if(omime->c_descr)
			fl_set_input(att_obj->Att_Descr, omime->c_descr);
		fl_deactivate_object(att_obj->Att_File_Choose);
		fl_deactivate_object(att_obj->Att_7bit);
		fl_deactivate_object(att_obj->Att_8bit);
		fl_deactivate_object(att_obj->Att_Base64);
		fl_deactivate_object(att_obj->Att_qprt);
	} else
		set_encode(CE_BASE64);

	chline = -1;
	i = 0;
	fl_clear_choice(att_obj->Att_Charset);
	while(supp_charsets[i].charset_code != CHAR_UNKNOWN) {
		if(is_charset_alias(supp_charsets[i].charset_name)) {
			i++;
			continue;
		}

		snprintf(buf, sizeof(buf), "%s (%s)",
				 supp_charsets[i].charset_name,
				 supp_charsets[i].charset_descr);
		fl_addto_choice(att_obj->Att_Charset, buf);
		if(def_charset == i)
			chline = fl_get_choice_maxitems(att_obj->Att_Charset);
		i++;
	}

	if(chline == -1) {
		def_charset = DEFAULT_CHARSET;
		fl_set_choice(att_obj->Att_Charset, 1);
	} else
		fl_set_choice(att_obj->Att_Charset, chline);

	again:
	fl_show_form(att_obj->Attach, FL_PLACE_CENTER, FL_TRANSIENT,
				 omime ? "Edit attachment" : "New attachment");

	mime = NULL;

	if(fl_do_only_forms() == att_obj->Att_Cancel)
		goto end;

	if(omime) {
		mime = omime;
		enc = mime->encoding->c_trans_enc;
	} else {
		enc = get_encode();
		if((mime = create_mime()) == NULL) {
			display_msg(MSG_WARN, "MIME", "Can not create new attachment");
			goto end;
		}
	}

	if((mcap = find_mailcap((char *) fl_get_input(att_obj->Att_Type),
					(char *) fl_get_input(att_obj->Att_Subtype),
					1)) == NULL) {
		display_msg(MSG_WARN, "MIME", "Unknown MIME type");
		if(!omime)
			discard_mime(mime);
		mime = NULL;
		goto end;
	}

	mime->mailcap = mcap;
	mime->encoding = &supp_encodings[enc];

	/*
	 if (enc != mcap->encode) {
		if (!display_msg(MSG_QUEST||MSG_DEFNO, "This type of encoding is not recommended for", "%s/%s, continue?", mcap->type_text, mcap->subtype_text)) {
		if (!omime)
			discard_mime(mime);
		mime = NULL;
		goto again; }
				}
	*/


	i = 0;
	chline = 0;
	while(supp_charsets[i].charset_code != CHAR_UNKNOWN) {
		if(is_charset_alias(supp_charsets[i].charset_name)) {
			i++;
			continue;
		}

		chline++;
		if(chline == fl_get_choice(att_obj->Att_Charset)) {
			mime->charset = &supp_charsets[i];
			break;
		}
		i++;
	}


	mfile = (char *) fl_get_input(att_obj->Att_File);
	if(!omime && (strlen(mfile) < 1)) {
		display_msg(MSG_WARN, "MIME", "Must specify filename");
		if(!omime)
			discard_mime(mime);
		mime = NULL;
		goto again;
	}

	if(omime == NULL) {
		if(stat(mfile, &sb) == -1) {
			display_msg(MSG_WARN, "MIME", "Can not access %s", mfile);
			discard_mime(mime);
			mime = NULL;
			goto again;
		}

		size = (u_int) sb.st_size;
		mime->src_info = strdup(mfile);

		if((name = strrchr(mfile, '/')) != NULL)
			name++;
		else
			name = mfile;
	} else {
		size = get_mime_fsize(mime);
		if(strlen(mfile) < 1) {
			name = NULL;
			size = 0;
		} else {
			if((name = strrchr(mfile, '/')) != NULL)
				name++;
			else
				name = mfile;
		}
	}

	mime->flags = ATTACHMENT;

	if(name) {
		snprintf(buf, sizeof(buf), "attachment; filename=\"%s\"", name);
	} else
		sprintf(buf, "attachment");

	replace_mime_field(mime, MIME_C_DISP, buf);

	replace_mime_field(mime, MIME_C_ENCR,
					   supp_encodings[enc].encoding_name);

	mdescr = (char *) fl_get_input(att_obj->Att_Descr);
	if((strlen(mdescr) > 1) && (strlen(mdescr) < 64)) {
		if(mime->c_descr)
			free(mime->c_descr);
		mime->c_descr = strdup(mdescr);
		replace_mime_field(mime, MIME_C_DESCR, mime->c_descr);
	}

	if(size > 0)
		snprintf(buf1, sizeof(buf1), "; SizeOnDisk=%d", size);
	else
		*buf = '\0';

	if(name) {
		if(mime->mailcap->type_code == CTYPE_TEXT)
			snprintf(buf, sizeof(buf), "%s/%s; charset=%s; name=%s%s",
					 mime->mailcap->type_text, mime->mailcap->subtype_text,
					 mime->charset->charset_name, name, buf1);
		else
			snprintf(buf, sizeof(buf), "%s/%s; name=%s%s",
					 mime->mailcap->type_text, mime->mailcap->subtype_text,
					 name, buf1);
	} else {
		if(mime->mailcap->type_code == CTYPE_TEXT)
			snprintf(buf, sizeof(buf), "%s/%s; charset=%s",
					 mime->mailcap->type_text, mime->mailcap->subtype_text,
					 mime->charset->charset_name);
		else
			snprintf(buf, sizeof(buf), "%s/%s", mime->mailcap->type_text,
					 mime->mailcap->subtype_text);
	}

	replace_mime_field(mime, MIME_C_TYPE, buf);

	end:fl_hide_form(att_obj->Attach);
	fl_free_form(att_obj->Attach);
	fl_free(att_obj);
	att_obj = NULL;

	ready = 0;
	return mime;
}

void display_mailcap() {
	char buf[255];
	char mtype[34];
	char mview[128];
	int i = 0;
	int s = 1, t = 1;

	fl_freeze_form(mime_obj->config_mime);
	if(fl_get_browser_maxline(mime_obj->MIME_Disp)) {
		t = fl_get_browser_topline(mime_obj->MIME_Disp);
		s = fl_get_browser(mime_obj->MIME_Disp);
	}

	fl_clear_browser(mime_obj->MIME_Disp);
	while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {

		snprintf(mtype, sizeof(mtype), "%s/%s", mailcap[i].type_text,
				 mailcap[i].subtype_text);
		strcpy(mview, "[none]");
		if(mailcap[i].process)
			strcpy(mview, "[internal]");
		else if(mailcap[i].ext_mcap)
			strncpy(mview, mailcap[i].ext_mcap, 96);
		else if(mailcap[i].view)
			strcpy(mview, "[internal]");

		mview[96] = '\0';

		if(mailcap[i].type_code == CTYPE_EXTERNAL)
			snprintf(buf, sizeof(buf), "@C4%-22.22s %-4.4s %s", mtype,
					 mailcap[i].ext, mview);
		else
			snprintf(buf, sizeof(buf), "%-22.22s %-4.4s %s", mtype,
					 mailcap[i].ext, mview);

		fl_add_browser_line(mime_obj->MIME_Disp, buf);
		i++;
	}

	if(s > fl_get_browser_maxline(mime_obj->MIME_Disp))
		s = fl_get_browser_maxline(mime_obj->MIME_Disp);
	fl_set_browser_topline(mime_obj->MIME_Disp, t);
	fl_select_browser_line(mime_obj->MIME_Disp, s);
	MIME_Disp_Call(NULL, s);
	fl_unfreeze_form(mime_obj->config_mime);
}

struct _mime_mailcap *get_mcap_by_num(int num) {
	int i;

	i = 0;
	while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
		i++;
		if(i == num)
			return &mailcap[i - 1];
	}

	return NULL;
}

void MIME_Disp_Call(FL_OBJECT * obj, long param) {
	int n;
	struct _mime_mailcap *mcap;

	if(obj)
		n = fl_get_browser(obj);
	else
		n = param;

	if((mcap = get_mcap_by_num(n)) == NULL)
		return;

	fl_set_input(mime_obj->MIME_Type, mcap->type_text);
	fl_set_input(mime_obj->MIME_Subtype, mcap->subtype_text);
	fl_set_input(mime_obj->MIME_Ext, mcap->ext);
	fl_set_input(mime_obj->MIME_Command,
				 mcap->ext_mcap ? mcap->ext_mcap : "");
}

void MIME_Type_Call(FL_OBJECT * obj, long param) {
}

void MIME_Subtype_Call(FL_OBJECT * obj, long param) {
}

void MIME_Ext_Call(FL_OBJECT * obj, long param) {
}

void MIME_Command_Call(FL_OBJECT * obj, long param) {
}

void MIME_Add_Call(FL_OBJECT * obj, long param) {
	char *type, *subtype, *ext, *command;
	struct _mime_mailcap *mcap;

	type = (char *) fl_get_input(mime_obj->MIME_Type);
	subtype = (char *) fl_get_input(mime_obj->MIME_Subtype);
	ext = (char *) fl_get_input(mime_obj->MIME_Ext);
	command = (char *) fl_get_input(mime_obj->MIME_Command);

	if((strlen(type) < 1) || (strlen(type) > 16)) {
		display_msg(MSG_WARN, "MIME", "Invalid MIME type");
		return;
	}

	if((strlen(subtype) < 1) || (strlen(subtype) > 16)) {
		display_msg(MSG_WARN, "MIME", "Invalid MIME subtype");
		return;
	}

	if(strlen(ext) > 4) {
		display_msg(MSG_WARN, "MIME",
					"Extension can not be longer then 4 characters");
		return;
	}

	if(strlen(command) < 1)
		command = NULL;

	if((mcap = find_mailcap(type, subtype, 1)) == NULL)
		return;

	if(mcap->process) {
		discard_mcap(mcap);
		return;
	}

	if(mcap->ext_mcap)
		free(mcap->ext_mcap);

	strcpy(mcap->ext, ext);

	if(command)
		mcap->ext_mcap = strdup(command);
	else
		mcap->ext_mcap = NULL;

	add_mailcap(mcap);
	discard_mcap(mcap);
	display_mailcap();
}

void MIME_Delete_Call(FL_OBJECT * obj, long param) {
	struct _mime_mailcap *mcap;
	int n;

	n = fl_get_browser(mime_obj->MIME_Disp);

	if((mcap = get_mcap_by_num(n)) == NULL)
		return;

	if(mcap->ext_mcap) {
		free(mcap->ext_mcap);
		mcap->ext_mcap = NULL;
	}

	if(mcap->type_code != CTYPE_EXTERNAL) {
		display_mailcap();
		return;
	}

	n--;
	while(mailcap[n].type_code != CTYPE_UNSUPPORTED) {
		if(mailcap[n].ext_mcap)
			free(mailcap[n].ext_mcap);

		memcpy(&mailcap[n], &mailcap[n + 1], sizeof(struct _mime_mailcap));

		mailcap[n + 1].ext_mcap = NULL;

		n++;
	}

	display_mailcap();
}

void MIME_Save_Call(FL_OBJECT * obj, long param) {
	save_mailcap();
}

void mime_conf(FD_config_mime * form) {
	mime_obj = form;
	fl_set_browser_fontstyle(mime_obj->MIME_Disp, FL_FIXED_STYLE);
	fl_set_browser_fontsize(mime_obj->MIME_Disp, FL_NORMAL_SIZE);
	fl_clear_browser(mime_obj->MIME_Disp);

	display_mailcap();
}

void MCAP_Browse_DCall(FL_OBJECT * obj, long param) {
	fl_trigger_object(mcap_obj->MCAP_Ok);
}

void MCAP_Browse_Call(FL_OBJECT * obj, long param) {
	if(fl_mouse_button() == FL_MIDDLE_MOUSE)
		fl_trigger_object(mcap_obj->MCAP_Ok);
}

void MCAP_Exec_Call(FL_OBJECT * obj, long param) {
}

struct _mime_mailcap *mcap_select(char *mtype, char *msubtype) {
	struct _mime_mailcap *mc = NULL;
	char buf[96], *exc;
	int i = 0, sel = 1;

	if(!mtype)
		return NULL;

	if(ready) {
		XRaiseWindow(fl_display, mcap_obj->mcap->window);
		display_msg(MSG_WARN, "Select viewer",
					"Dialog is currently in use, close it and open again");
		return NULL;
	}

	mcap_obj = create_form_mcap();
	ready = 1;

	fl_set_browser_dblclick_callback(mcap_obj->MCAP_Browse,
									 MCAP_Browse_DCall, 0);

	fl_freeze_form(mcap_obj->mcap);
	fl_clear_browser(mcap_obj->MCAP_Browse);
	while(mailcap[i].type_code != CTYPE_UNSUPPORTED) {
		if(mailcap[i].process ||
		   (!mailcap[i].view && !mailcap[i].ext_mcap))
			snprintf(buf, sizeof(buf), "@N%s/%s", mailcap[i].type_text,
					 mailcap[i].subtype_text);
		else
			snprintf(buf, sizeof(buf), "%s/%s", mailcap[i].type_text,
					 mailcap[i].subtype_text);

		if(mailcap[i].type_code == CTYPE_DEFAULT)
			sel = i + 1;

		fl_add_browser_line(mcap_obj->MCAP_Browse, buf);
		i++;
	}

	fl_select_browser_line(mcap_obj->MCAP_Browse, sel);
	fl_unfreeze_form(mcap_obj->mcap);

	snprintf(buf, sizeof(buf), "View %s/%s as:", mtype,
			 msubtype ? msubtype : "*");
	fl_set_object_label(mcap_obj->MCAP_Title, buf);
	snprintf(buf, sizeof(buf), "%s/%s", mtype, msubtype ? msubtype : "*");
	fl_show_form(mcap_obj->mcap, FL_PLACE_CENTER, FL_TRANSIENT, buf);

	if(fl_do_only_forms() == mcap_obj->MCAP_Cancel)
		goto mcap_end;

	exc = (char *) fl_get_input(mcap_obj->MCAP_Exec);
	if(exc && *exc) {
		if((mc = find_mailcap(mtype, msubtype, 1)) != NULL) {
			if(mc->ext_mcap)
				free(mc->ext_mcap);
			mc->ext_mcap = strdup(exc);
		}
	} else
		mc = get_mcap_by_num(fl_get_browser(mcap_obj->MCAP_Browse));

	mcap_end:
	fl_hide_form(mcap_obj->mcap);
	fl_free_form(mcap_obj->mcap);
	fl_free(mcap_obj);
	mcap_obj = NULL;

	ready = 0;
	return mc;
}


int save_part(struct _mail_msg *msg, struct _mime_msg *mime, char *file, u_int flags) {
	static int mimefcnt = 0;
	FILE *mfd, *sfd;
	struct _head_field *fld;
	struct stat sb;
	char buf[255];
	char file1[255];
	int i = 0;
	char *p = NULL;
	fn_decode save_mime_encoding = dumb_decode;

	if(!msg || !mime)
		return -1;

	p = NULL;
	if((fld = find_mime_field(mime, MIME_C_TYPE)) != NULL)
		p = get_fld_param(fld, "name");

	if(p == NULL) {
		if((fld = find_mime_field(mime, MIME_C_DISP)) != NULL)
			p = get_fld_param(fld, "filename");
	}

	fl_set_fselector_title("Save part as");
	if(flags & SAVEPART_CHFILE) {
		if(p == NULL) {
			snprintf(file1, sizeof(file1), "mime%d.%s", mimefcnt++,
					 (strlen(mime->mailcap->ext) >=
					  1) ? mime->mailcap->ext : "txt");
			file =
			(char *) fl_show_fselector("Save as", file ? file : "", "",
									   file1);
			if(!file || !*file)
				return 0;
		} else {
			if(strrchr(p, '/')) {
				p = strrchr(p, '/');
				p++;
			}
			if(file) {
				snprintf(file1, sizeof(file1), "%s/%s", file, p);
				file = file1;
			} else
				file = p;
		}
	}

	if(!file) {
		if(p == NULL) {
			snprintf(file1, sizeof(file1), "mime%d.%s", mimefcnt++,
					 (strlen(mime->mailcap->ext) >=
					  1) ? mime->mailcap->ext : "txt");
			p = file1;
		}

		file = (char *) fl_show_fselector("Save as", "", "", p ? p : "");
		if(!file || !*file)
			return 0;

	}

	if(!(flags & SAVEPART_APPEND) && (stat(file, &sb) != -1)) {
		if(!display_msg
		   (MSG_QUEST | MSG_DEFNO, "Save",
			"%s already exists, overwrite?", file))
			return -1;
		unlink(file);
	}

	if((sfd = fopen(file, (flags & SAVEPART_APPEND) ? "a" : "w")) == NULL) {
		display_msg(MSG_WARN, "MIME", "Can not open %s", file);
		return -1;
	}

	if((mfd = fopen(msg->get_file(msg), "r")) == NULL) {
		display_msg(MSG_WARN, "MIME", "Can not open %s",
					msg->get_file(msg));
		fclose(sfd);
		return -1;
	}

	if(flags & SAVEPART_HEADER) {
		if(mime->boundary) {
			fseek(mfd, mime->m_start, SEEK_SET);
			fgets(buf, 255, mfd);
			while(fgets(buf, 255, mfd)) {
				strip_newline(buf);
				if(*buf)
					fputs(buf, sfd);
				if(flags & SAVEPART_CRLF)
					fputs("\r\n", sfd);
				else
					fputs("\n", sfd);
				if(!*buf)
					break;
			}
		} else
			print_message_header(msg, sfd);
	} else if(flags & SAVEPART_FHDR) {
		print_mime_msg_header(mime, msg, sfd);
		fputc('\n', sfd);
	}

	if(mime->boundary) {
		fseek(mfd, mime->m_start, SEEK_SET);
		while(fgets(buf, 255, mfd)) {
			strip_newline(buf);
			if(strlen(buf) < 1)
				break;
		}
	} else
		fseek(mfd, msg->header->header_len, SEEK_SET);

	if(ferror(mfd) || feof(mfd)) {
		display_msg(MSG_WARN, "MIME", "Can not read from %s",
					msg->get_file(msg));
		fclose(mfd);
		fclose(sfd);
		return -1;
	}
	/* Hack ! */
	if(flags & SAVEPART_RAW) {
		save_mime_encoding = mime->encoding->ce_dec;
		mime->encoding->ce_dec = dumb_decode;
	}

	(*mime->encoding->ce_dec) (NULL, &i);
	while((ftell(mfd) < mime->m_end) && fgets(buf, 255, mfd)) {
		if((p = (*mime->encoding->ce_dec) (buf, &i)) == NULL)
			continue;

		if(i == 0)
			continue;

		if(flags & SAVEPART_CRLF) {
			fflush(sfd);
			if((p[i - 1] == '\n') && ((i == 1) || (p[i - 2] != '\r'))) {
				i--;
				if(i > 0) {
					if(fwrite(p, i, 1, sfd) != 1) {
						display_msg(MSG_WARN, "MIME",
									"Can not write to %s", file);
						fclose(mfd);
						fclose(sfd);
						if(flags & SAVEPART_RAW)
							mime->encoding->ce_dec = save_mime_encoding;
						return -1;
					}
				}
				fflush(sfd);
				fputs("\r\n", sfd);
				fflush(sfd);
				continue;
			}
		}

		if(fwrite(p, i, 1, sfd) != 1) {
			display_msg(MSG_WARN, "MIME", "Can not write to %s", file);
			fclose(mfd);
			fclose(sfd);
			if(flags & SAVEPART_RAW)
				mime->encoding->ce_dec = save_mime_encoding;
			return -1;
		}
	}

	p = (*mime->encoding->ce_dec) (NULL, &i);
	if(p && (strlen(p) > 1))
		fwrite(p, i, 1, sfd);

	fclose(mfd);
	fclose(sfd);
	if(flags & SAVEPART_RAW)
		mime->encoding->ce_dec = save_mime_encoding;

	return 0;
}
