コード例 #1
0
ファイル: addr_compl.c プロジェクト: twolife/claws
/**
 * Read address book, creating all entries in the completion index.
 */ 
static void read_address_book(gchar *folderpath) {
	free_all_addresses();
	free_completion_list();

#ifndef USE_ALT_ADDRBOOK
	addrindex_load_completion( add_address, folderpath );
#else
	GError* error = NULL;
	
	addrcompl_initialize();
	if (! addrindex_dbus_load_completion(add_address, &error)) {
		g_warning("Failed to populate address completion list");
        g_error_free(error);
		return;
	}
#endif
	/* plugins may hook in here to modify/extend the completion list */
	if(!folderpath) {
		hooks_invoke(ADDDRESS_COMPLETION_BUILD_ADDRESS_LIST_HOOKLIST, &g_address_list);
	}

	g_address_list = g_list_reverse(g_address_list);
	g_completion_list = g_list_reverse(g_completion_list);
	/* merge the completion entry list into g_completion */
	if (g_completion_list) {
		g_completion_add_items(g_completion, g_completion_list);
		if (debug_get_mode())
			debug_print("read %d items in %s\n",
				g_list_length(g_completion_list),
				folderpath?folderpath:"(null)");
	}
}
コード例 #2
0
ファイル: log.c プロジェクト: Mortal/claws
void log_status_skip(LogInstance instance, const gchar *format, ...)
{
	va_list args;
	gchar buf[BUFFSIZE + LOG_TIME_LEN];
	time_t t;
	LogText *logtext = g_new0(LogText, 1);
	struct tm buft;

	time(&t);
	strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));

	va_start(args, format);
	g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
	va_end(args);

	if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);

	logtext->instance = instance;
	logtext->text = g_strdup(buf + LOG_TIME_LEN);
	logtext->type = LOG_STATUS_SKIP;
	
	g_timeout_add(0, invoke_hook_cb, logtext);

	if (log_fp[instance] && prefs_common_enable_log_status()) {
		FWRITE(buf, 1, LOG_TIME_LEN, log_fp[instance])
		FPUTS("* SKIPPED: ", log_fp[instance])
		log_size[instance] += strlen("* SKIPPED: ");
		FPUTS(buf + LOG_TIME_LEN, log_fp[instance])
		log_size[instance] += strlen(buf);
		FFLUSH(log_fp[instance])
		rotate_log(instance);
	}
}
コード例 #3
0
ファイル: ldapupdate.c プロジェクト: twolife/claws
/**
 * Print contents of contacts hashtable for debug.
 * This function must be called with g_hash_table_foreach.
 * \param key Key to process.
 * \param data Data to process.
 * \param fd Output stream.
 */
