evolution-3.6.4/modules/mdn/evolution-mdn.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found evolution-mdn.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found evolution-mdn.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * evolution-mdn.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  */
 18 
 19 #include <config.h>
 20 #include <string.h>
 21 #include <glib/gi18n-lib.h>
 22 
 23 #include <libebackend/libebackend.h>
 24 
 25 #include <libevolution-utils/e-alert-dialog.h>
 26 
 27 #include <libemail-engine/e-mail-session-utils.h>
 28 
 29 #include <mail/em-utils.h>
 30 #include <mail/e-mail-reader.h>
 31 #include <mail/mail-send-recv.h>
 32 #include <mail/message-list.h>
 33 #include <mail/em-composer-utils.h>
 34 
 35 #define MDN_USER_FLAG "receipt-handled"
 36 
 37 #define E_TYPE_MDN (e_mdn_get_type ())
 38 #define E_MDN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_MDN, EMdn))
 39 #define E_IS_MDN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_MDN))
 40 
 41 typedef struct _EMdn EMdn;
 42 typedef struct _EMdnClass EMdnClass;
 43 
 44 struct _EMdn {
 45 	EExtension parent;
 46 	gpointer alert;  /* weak pointer */
 47 };
 48 
 49 struct _EMdnClass {
 50 	EExtensionClass parent_class;
 51 };
 52 
 53 typedef struct _MdnContext MdnContext;
 54 
 55 struct _MdnContext {
 56 	ESource *source;
 57 	EMailReader *reader;
 58 	CamelFolder *folder;
 59 	CamelMessageInfo *info;
 60 	CamelMimeMessage *message;
 61 	gchar *notify_to;
 62 };
 63 
 64 typedef enum {
 65 	MDN_ACTION_MODE_MANUAL,
 66 	MDN_ACTION_MODE_AUTOMATIC
 67 } MdnActionMode;
 68 
 69 typedef enum {
 70 	MDN_SENDING_MODE_MANUAL,
 71 	MDN_SENDING_MODE_AUTOMATIC
 72 } MdnSendingMode;
 73 
 74 /* Module Entry Points */
 75 void e_module_load (GTypeModule *type_module);
 76 void e_module_unload (GTypeModule *type_module);
 77 
 78 /* Forward Declarations */
 79 GType e_mdn_get_type (void);
 80 
 81 G_DEFINE_DYNAMIC_TYPE (EMdn, e_mdn, E_TYPE_EXTENSION)
 82 
 83 static void
 84 mdn_context_free (MdnContext *context)
 85 {
 86 	if (context->info != NULL)
 87 		camel_folder_free_message_info (
 88 			context->folder, context->info);
 89 
 90 	g_object_unref (context->source);
 91 	g_object_unref (context->reader);
 92 	g_object_unref (context->folder);
 93 	g_object_unref (context->message);
 94 
 95 	g_free (context->notify_to);
 96 
 97 	g_slice_free (MdnContext, context);
 98 }
 99 