void ldapsvr_print_contacts_hashtable(gpointer key, gpointer data, gpointer fd) {
	gchar *keyName = (gchar *) key;
	GList *node;

	if (g_ascii_strcasecmp("mail", keyName) == 0) {
		node = (GList *) data;
		while (node) {
			EmailKeyValue *item = node->data;
			if (debug_get_mode()) {
				debug_print("\t\talias = %s\n", item->alias?item->alias:"null");
				debug_print("\t\tmail = %s\n", item->mail?item->mail:"null");
				debug_print("\t\tremarks = %s\n", item->remarks?item->remarks:"null");
			}
			else if (fd) {
				FILE *stream = (FILE *) fd;
				fprintf(stream, "\t\talias = %s\n", item->alias?item->alias:"null");
				fprintf(stream, "\t\tmail = %s\n", item->mail?item->mail:"null");
				fprintf(stream, "\t\tremarks = %s\n", item->remarks?item->remarks:"null");
			}
			node = g_list_next(node);
		}
	}
	else if (g_ascii_strcasecmp("attribute", keyName) == 0) {
		node = (GList *) data;
		while (node) {
			AttrKeyValue *item = node->data;
			if (debug_get_mode()) {
				debug_print("\t\t%s = %s\n", item->key?item->key:"null",
						item->value?item->value:"null");
			}
			else if (fd) {
				FILE *stream = (FILE *) fd;
				fprintf(stream, "\t\t%s = %s\n", item->key?item->key:"null",
						item->value?item->value:"null");
			}
			node = g_list_next(node);
		}
	}
	else {
		if (debug_get_mode())
			debug_print("\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
		else if (fd) {
			FILE *stream = (FILE *) fd;
			fprintf(stream, "\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
		}
	}
}
コード例 #4
0
ファイル: ldapquery.c プロジェクト: kuba-moo/claws-mail
/**
 * Connect to LDAP server.
 * \param  qry Query object to process.
 * \return Error/status code.
 */
static gint ldapqry_connect( LdapQuery *qry ) {
	LdapControl *ctl;
	LDAP *ld = NULL;

	/* Initialize connection */
	if (debug_get_mode()) {
		debug_print("===ldapqry_connect===\n");
		/*ldapqry_print(qry, stdout);*/
	}
	ctl = qry->control;
	/*if (debug_get_mode()) {
		ldapctl_print(ctl, stdout);
		debug_print("======\n");
	}*/
	ldapqry_touch( qry );
	qry->startTime = qry->touchTime;
	qry->elapsedTime = -1;
	ADDRQUERY_RETVAL(qry) = LDAPRC_INIT;

	ld = ldapsvr_connect(ctl);

	if (ld == NULL)
		return ADDRQUERY_RETVAL(qry);

	qry->ldap = ld;
	ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
	if( ldapqry_get_stop_flag( qry ) ) {
		return ADDRQUERY_RETVAL(qry);
	}
	ldapqry_touch( qry );

	debug_print("connected to LDAP host %s on port %d\n",
			ctl->hostName?ctl->hostName:"null", ctl->port);

	ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
	if( ldapqry_get_stop_flag( qry ) ) {
		return ADDRQUERY_RETVAL(qry);
	}
	ldapqry_touch( qry );

	ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS;

	return ADDRQUERY_RETVAL(qry);
}
コード例 #5
0
ファイル: xml.c プロジェクト: eworm-de/claws-mail
GNode *xml_parse_file(const gchar *path)
{
	XMLFile *file;
	GNode *node;

	file = xml_open_file(path);
	if (file == NULL)
		return NULL;

	xml_get_dtd(file);

	node = xml_build_tree(file, NULL, file->level);

	xml_close_file(file);

#if defined(SPARSE_MEMORY)
	if (debug_get_mode())
		string_table_get_stats(xml_string_table);
#endif

	return node;
}
コード例 #6
0
ファイル: html.c プロジェクト: eworm-de/claws-mail
static SC_HTMLTag *sc_html_get_tag(const gchar *str)
{
	SC_HTMLTag *tag;
	gchar *tmp;
	guchar *tmpp;

	cm_return_val_if_fail(str != NULL, NULL);

	if (*str == '\0' || *str == '!') return NULL;

	Xstrdup_a(tmp, str, return NULL);

	tag = g_new0(SC_HTMLTag, 1);

	for (tmpp = tmp; *tmpp != '\0' && !g_ascii_isspace(*tmpp); tmpp++)
		;

	if (*tmpp == '\0') {
		tag->name = g_utf8_strdown(tmp, -1);
		return tag;
	} else {
		*tmpp++ = '\0';
		tag->name = g_utf8_strdown(tmp, -1);
	}

	while (*tmpp != '\0') {
		SC_HTMLAttr *attr;
		gchar *attr_name;
		gchar *attr_value;
		gchar *p;
		gchar quote;

		while (g_ascii_isspace(*tmpp)) tmpp++;
		attr_name = tmpp;

		while (*tmpp != '\0' && !g_ascii_isspace(*tmpp) &&
		       *tmpp != '=')
			tmpp++;
		if (*tmpp != '\0' && *tmpp != '=') {
			*tmpp++ = '\0';
			while (g_ascii_isspace(*tmpp)) tmpp++;
		}

		if (*tmpp == '=') {
			*tmpp++ = '\0';
			while (g_ascii_isspace(*tmpp)) tmpp++;

			if (*tmpp == '"' || *tmpp == '\'') {
				/* name="value" */
				quote = *tmpp;
				tmpp++;
				attr_value = tmpp;
				if ((p = strchr(attr_value, quote)) == NULL) {
					if (debug_get_mode()) {
						g_warning("sc_html_get_tag(): syntax error in tag: '%s'",
								  str);
					} else {
						gchar *cut = g_strndup(str, 100);
						g_warning("sc_html_get_tag(): syntax error in tag: '%s%s'",
								  cut, strlen(str)>100?"...":".");
						g_free(cut);
					}
					return tag;
				}
				tmpp = p;
				*tmpp++ = '\0';
				while (g_ascii_isspace(*tmpp)) tmpp++;
			} else {
				/* name=value */
				attr_value = tmpp;
				while (*tmpp != '\0' && !g_ascii_isspace(*tmpp)) tmpp++;
				if (*tmpp != '\0')
					*tmpp++ = '\0';
			}
		} else
			attr_value = "";

		g_strchomp(attr_name);
		attr = g_new(SC_HTMLAttr, 1);
		attr->name = g_utf8_strdown(attr_name, -1);
		attr->value = g_strdup(attr_value);
		tag->attr = g_list_append(tag->attr, attr);
	}

	return tag;
}
コード例 #7
0
ファイル: ldapupdate.c プロジェクト: twolife/claws
/**
 * Add new contact to LDAP
 *
 * \param server AddressBook resource
 * \param contact GHashTable with object to add
 */
void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
	gchar *email = NULL, *param = NULL;
	LDAP *ld = NULL;
	LDAPMod *mods[MODSIZE];
	LDAPMod modarr[7];
	gint cnt = 0;
	char *cn[] = {NULL, NULL};
	char *displayName[] = {NULL, NULL};
	char *givenName[] = {NULL, NULL};
	char **mail = NULL;
	char *sn[] = {NULL, NULL};
	char *org[] = {NULL, NULL};
	char *obj[] = {/*"top",*/ "person", "organizationalPerson", "inetOrgPerson", NULL}; 
	int rc=0;
	GList *node;
	AttrKeyValue *ou, *commonName;
	ItemPerson *person;
	gchar *base_dn;
	GList *mailList;

	cm_return_if_fail(server != NULL || contact != NULL);
	node = g_hash_table_lookup(contact , "mail");
	if (node) {
		EmailKeyValue *newEmail = node->data;
		email = g_strdup(newEmail->mail);
	}
	if (email == NULL) {
		server->retVal = LDAPRC_NODN;
		clean_up(ld, server, contact);
		return;
	}
	base_dn = g_strdup_printf("mail=%s,%s",
			email, server->control->baseDN?server->control->baseDN:"null");
	g_free(email);
	person = 
		ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
	person->externalID = g_strdup(base_dn);
	debug_print("dn: %s\n", base_dn);
	ld = ldapsvr_connect(server->control);
	if (ld == NULL) {
		clean_up(ld, server, contact);
		debug_print("no ldap found\n");
		return;
	}
	SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "objectClass", obj);
	cnt++;
	ou = get_ou(base_dn);
	if (ou != NULL) {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(ou->key), org, g_strdup(ou->value));
		cnt++;
		attrkeyvalue_free(ou);
	}
	
	commonName = get_cn(base_dn);
	if (commonName == NULL) {
		param = g_hash_table_lookup(contact , "cn");
		if (param) {
			SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, param);
		}
		else {
			clean_up(ld, server, contact);
			debug_print("no CN found\n");
			return;
		}
	}
	else {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(commonName->key), cn, g_strdup(commonName->value));
		cnt++;
		param = g_hash_table_lookup(contact , "cn");
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "displayName", displayName, param);
		g_hash_table_insert(contact, "displayName", param);
		attrkeyvalue_free(commonName);
	}
	cnt++;
	param = g_hash_table_lookup(contact , "givenName");
	if (param) {
		SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", givenName, param);
		cnt++;
	}
	mailList = g_hash_table_lookup(contact , "mail");
	if (mailList) {
		char **tmp;
		tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1));
		mail = tmp;
		while (mailList) {
			EmailKeyValue *item = mailList->data;
			*tmp++ = g_strdup((gchar *) item->mail);
			mailList = g_list_next(mailList);
		}
		*tmp = NULL;
		SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail);
		cnt++;
	}
	param = g_hash_table_lookup(contact, "sn");
	if (param == NULL)
		param = g_strdup(N_("Some SN"));
	SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, param);
	cnt++;
	mods[cnt] = NULL;
	if (debug_get_mode()) {
		ldapsvr_print_ldapmod(mods);
	}
	server->retVal = LDAPRC_SUCCESS;
	rc = ldap_add_ext_s(ld, base_dn, mods, NULL, NULL);
	if (rc) {
		switch (rc) {
			case LDAP_ALREADY_EXISTS: 
				server->retVal = LDAPRC_ALREADY_EXIST;
				break;
			default:
				g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
						base_dn, rc, ldaputil_get_error(ld));
				if (rc == 0x8)
					server->retVal = LDAPRC_STRONG_AUTH;
				else
					server->retVal = LDAPRC_NAMING_VIOLATION;
		}
	}
	ldapsvr_handle_other_attributes(ld, server, base_dn, contact);
	g_free(base_dn);
	clean_up(ld, server, contact);
}
コード例 #8
0
ファイル: ldapupdate.c プロジェクト: twolife/claws
/**
 * Deside which other attributes needs updating
 *
 * \param ld LDAP resource
 * \param server AddressBook resource
 * \param dn dn for the entry
 * \param contact GHashTable with information for the current contact
 */
void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHashTable *contact) {
	GList *node;
	gboolean CHECKED_ATTRIBUTE[ATTRIBUTE_SIZE + 1];
	LDAPMod *mods[ATTRIBUTE_SIZE + 1];
	LDAPMod modarr[ATTRIBUTE_SIZE];
	gint cnt = 0;
	char *attr[ATTRIBUTE_SIZE + 1][2];
	int mod_op, rc, i;

	cm_return_if_fail(server != NULL || dn != NULL || contact != NULL);
	for (i = 0; i <= ATTRIBUTE_SIZE; i++) {
		CHECKED_ATTRIBUTE[i] = FALSE;
		attr[i][0] = attr[i][1] = NULL;
	}
	node = g_hash_table_lookup(contact , "attribute");
	while (node) {
		AttrKeyValue *item = node->data;
		if (item) {
			int index = get_attribute_index(item->key);
			if (index >= 0) {
				debug_print("Found other attribute: %s = %s\n",
						item->key?item->key:"null", item->value?item->value:"null");
				mod_op = ldapsvr_deside_operation(ld, server, dn, item->key, item->value);
				/* Only consider attributes which we no how to handle.
				 * Set to TRUE in CHECKED_ATTRIBUTE array to indicate no further action
				 */
				if (mod_op < 0) {
					CHECKED_ATTRIBUTE[index] = TRUE;
					node = g_list_next(node);
					continue;
				}
				if (mod_op == LDAP_MOD_DELETE) {
					/* Setting param to NULL instructs OpenLDAP to remove any
			 		* value stored for this attribute and remove the attribute
			 		* completely. Should multiple instances of an attribute be
			 		* allowed in the future param is required to have the value
			 		* store for the attribute which is going to be deleted
			 		*/
					item->value = NULL;
				}
				if (mod_op == LDAP_MOD_REPLACE && strcmp(item->value, "") == 0) {
					/* Having an empty string is considered a syntax error in
			 		* ldap. E.g attributes with empty strings are not allowed
			 		* in which case we treate this as a request for deleting
			 		* the attribute.
			 		*/
					mod_op = LDAP_MOD_DELETE;
					item->value = NULL;
				}
				if (mod_op == LDAP_MOD_ADD && strcmp(item->value, "") == 0) {
					/* Adding an empty string is considered a syntax error in
			 		* ldap. E.g attributes with empty strings are not allowed
			 		* in which case we silently refuse to add this entry
			 		*/
				}
				else {
					SETMOD(mods[cnt], modarr[cnt], mod_op, g_strdup(item->key), attr[cnt], g_strdup(item->value));
					cnt++;
					CHECKED_ATTRIBUTE[index] = TRUE;
				}
			}
		}
		node = g_list_next(node);
	}
	char **attribs = ldapctl_full_attribute_array(server->control);
	for (i = 0; i < ATTRIBUTE_SIZE; i++) {
		/* Attributes which holds no information are to be removed */
		if (CHECKED_ATTRIBUTE[i] == FALSE) {
			/* Only consider those attributes which is currently part of the search criteria.
			 * If attributes are not part of the search criteria they would seem to hold
			 * no information since their values will not be populated in the GUI
			 */
			if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
				debug_print("not updating jpegPhoto\n");
				continue;
			}
			if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
				mod_op = ldapsvr_deside_operation(ld, server, dn, (char *) ATTRIBUTE[i], "");
				if (mod_op == LDAP_MOD_DELETE) {
					SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_DELETE, g_strdup((char *) ATTRIBUTE[i]), attr[cnt], NULL);
					cnt++;
				}
			}
		}
	}
	ldapctl_free_attribute_array(attribs);
	mods[cnt] = NULL;
	if (debug_get_mode())
		ldapsvr_print_ldapmod(mods);
	server->retVal = LDAPRC_SUCCESS;
	rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
	if (rc) {
		switch (rc) {
			case LDAP_ALREADY_EXISTS: 
				server->retVal = LDAPRC_ALREADY_EXIST;
				break;
			default:
				g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n", dn, rc, ldaputil_get_error(ld));
				if (rc == 0x8)
					server->retVal = LDAPRC_STRONG_AUTH;
				else
					server->retVal = LDAPRC_NAMING_VIOLATION;
		}
	}
	else {
		char **attribs = ldapctl_full_attribute_array(server->control);
		for (i = 0; i < ATTRIBUTE_SIZE; i++) {
			if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
				debug_print("not updating jpegPhoto\n");
				continue;
			}
			if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
				if (CHECKED_ATTRIBUTE[i] == FALSE) {
					AddrItemObject *aio = addrcache_get_object(server->addressCache, g_hash_table_lookup(contact , "uid"));
					ItemPerson *person = (ItemPerson *) aio;
					addritem_person_remove_attribute(person, (const gchar *) ATTRIBUTE[i]);
				}
			}
		}
		ldapctl_free_attribute_array(attribs);
	}
}
コード例 #9
0
ファイル: ldapupdate.c プロジェクト: twolife/claws
/**
 * Update any changes to the server.
 *
 * \param server AddressBook resource.
 * \param person ItemPerson holding user input.
 */