100 static void
101 mdn_remove_alert (EMdn *mdn)
102 {
103 	g_return_if_fail (E_IS_MDN (mdn));
104 
105 	if (mdn->alert != NULL)
106 		e_alert_response (mdn->alert, GTK_RESPONSE_OK);
107 }
108 
109 static void
110 mdn_submit_alert (EMdn *mdn,
111                   EMailReader *reader,
112                   EAlert *alert)
113 {
114 	EPreviewPane *preview_pane;
115 
116 	g_return_if_fail (E_IS_MDN (mdn));
117 
118 	mdn_remove_alert (mdn);
119 
120 	g_return_if_fail (mdn->alert == NULL);
121 
122 	/* Make sure alerts are shown in the preview pane and not
123 	 * wherever e_mail_reader_get_alert_sink() might show it. */
124 	preview_pane = e_mail_reader_get_preview_pane (reader);
125 	e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
126 
127 	mdn->alert = alert;
128 	g_object_add_weak_pointer (G_OBJECT (mdn->alert), &mdn->alert);
129 }
130 
131 static gchar *
132 mdn_get_notify_to (CamelMimeMessage *message)
133 {
134 	CamelMedium *medium;
135 	const gchar *address;
136 	const gchar *header_name;
137 
138 	medium = CAMEL_MEDIUM (message);
139 	header_name = "Disposition-Notification-To";
140 	address = camel_medium_get_header (medium, header_name);
141 
142 	/* TODO Should probably decode/format the address,
143 	 *      since it could be in RFC 2047 format. */
144 	if (address != NULL)
145 		while (camel_mime_is_lwsp (*address))
146 			address++;
147 
148 	return g_strdup (address);
149 }
150 
151 static gchar *
152 mdn_get_disposition (MdnActionMode action_mode,
153                      MdnSendingMode sending_mode)
154 {
155 	GString *string;
156 
157 	string = g_string_sized_new (64);
158 
159 	switch (action_mode) {
160 		case MDN_ACTION_MODE_MANUAL:
161 			g_string_append (string, "manual-action");
162 			break;
163 		case MDN_ACTION_MODE_AUTOMATIC:
164 			g_string_append (string, "automatic-action");
165 			break;
166 		default:
167 			g_warn_if_reached ();
168 	}
169 
170 	g_string_append_c (string, '/');
171 
172 	switch (sending_mode) {
173 		case MDN_SENDING_MODE_MANUAL:
174 			g_string_append (string, "MDN-sent-manually");
175 			break;
176 		case MDN_SENDING_MODE_AUTOMATIC:
177 			g_string_append (string, "MDN-sent-automatically");
178 			break;
179 		default:
180 			g_warn_if_reached ();
181 	}
182 
183 	g_string_append (string, ";displayed");
184 
185 	return g_string_free (string, FALSE);
186 }
187 
188 static void
189 mdn_receipt_done (EMailSession *session,
190                   GAsyncResult *result,
191                   gpointer user_data)
192 {
193 	GError *error = NULL;
194 
195 	e_mail_session_append_to_local_folder_finish (
196 		session, result, NULL, &error);
197 
198 	if (error == NULL) {
199 		mail_send (session);
200 	} else {
201 		/* FIXME Poor error handling. */
202 		g_warning ("%s: %s", G_STRFUNC, error->message);
203 		g_error_free (error);
204 	}
205 }
206 
207 static void
208 mdn_notify_sender (ESource *identity_source,
209                    EMailReader *reader,
210                    CamelFolder *folder,
211                    CamelMimeMessage *message,
212                    CamelMessageInfo *info,
213                    const gchar *notify_to,
214                    MdnActionMode action_mode,
215                    MdnSendingMode sending_mode)
216 {
217 	/* See RFC 3798 for a description of message receipts. */
218 
219 	CamelMimeMessage *receipt;
220 	CamelMultipart *body;
221 	CamelMimePart *part;
222 	CamelMedium *medium;
223 	CamelDataWrapper *receipt_text, *receipt_data;
224 	CamelContentType *type;
225 	CamelInternetAddress *address;
226 	CamelStream *stream;
227 	CamelMessageInfo *receipt_info;
228 	EMailBackend *backend;
229 	EMailSession *session;
230 	ESourceExtension *extension;
231 	const gchar *message_id;
232 	const gchar *message_date;
233 	const gchar *message_subject;
234 	const gchar *extension_name;
235 	const gchar *transport_uid;
236 	const gchar *self_address;
237 	const gchar *sent_folder_uri;
238 	gchar *fake_msgid;
239 	gchar *hostname;
240 	gchar *receipt_subject;
241 	gchar *disposition;
242 	gchar *recipient;
243 	gchar *content;
244 	gchar *ua;
245 
246 	backend = e_mail_reader_get_backend (reader);
247 	session = e_mail_backend_get_session (backend);
248 
249 	/* Tag the message immediately even though we haven't actually sent
250 	 * the read receipt yet.  Not a big deal if we fail to send it, and
251 	 * we don't want to keep badgering the user about it. */
252 	camel_message_info_set_user_flag (info, MDN_USER_FLAG, TRUE);
253 
254 	medium = CAMEL_MEDIUM (message);
255 	message_id = camel_medium_get_header (medium, "Message-ID");
256 	message_date = camel_medium_get_header (medium, "Date");
257 	message_subject = camel_mime_message_get_subject (message);
258 
259 	if (message_id == NULL)
260 		message_id = "";
261 
262 	if (message_date == NULL)
263 		message_date = "";
264 
265 	/* Collect information for the receipt. */
266 
267 	g_return_if_fail (identity_source != NULL);
268 
269 	extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
270 	extension = e_source_get_extension (identity_source, extension_name);
271 
272 	self_address = e_source_mail_identity_get_address (
273 		E_SOURCE_MAIL_IDENTITY (extension));
274 
275 	extension_name = E_SOURCE_EXTENSION_MAIL_SUBMISSION;
276 	extension = e_source_get_extension (identity_source, extension_name);
277 
278 	sent_folder_uri = e_source_mail_submission_get_sent_folder (
279 		E_SOURCE_MAIL_SUBMISSION (extension));
280 
281 	transport_uid = e_source_mail_submission_get_transport_uid (
282 		E_SOURCE_MAIL_SUBMISSION (extension));
283 
284 	/* We use camel_header_msgid_generate() to get a canonical
285 	 * hostname, then skip the part leading to '@' */
286 	fake_msgid = camel_header_msgid_generate ();
287 	hostname = strchr (fake_msgid, '@');
288 	hostname++;
289 
290 	/* Create toplevel container. */
291 	body = camel_multipart_new ();
292 	camel_data_wrapper_set_mime_type (
293 		CAMEL_DATA_WRAPPER (body),
294 		"multipart/report;"
295 		"report-type=\"disposition-notification\"");
296 	camel_multipart_set_boundary (body, NULL);
297 
298 	/* Create textual receipt. */
299 
300 	receipt_text = camel_data_wrapper_new ();
301 
302 	type = camel_content_type_new ("text", "plain");
303 	camel_content_type_set_param (type, "format", "flowed");
304 	camel_content_type_set_param (type, "charset", "UTF-8");
305 	camel_data_wrapper_set_mime_type_field (receipt_text, type);
306 	camel_content_type_unref (type);
307 
308 	content = g_strdup_printf (
309 		/* Translators: First %s is an email address, second %s
310 		 * is the subject of the email, third %s is the date. */
311 		_("Your message to %s about \"%s\" on %s has been read."),
312 		self_address, message_subject, message_date);
313 	stream = camel_stream_mem_new ();
314 	camel_stream_write_string (stream, content, NULL, NULL);
315 	camel_data_wrapper_construct_from_stream_sync (
316 		receipt_text, stream, NULL, NULL);
317 	g_object_unref (stream);
318 	g_free (content);
319 
320 	part = camel_mime_part_new ();
321 	camel_medium_set_content (CAMEL_MEDIUM (part), receipt_text);
322 	camel_mime_part_set_encoding (
323 		part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
324 	camel_multipart_add_part (body, part);
325 	g_object_unref (part);
326 
327 	g_object_unref (receipt_text);
328 
329 	/* Create the machine-readable receipt. */
330 
331 	receipt_data = camel_data_wrapper_new ();
332 
333 	ua = g_strdup_printf (
334 		"%s; %s", hostname, "Evolution "
335 		VERSION SUB_VERSION " " VERSION_COMMENT);
336 	recipient = g_strdup_printf ("rfc822; %s", self_address);
337 	disposition = mdn_get_disposition (action_mode, sending_mode);
338 
339 	type = camel_content_type_new ("message", "disposition-notification");
340 	camel_data_wrapper_set_mime_type_field (receipt_data, type);
341 	camel_content_type_unref (type);
342 
343 	content = g_strdup_printf (
344 		"Reporting-UA: %s\n"
345 		"Final-Recipient: %s\n"
346 		"Original-Message-ID: %s\n"
347 		"Disposition: %s\n",
348 		ua, recipient, message_id, disposition);
349 	stream = camel_stream_mem_new ();
350 	camel_stream_write_string (stream, content, NULL, NULL);
351 	camel_data_wrapper_construct_from_stream_sync (
352 		receipt_data, stream, NULL, NULL);
353 	g_object_unref (stream);
354 	g_free (content);
355 
356 	g_free (ua);
357 	g_free (recipient);
358 	g_free (fake_msgid);
359 	g_free (disposition);
360 
361 	part = camel_mime_part_new ();
362 	camel_medium_set_content (CAMEL_MEDIUM (part), receipt_data);
363 	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_7BIT);
364 	camel_multipart_add_part (body, part);
365 	g_object_unref (part);
366 
367 	g_object_unref (receipt_data);
368 
369 	/* Finish creating the message. */
370 
371 	receipt = camel_mime_message_new ();
372 	camel_medium_set_content (
373 		CAMEL_MEDIUM (receipt), CAMEL_DATA_WRAPPER (body));
374 	g_object_unref (body);
375 
376 	receipt_subject = g_strdup_printf (
377 		/* Translators: %s is the subject of the email message. */
378 		_("Delivery Notification for \"%s\""), message_subject);
379 	camel_mime_message_set_subject (receipt, receipt_subject);
380 	g_free (receipt_subject);
381 
382 	address = camel_internet_address_new ();
383 	camel_address_decode (CAMEL_ADDRESS (address), self_address);
384 	camel_mime_message_set_from (receipt, address);
385 	g_object_unref (address);
386 
387 	address = camel_internet_address_new ();
388 	camel_address_decode (CAMEL_ADDRESS (address), notify_to);
389 	camel_mime_message_set_recipients (
390 		receipt, CAMEL_RECIPIENT_TYPE_TO, address);
391 	g_object_unref (address);
392 
393 	camel_medium_set_header (
394 		CAMEL_MEDIUM (receipt),
395 		"Return-Path", "<>");
396 	camel_medium_set_header (
397 		CAMEL_MEDIUM (receipt),
398 		"X-Evolution-Identity",
399 		e_source_get_uid (identity_source));
400 	camel_medium_set_header (
401 		CAMEL_MEDIUM (receipt),
402 		"X-Evolution-Transport",
403 		transport_uid);
404 	camel_medium_set_header (
405 		CAMEL_MEDIUM (receipt),
406 		"X-Evolution-Fcc",
407 		sent_folder_uri);
408 
409 	/* RFC 3834, Section 5 describes this header. */
410 	camel_medium_set_header (
411 		CAMEL_MEDIUM (receipt),
412 		"Auto-Submitted", "auto-replied");
413 
414 	/* Send the receipt. */
415 	receipt_info = camel_message_info_new (NULL);
416 	camel_message_info_set_flags (
417 		receipt_info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
418 
419 	/* FIXME Pass a GCancellable. */
420 	e_mail_session_append_to_local_folder (
421 		session, E_MAIL_LOCAL_FOLDER_OUTBOX,
422 		receipt, receipt_info, G_PRIORITY_DEFAULT,
423 		NULL, (GAsyncReadyCallback) mdn_receipt_done,
424 		g_object_ref (session));
425 
426 	camel_message_info_free (receipt_info);
427 }
428 
429 static void
430 mdn_notify_action_cb (GtkAction *action,
431                       MdnContext *context)
432 {
433 	mdn_notify_sender (
434 		context->source,
435 		context->reader,
436 		context->folder,
437 		context->message,
438 		context->info,
439 		context->notify_to,
440 		MDN_ACTION_MODE_MANUAL,
441 		MDN_SENDING_MODE_MANUAL);
442 
443 	/* Make sure the newly-added user flag gets saved. */
444 	camel_folder_free_message_info (context->folder, context->info);
445 	context->info = NULL;
446 }
447 
448 static void
449 mdn_mail_reader_changed_cb (EMailReader *reader,
450                             EMdn *mdn)
451 {
452 	MessageList *message_list;
453 
454 	g_return_if_fail (E_IS_MAIL_READER (reader));
455 
456 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
457 
458 	if (!message_list || message_list_selected_count (message_list) != 1)
459 		mdn_remove_alert (mdn);
460 }
461 
462 static void
463 mdn_message_loaded_cb (EMailReader *reader,
464                        const gchar *message_uid,
465                        CamelMimeMessage *message,
466                        EMdn *mdn)
467 {
468 	EAlert *alert;
469 	ESource *source;
470 	ESourceMDN *extension;
471 	ESourceRegistry *registry;
472 	EMailBackend *backend;
473 	EMailSession *session;
474 	CamelFolder *folder;
475 	CamelMessageInfo *info;
476 	EMdnResponsePolicy response_policy;
477 	const gchar *extension_name;
478 	gchar *notify_to = NULL;
479 
480 	backend = e_mail_reader_get_backend (reader);
481 	session = e_mail_backend_get_session (backend);
482 	registry = e_mail_session_get_registry (session);
483 
484 	folder = e_mail_reader_get_folder (reader);
485 
486 	mdn_remove_alert (mdn);
487 
488 	info = camel_folder_get_message_info (folder, message_uid);
489 	if (info == NULL)
490 		return;
491 
492 	if (camel_message_info_user_flag (info, MDN_USER_FLAG)) {
493 		alert = e_alert_new ("mdn:sender-notified", NULL);
494 		mdn_submit_alert (mdn, reader, alert);
495 		g_object_unref (alert);
496 		goto exit;
497 	}
498 
499 	notify_to = mdn_get_notify_to (message);
500 	if (notify_to == NULL)
501 		goto exit;
502 
503 	/* do not show the notice in special folders */
504 	if (em_utils_folder_is_drafts (registry, folder) ||
505 	    em_utils_folder_is_templates (registry, folder) ||
506 	    em_utils_folder_is_sent (registry, folder) ||
507 	    em_utils_folder_is_outbox (registry, folder))
508 		goto exit;
509 
510 	/* This returns a new ESource reference. */
511 	source = em_utils_guess_mail_identity_with_recipients (
512 		registry, message, folder, message_uid);
513 	if (source == NULL)
514 		goto exit;
515 
516 	extension_name = E_SOURCE_EXTENSION_MDN;
517 	extension = e_source_get_extension (source, extension_name);
518 	response_policy = e_source_mdn_get_response_policy (extension);
519 
520 	if (response_policy == E_MDN_RESPONSE_POLICY_ASK) {
521 		MdnContext *context;
522 		GtkAction *action;
523 		gchar *tooltip;
524 
525 		context = g_slice_new0 (MdnContext);
526 		context->source = g_object_ref (source);
527 		context->reader = g_object_ref (reader);
528 		context->folder = g_object_ref (folder);
529 		context->message = g_object_ref (message);
530 		context->info = camel_message_info_ref (info);
531 
532 		context->notify_to = notify_to;
533 		notify_to = NULL;
534 
535 		tooltip = g_strdup_printf (
536 			_("Send a read receipt to '%s'"),
537 			context->notify_to);
538 
539 		action = gtk_action_new (
540 			"notify-sender",  /* name doesn't matter */
541 			_("_Notify Sender"),
542 			tooltip, NULL);
543 
544 		g_signal_connect_data (
545 			action, "activate",
546 			G_CALLBACK (mdn_notify_action_cb),
547 			context,
548 			(GClosureNotify) mdn_context_free,
549 			(GConnectFlags) 0);
550 
551 		alert = e_alert_new ("mdn:notify-sender", NULL);
552 		e_alert_add_action (alert, action, GTK_RESPONSE_APPLY);
553 		mdn_submit_alert (mdn, reader, alert);
554 		g_object_unref (alert);
555 
556 		g_object_unref (action);
557 		g_free (tooltip);
558 	}
559 
560 	g_object_unref (source);
561 
562 exit:
563 	camel_folder_free_message_info (folder, info);
564 	g_free (notify_to);
565 }
566 
567 static void
568 mdn_message_seen_cb (EMailReader *reader,
569                      const gchar *message_uid,
570                      CamelMimeMessage *message)
571 {
572 	ESource *source;
573 	ESourceMDN *extension;
574 	ESourceRegistry *registry;
575 	EMailBackend *backend;
576 	EMailSession *session;
577 	CamelFolder *folder;
578 	CamelMessageInfo *info;
579 	EMdnResponsePolicy response_policy;
580 	const gchar *extension_name;
581 	gchar *notify_to = NULL;
582 
583 	backend = e_mail_reader_get_backend (reader);
584 	session = e_mail_backend_get_session (backend);
585 	registry = e_mail_session_get_registry (session);
586 
587 	folder = e_mail_reader_get_folder (reader);
588 
589 	info = camel_folder_get_message_info (folder, message_uid);
590 	if (info == NULL)
591 		return;
592 
593 	if (camel_message_info_user_flag (info, MDN_USER_FLAG))
594 		goto exit;
595 
596 	notify_to = mdn_get_notify_to (message);
597 	if (notify_to == NULL)
598 		goto exit;
599 
600 	/* This returns a new ESource reference. */
601 	source = em_utils_guess_mail_identity_with_recipients (
602 		registry, message, folder, message_uid);
603 	if (source == NULL)
604 		goto exit;
605 
606 	extension_name = E_SOURCE_EXTENSION_MDN;
607 	extension = e_source_get_extension (source, extension_name);
608 	response_policy = e_source_mdn_get_response_policy (extension);
609 
610 	if (response_policy == E_MDN_RESPONSE_POLICY_ALWAYS)
611 		mdn_notify_sender (
612 			source, reader, folder,
613 			message, info, notify_to,
614 			MDN_ACTION_MODE_AUTOMATIC,
615 			MDN_SENDING_MODE_AUTOMATIC);
616 
617 	g_object_unref (source);
618 
619 exit:
620 	camel_folder_free_message_info (folder, info);
621 	g_free (notify_to);
622 }
623 
624 static void
625 mdn_constructed (GObject *object)
626 {
627 	EExtension *extension;
628 	EExtensible *extensible;
629 
630 	extension = E_EXTENSION (object);
631 	extensible = e_extension_get_extensible (extension);
632 	g_return_if_fail (E_IS_MAIL_READER (extensible));
633 
634 	g_signal_connect (
635 		extensible, "changed",
636 		G_CALLBACK (mdn_mail_reader_changed_cb), extension);
637 
638 	g_signal_connect (
639 		extensible, "message-loaded",
640 		G_CALLBACK (mdn_message_loaded_cb), extension);
641 
642 	g_signal_connect (
643 		extensible, "message-seen",
644 		G_CALLBACK (mdn_message_seen_cb), NULL);
645 
646 	/* Chain up to parent's constructed() method. */
647 	G_OBJECT_CLASS (e_mdn_parent_class)->constructed (object);
648 }
649 
650 static void
651 mdn_dispose (GObject *object)
652 {
653 	mdn_remove_alert (E_MDN (object));
654 
655 	/* Chain up to parent's dispose() method. */
656 	G_OBJECT_CLASS (e_mdn_parent_class)->dispose (object);
657 }
658 
659 static void
660 e_mdn_class_init (EMdnClass *class)
661 {
662 	GObjectClass *object_class;
663 	EExtensionClass *extension_class;
664 
665 	object_class = G_OBJECT_CLASS (class);
666 	object_class->constructed = mdn_constructed;
667 	object_class->dispose = mdn_dispose;
668 
669 	extension_class = E_EXTENSION_CLASS (class);
670 	extension_class->extensible_type = E_TYPE_MAIL_READER;
671 }
672 
673 static void
674 e_mdn_class_finalize (EMdnClass *class)
675 {
676 }
677 
678 static void
679 e_mdn_init (EMdn *extension)
680 {
681 }
682 
683 G_MODULE_EXPORT void
684 e_module_load (GTypeModule *type_module)
685 {
686 	e_mdn_register_type (type_module);
687 }
688 
689 G_MODULE_EXPORT void
690 e_module_unload (GTypeModule *type_module)
691 {
692 }