void ldapsvr_update_book(LdapServer *server, ItemPerson *item) {
	GList *node = NULL;
	GHashTable *contact = NULL;
	GList *contacts = NULL, *head = NULL;

	cm_return_if_fail(server != NULL);
	debug_print("updating ldap addressbook\n");

	contact = g_hash_table_new(g_str_hash, g_str_equal);
	if (item) {
		gboolean result = ldapsvr_retrieve_item_person(item, contact);
		debug_print("Found contact to update: %s\n", result? "Yes" : "No");
		if (result) {
			if (debug_get_mode()) {
				addritem_print_item_person(item, stdout);
			}
			contacts = g_list_append(contacts, contact);
		}
	}
	else {
		ItemFolder *folder = server->addressCache->rootFolder;
		node = folder->listFolder;
		if (node) {
			while (node) {
				AddrItemObject *aio = node->data;
				if (aio) {
					if (aio->type == ITEMTYPE_FOLDER) {
						ItemFolder *folder = (ItemFolder *) aio;
						GList *persons = folder->listPerson;
						while (persons) {
							AddrItemObject *aio = persons->data;
							if (aio) {
								if (aio->type == ITEMTYPE_PERSON) {
									ItemPerson *item = (ItemPerson *) aio;
									gboolean result = ldapsvr_retrieve_item_person(item, contact);
									debug_print("Found contact to update: %s\n", result? "Yes" : "No");
									if (result) {
										if (debug_get_mode()) {
											gchar *uid = g_hash_table_lookup(contact, "uid");
											item = ldapsvr_get_contact(server, uid);
											addritem_print_item_person(item, stdout);
										}
										contacts = g_list_append(contacts, contact);
									}
								}
							}
							persons = g_list_next(persons);
						}
					}
				}
				else {
					g_printerr("\t\tpid : ???\n");
				}
				node = g_list_next(node);
			}
		}
	}
	head = contacts;
	if (debug_get_mode()) {
		if (contacts)
			debug_print("Contacts which must be updated in LDAP:\n");
		while (contacts) {
			debug_print("\tContact:\n");
			g_hash_table_foreach(contacts->data, 
				ldapsvr_print_contacts_hashtable, stderr);
			contacts = g_list_next(contacts);
		}
	}
	if (contacts == NULL)
		contacts = head;
	while (contacts) {
		gchar *status;
		contact = (GHashTable *) contacts->data;
		status = (gchar *) g_hash_table_lookup(contact, "status");
		if (status == NULL)
			status = g_strdup("NULL");
		if (g_ascii_strcasecmp(status, "new") == 0) {
			ldapsvr_add_contact(server, contact);
		}
		else if (g_ascii_strcasecmp(status, "update") == 0) {
			ldapsvr_update_contact(server, contact);
		}
		else if (g_ascii_strcasecmp(status, "delete") == 0) {
			ldapsvr_delete_contact(server, contact);
		}
		else
			g_critical("ldapsvr_update_book->Unknown status: %s\n", status);
		contacts = g_list_next(contacts);
	}
	ldapsvr_free_hashtable(head);
}
コード例 #10
0
ファイル: tnef_parse.c プロジェクト: kuba-moo/claws-mail
static gboolean tnef_parse (MimeParser *parser, MimeInfo *mimeinfo)
{
	TNEFStruct *tnef;
	MimeInfo *sub_info = NULL;
	variableLength *tmp_var;
	Attachment *att;
	int parse_result = 0;
	gboolean cal_done = FALSE;

	if (!procmime_decode_content(mimeinfo)) {
		debug_print("error decoding\n");
		return FALSE;
	}
	debug_print("Tnef parser parsing part (%d).\n", mimeinfo->length);
	if (mimeinfo->content == MIMECONTENT_FILE)
		debug_print("content: %s\n", mimeinfo->data.filename);
	else 
		debug_print("contents in memory (len %zd)\n", 
			strlen(mimeinfo->data.mem));
	
	tnef = g_new0(TNEFStruct, 1);
	TNEFInitialize(tnef);

	tnef->Debug = debug_get_mode();

	if (mimeinfo->content == MIMECONTENT_MEM)
		parse_result = TNEFParseMemory(mimeinfo->data.mem, mimeinfo->length, tnef);
	else
		parse_result = TNEFParseFile(mimeinfo->data.filename, tnef);
	
	mimeinfo->type = MIMETYPE_MULTIPART;
	mimeinfo->subtype = g_strdup("mixed");
	g_hash_table_insert(mimeinfo->typeparameters,
			    g_strdup("description"),
			    g_strdup("Parsed from MS-TNEF"));

	if (parse_result != 0) {
		g_warning("Failed to parse TNEF data.");
		TNEFFree(tnef);
		return FALSE;
	}
	
	sub_info = NULL;
	if (tnef->messageClass[0] != '\0') {
		if (strcmp(tnef->messageClass, "IPM.Contact") == 0)
			sub_info = tnef_parse_vcard(tnef);
		else if (strcmp(tnef->messageClass, "IPM.Task") == 0)
			sub_info = tnef_parse_vtask(tnef);
		else if (strcmp(tnef->messageClass, "IPM.Appointment") == 0) {
			sub_info = tnef_parse_vcal(tnef);
			cal_done = TRUE;
		}
	}

	if (sub_info)
		g_node_append(mimeinfo->node, sub_info->node);
	sub_info = NULL;

	if (tnef->MapiProperties.count > 0) {
		tmp_var = MAPIFindProperty (&(tnef->MapiProperties), PROP_TAG(PT_BINARY,PR_RTF_COMPRESSED));
		if (tmp_var != MAPI_UNDEFINED) {
			sub_info = tnef_parse_rtf(tnef, tmp_var);
		}
	}

	if (sub_info)
		g_node_append(mimeinfo->node, sub_info->node);
	sub_info = NULL;

	tmp_var = MAPIFindUserProp(&(tnef->MapiProperties), PROP_TAG(PT_STRING8,0x24));
	if (tmp_var != MAPI_UNDEFINED) {
		if (!cal_done && strcmp(tmp_var->data, "IPM.Appointment") == 0) {
			sub_info = tnef_parse_vcal(tnef);
		}
	}
	
	if (sub_info)
		g_node_append(mimeinfo->node, sub_info->node);
	sub_info = NULL;

	att = tnef->starting_attach.next;
	while (att) {
		gchar *filename = NULL;
		gboolean is_object = TRUE;
		DWORD signature;

		tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(30,0x3707));
		if (tmp_var == MAPI_UNDEFINED)
			tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(30,0x3001));
		if (tmp_var == MAPI_UNDEFINED)
			tmp_var = &(att->Title);

		if (tmp_var->data)
			filename = g_strdup(tmp_var->data);
		
		tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(PT_OBJECT, PR_ATTACH_DATA_OBJ));
		if (tmp_var == MAPI_UNDEFINED)
			tmp_var = MAPIFindProperty(&(att->MAPI), PROP_TAG(PT_BINARY, PR_ATTACH_DATA_OBJ));
		if (tmp_var == MAPI_UNDEFINED) {
			tmp_var = &(att->FileData);
			is_object = FALSE;
		}
		
		sub_info = tnef_dump_file(filename, 
			tmp_var->data + (is_object ? 16:0), 
			tmp_var->size - (is_object ? 16:0));
		
		if (sub_info)
			g_node_append(mimeinfo->node, sub_info->node);
	
		memcpy(&signature, tmp_var->data+(is_object ? 16:0), sizeof(DWORD));

		if (TNEFCheckForSignature(signature) == 0) {
			debug_print("that's TNEF stuff, process it\n");
			tnef_parse(parser, sub_info);
		}

		sub_info = NULL;
		
		att = att->next;

		g_free(filename);
	}
	
	TNEFFree(tnef);
	return TRUE;
}