1 /* Copyright (c) 2007, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gstdio.h>
33 #include <string.h> /* for strlen */
34 #include <modest-runtime.h>
35 #include <libgnomevfs/gnome-vfs.h>
36 #include <tny-fs-stream.h>
37 #include <tny-camel-account.h>
38 #include <tny-status.h>
39 #include <tny-camel-send-queue.h>
40 #include <tny-camel-transport-account.h>
41 #include <tny-camel-imap-store-account.h>
42 #include <tny-camel-pop-store-account.h>
44 #include <modest-defs.h>
45 #include "modest-utils.h"
46 #include "modest-platform.h"
47 #include <modest-account-protocol.h>
48 #include "modest-account-mgr-helpers.h"
49 #include "modest-text-utils.h"
50 #include <modest-local-folder-info.h>
51 #include "widgets/modest-header-view.h"
52 #include "widgets/modest-main-window.h"
53 #include "modest-widget-memory.h"
54 #include "widgets/modest-sort-criterium-view.h"
55 #ifdef MODEST_TOOLKIT_HILDON2
56 #include "modest-header-window.h"
61 modest_utils_get_supported_secure_authentication_error_quark (void)
63 return g_quark_from_static_string("modest-utils-get-supported-secure-authentication-error-quark");
67 modest_utils_folder_writable (const gchar *filename)
69 g_return_val_if_fail (filename, FALSE);
74 if (g_ascii_strncasecmp (filename, "obex", 4) != 0) {
75 GnomeVFSFileInfo *folder_info = NULL;
76 GnomeVFSResult result = GNOME_VFS_OK;
77 GnomeVFSURI *uri = NULL;
78 GnomeVFSURI *folder_uri = NULL;
80 uri = gnome_vfs_uri_new (filename);
81 folder_uri = gnome_vfs_uri_get_parent (uri);
83 if (folder_uri != NULL) {
84 folder_info = gnome_vfs_file_info_new ();
85 result = gnome_vfs_get_file_info_uri (folder_uri, folder_info,
86 GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS);
87 gnome_vfs_uri_unref (folder_uri);
89 gnome_vfs_uri_unref (uri);
91 if (folder_uri == NULL)
94 if ((result != GNOME_VFS_OK) ||
95 (!((folder_info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) ||
96 (folder_info->permissions & GNOME_VFS_PERM_USER_WRITE)))) {
98 gnome_vfs_file_info_unref (folder_info);
101 gnome_vfs_file_info_unref (folder_info);
107 modest_utils_file_exists (const gchar *filename)
109 gboolean result = FALSE;
112 g_return_val_if_fail (filename, FALSE);
114 path = strstr (filename, "file://");
116 path = (gchar *) filename;
118 path = (gchar *) filename + strlen ("file://");
120 if (g_access (path, F_OK) == 0)
127 modest_utils_create_temp_stream (const gchar *orig_name, const gchar *hash_base, gchar **path)
130 gchar *filepath = NULL;
134 /* hmmm... maybe we need a modest_text_utils_validate_file_name? */
135 g_return_val_if_fail (orig_name && strlen(orig_name) != 0, NULL);
137 if (strlen(orig_name) > 200) {
138 g_warning ("%s: filename too long ('%s')",
139 __FUNCTION__, orig_name);
143 if (g_strstr_len (orig_name, strlen(orig_name), "/") != NULL) {
144 g_warning ("%s: filename contains '/' character(s) (%s)",
145 __FUNCTION__, orig_name);
149 /* make a random subdir under /tmp or /var/tmp */
150 if (hash_base != NULL) {
151 hash_number = g_str_hash (hash_base);
153 hash_number = (guint) random ();
155 tmpdir = g_strdup_printf ("%s/%u", g_get_tmp_dir (), hash_number);
156 if ((g_access (tmpdir, R_OK) == -1) && (g_mkdir (tmpdir, 0755) == -1)) {
157 g_warning ("%s: failed to create dir '%s': %s",
158 __FUNCTION__, tmpdir, g_strerror(errno));
163 tmp = g_uri_escape_string (orig_name, NULL, FALSE);
164 filepath = g_build_filename (tmpdir, tmp, NULL);
167 /* if file exists, first we try to remove it */
168 if (g_access (filepath, F_OK) == 0)
171 /* don't overwrite if it already exists, even if it is writable */
172 if (g_access (filepath, F_OK) == 0) {
181 /* try to write the file there */
182 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
184 g_warning ("%s: failed to create '%s': %s",
185 __FUNCTION__, filepath, g_strerror(errno));
199 return TNY_FS_STREAM (tny_fs_stream_new (fd));
207 } ModestGetSupportedAuthInfo;
210 on_idle_secure_auth_finished (gpointer user_data)
212 /* Operation has finished, close the dialog. Control continues after
213 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
214 gdk_threads_enter(); /* CHECKED */
215 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
216 gdk_threads_leave(); /* CHECKED */
222 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
228 ModestPairList *pairs;
230 ModestProtocolRegistry *protocol_registry;
231 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
234 g_return_if_fail (user_data);
235 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
236 g_return_if_fail (TNY_IS_LIST(auth_types));
238 info = (ModestGetSupportedAuthInfo *) user_data;
240 /* Free everything if the actual action was canceled */
242 g_debug ("%s: operation canceled\n", __FUNCTION__);
247 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
252 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
256 if (tny_list_get_length(auth_types) == 0) {
257 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
261 protocol_registry = modest_runtime_get_protocol_registry ();
262 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
264 /* Get the enum value for the strings: */
266 iter = tny_list_create_iterator(auth_types);
267 while (!tny_iterator_is_done(iter)) {
269 const gchar *auth_name;
270 ModestProtocolType protocol_type;
272 pair = TNY_PAIR(tny_iterator_get_current(iter));
275 auth_name = tny_pair_get_name(pair);
276 g_object_unref (pair);
280 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
282 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
283 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
286 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
287 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
289 tny_iterator_next(iter);
291 g_object_unref (iter);
293 modest_pair_list_free (pairs);
294 *(info->result) = result;
297 /* Close the dialog in a main thread */
298 g_idle_add(on_idle_secure_auth_finished, info->dialog);
301 g_slice_free (ModestGetSupportedAuthInfo, info);
306 gboolean not_finished;
310 keep_pulsing (gpointer user_data)
312 KeepPulsing *info = (KeepPulsing *) user_data;
314 if (!info->not_finished) {
315 g_slice_free (KeepPulsing, info);
319 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
324 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
325 const gchar* hostname,
327 const gchar* username,
328 GtkWindow *parent_window,
331 TnyAccount * tny_account = NULL;
332 ModestProtocolRegistry *protocol_registry;
335 ModestTnyAccountStore *account_store;
336 TnySessionCamel *session = NULL;
337 ModestProtocol *protocol = NULL;
338 GList *result = NULL;
341 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
343 protocol_registry = modest_runtime_get_protocol_registry ();
345 /* We need a connection to get the capabilities; */
346 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
349 /* Create a TnyCamelAccount so we can use
350 * tny_camel_account_get_supported_secure_authentication(): */
351 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
353 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
354 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
358 g_printerr ("%s could not create tny account.", __FUNCTION__);
362 /* Set proto, so that the prepare_func() vfunc will work when
363 * we call set_session(): */
364 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
365 tny_account_set_id (tny_account, "temp_account");
366 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
367 tny_account_set_hostname (tny_account, hostname);
368 tny_account_set_user (tny_account, username);
371 tny_account_set_port (tny_account, port);
373 /* Set the session for the account, so we can use it: */
374 account_store = modest_runtime_get_account_store ();
375 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
376 g_return_val_if_fail (session, NULL);
377 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
379 dialog = gtk_dialog_new_with_buttons(" ",
381 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
382 _("mcen_bd_dialog_cancel"),
386 /* Ask camel to ask the server, asynchronously: */
387 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
388 info->result = &result;
389 info->dialog = dialog;
391 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
392 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
393 progress = gtk_progress_bar_new();
394 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
395 gtk_widget_show_all(info->dialog);
397 KeepPulsing *pi = g_slice_new (KeepPulsing);
398 pi->progress = progress;
399 pi->not_finished = TRUE;
401 /* Starts the pulsing of the progressbar */
402 g_timeout_add (500, keep_pulsing, pi);
404 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
405 on_camel_account_get_supported_secure_authentication,
409 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
411 pi->not_finished = FALSE;
412 /* pi is freed in the timeout itself to avoid a GCond here */
414 gtk_widget_destroy(dialog);
417 tny_account_cancel (tny_account);
418 g_object_unref (tny_account);
424 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
427 g_return_if_fail (GTK_IS_WINDOW(parent_window));
428 g_return_if_fail (GTK_IS_DIALOG(dialog));
430 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
432 /* Destroy the dialog when it is closed: */
433 g_signal_connect_swapped (dialog,
435 G_CALLBACK (gtk_widget_destroy),
438 gtk_widget_show (GTK_WIDGET (dialog));
442 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
444 GSList *proxies = NULL;
446 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
448 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
449 proxies != NULL; proxies = g_slist_next (proxies)) {
450 GtkWidget *widget = (GtkWidget *) proxies->data;
451 gtk_action_block_activate_from (GTK_ACTION (action), widget);
454 gtk_toggle_action_set_active (action, value);
456 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
457 proxies != NULL; proxies = g_slist_next (proxies)) {
458 GtkWidget *widget = (GtkWidget *) proxies->data;
459 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
466 modest_list_index (TnyList *list, GObject *object)
471 g_return_val_if_fail (TNY_IS_LIST(list), -1);
472 g_return_val_if_fail (G_IS_OBJECT(object), -1);
474 iter = tny_list_create_iterator (list);
475 while (!tny_iterator_is_done (iter)) {
476 GObject *current = tny_iterator_get_current (iter);
478 g_object_unref (current);
479 if (current == object)
482 tny_iterator_next (iter);
486 if (tny_iterator_is_done (iter))
488 g_object_unref (iter);
493 modest_utils_get_available_space (const gchar *maildir_path)
498 GnomeVFSFileSize size;
500 folder = modest_local_folder_info_get_maildir_path (maildir_path);
501 uri_string = gnome_vfs_get_uri_from_local_path (folder);
502 uri = gnome_vfs_uri_new (uri_string);
507 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
509 gnome_vfs_uri_unref (uri);
514 return (guint64) size;
517 on_destroy_dialog (GtkDialog *dialog)
519 gtk_widget_destroy (GTK_WIDGET(dialog));
520 if (gtk_events_pending ())
521 gtk_main_iteration ();
525 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
529 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
530 g_return_val_if_fail (key, 0);
532 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
533 if (sort_key < 0 || sort_key >= max) {
534 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
537 return (guint)sort_key;
541 launch_sort_headers_dialog (GtkWindow *parent_window,
544 ModestHeaderView *header_view = NULL;
546 GtkSortType sort_type;
548 gint default_key = 0;
550 gboolean outgoing = FALSE;
551 gint current_sort_colid = -1;
552 GtkSortType current_sort_type;
553 gint attachments_sort_id;
554 gint priority_sort_id;
555 GtkTreeSortable *sortable;
557 /* Get header window */
558 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
559 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
560 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
561 #ifdef MODEST_TOOLKIT_HILDON2
562 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
563 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
570 /* Add sorting keys */
571 cols = modest_header_view_get_columns (header_view);
574 #define SORT_ID_NUM 6
575 int sort_model_ids[SORT_ID_NUM];
576 int sort_ids[SORT_ID_NUM];
578 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
579 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
581 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
584 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
585 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
587 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
588 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
591 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
594 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
595 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
597 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
598 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
600 default_key = sort_key;
602 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
604 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
606 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
608 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
610 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
612 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
613 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
614 attachments_sort_id = sort_key;
616 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
618 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
619 sort_ids[sort_key] = 0;
621 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
623 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
624 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
625 priority_sort_id = sort_key;
627 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
629 if (!gtk_tree_sortable_get_sort_column_id (sortable,
630 ¤t_sort_colid, ¤t_sort_type)) {
631 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
632 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
634 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
635 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
636 gpointer flags_sort_type_pointer;
637 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
638 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
639 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
641 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
643 gint current_sort_keyid = 0;
644 while (current_sort_keyid < SORT_ID_NUM) {
645 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
648 current_sort_keyid++;
650 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
654 result = gtk_dialog_run (GTK_DIALOG (dialog));
655 if (result == GTK_RESPONSE_OK) {
656 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
657 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
658 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
662 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
663 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
664 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
665 GINT_TO_POINTER (sort_ids[sort_key]));
666 /* This is a hack to make it resort rows always when flag fields are
667 * selected. If we do not do this, changing sort field from priority to
668 * attachments does not work */
669 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
671 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
672 sort_model_ids[sort_key]);
675 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
676 gtk_tree_sortable_sort_column_changed (sortable);
679 modest_widget_memory_save (modest_runtime_get_conf (),
680 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
687 modest_utils_run_sort_dialog (GtkWindow *parent_window,
688 ModestSortDialogType type)
690 GtkWidget *dialog = NULL;
693 dialog = modest_platform_create_sort_dialog (parent_window);
696 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
697 GTK_WINDOW (dialog), parent_window);
701 case MODEST_SORT_HEADERS:
702 launch_sort_headers_dialog (parent_window,
708 on_destroy_dialog (GTK_DIALOG(dialog));
713 modest_images_cache_get_id (const gchar *account, const gchar *uri)
715 GnomeVFSURI *vfs_uri;
718 vfs_uri = gnome_vfs_uri_new (uri);
722 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
723 gnome_vfs_uri_unref (vfs_uri);
729 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
731 gchar *account_name = NULL;
732 ModestAccountMgr *mgr = NULL;
733 GSList *accounts = NULL, *node = NULL;
737 g_return_val_if_fail (from_header, NULL);
739 mgr = modest_runtime_get_account_mgr ();
740 accounts = modest_account_mgr_account_names (mgr, TRUE);
742 for (node = accounts; node != NULL; node = g_slist_next (node)) {
744 gchar *transport_account;
746 if (!strcmp (from_header, node->data)) {
747 account_name = g_strdup (node->data);
751 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
752 (const gchar *) node->data,
753 TNY_ACCOUNT_TYPE_TRANSPORT);
754 if (transport_account) {
756 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
759 ModestProtocol *protocol =
760 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
761 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
763 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
764 ModestPairList *pair_list;
766 gchar *from_header_email =
767 modest_text_utils_get_email_address (from_header);
768 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
771 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
773 account_name = g_strdup (node->data);
775 *mailbox = g_strdup (from_header_email);
778 modest_pair_list_free (pair_list);
783 g_free (transport_account);
785 if (mailbox && *mailbox)
789 modest_account_mgr_get_from_string (mgr, node->data, NULL);
793 modest_text_utils_get_email_address (from);
794 gchar *from_header_email =
795 modest_text_utils_get_email_address (from_header);
797 if (from_email && from_header_email) {
798 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
799 account_name = g_strdup (node->data);
806 g_free (from_header_email);
812 g_slist_foreach (accounts, (GFunc) g_free, NULL);
813 g_slist_free (accounts);
819 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
820 const gchar* character,
823 gchar *message = NULL;
824 const gchar *show_char = NULL;
827 show_char = character;
832 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
833 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
838 modest_utils_open_mcc_mapping_file (gboolean from_lc_messages, gboolean *translated)
842 const gchar *env_list;
843 gchar **parts, **node;
845 if (from_lc_messages) {
846 env_list = setlocale (LC_MESSAGES, NULL);
848 env_list = getenv ("LANG");
850 parts = g_strsplit (env_list, ":", 0);
852 const gchar* path2 = MODEST_MCC_MAPPING;
858 for (node = parts; path == NULL && node != NULL && *node != NULL && **node != '\0'; node++) {
859 path1 = g_strdup_printf ("%s.%s", MODEST_OPERATOR_WIZARD_MCC_MAPPING, *node);
860 if (access (path1, R_OK) == 0) {
871 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
872 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
875 } else if (access (path2, R_OK) == 0) {
878 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
879 __FUNCTION__, path1, path2);
884 result = fopen (path, "r");
886 g_warning ("%s: error opening mapping file '%s': %s",
887 __FUNCTION__, path, strerror(errno));
895 /* cluster mcc's, based on the list
896 * http://en.wikipedia.org/wiki/Mobile_country_code
899 effective_mcc (gint mcc)
902 case 405: return 404; /* india */
903 case 441: return 440; /* japan */
904 case 235: return 234; /* united kingdom */
910 case 316: return 310; /* united states */
915 /* each line is of the form:
918 NOTE: this function is NOT re-entrant, the out-param country
919 are static strings that should NOT be freed. and will change when
920 calling this function again
922 also note, this function will return the "effective mcc", which
923 is the normalized mcc for a country - ie. even if the there
924 are multiple entries for the United States with various mccs,
925 this function will always return 310, even if the real mcc parsed
926 would be 314. see the 'effective_mcc' function above.
929 parse_mcc_mapping_line (const char* line, char** country)
931 char mcc[4]; /* the mcc code, always 3 bytes*/
932 gchar *iter, *tab, *final;
939 /* Go to the first tab (Country separator) */
940 tab = g_utf8_strrchr (line, -1, '\t');
944 *country = g_utf8_find_next_char (tab, NULL);
946 /* Replace by end of string. We need to use strlen, because
947 g_utf8_strrchr expects bytes and not UTF8 characters */
948 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\n');
949 if (G_LIKELY (final))
952 tab[strlen(tab) - 1] = '\0';
955 mcc[0] = g_utf8_get_char (line);
956 iter = g_utf8_find_next_char (line, NULL);
957 mcc[1] = g_utf8_get_char (iter);
958 iter = g_utf8_find_next_char (iter, NULL);
959 mcc[2] = g_utf8_get_char (iter);
962 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
965 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
967 /** Note that the mcc_mapping file is installed
968 * by the operator-wizard-settings package.
971 modest_utils_create_country_model (void)
975 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
981 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
984 char line[MCC_FILE_MAX_LINE_LEN];
985 guint previous_mcc = 0;
987 GHashTable *country_hash;
990 /* First we need to know our current region */
991 file = modest_utils_open_mcc_mapping_file (FALSE, &translated);
993 g_warning ("Could not open mcc_mapping file");
997 /* Get the territory specified for the current locale */
998 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
1000 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1002 char *country = NULL;
1004 mcc = parse_mcc_mapping_line (line, &country);
1005 if (!country || mcc == 0) {
1006 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1010 if (mcc == previous_mcc) {
1011 /* g_warning ("already seen: %s", line); */
1016 if (!(*locale_mcc)) {
1018 if (!g_utf8_collate (country, territory))
1021 gchar *translation = dgettext ("osso-countries", country);
1022 if (!g_utf8_collate (translation, territory))
1029 /* Now we fill the model */
1030 file = modest_utils_open_mcc_mapping_file (TRUE, &translated);
1032 g_warning ("Could not open mcc_mapping file");
1036 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1037 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1040 char *country = NULL;
1042 const gchar *name_translated;
1044 mcc = parse_mcc_mapping_line (line, &country);
1045 if (!country || mcc == 0) {
1046 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1050 if (mcc == previous_mcc ||
1051 g_hash_table_lookup (country_hash, country)) {
1052 g_debug ("already seen: '%s' %d", country, mcc);
1057 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1059 name_translated = dgettext ("osso-countries", country);
1061 /* Add the row to the model: */
1062 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1063 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1064 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1065 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1070 g_hash_table_unref (country_hash);
1073 /* Fallback to Finland */
1077 /* Sort the items: */
1078 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1079 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1083 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1085 GList *new_headers_list;
1088 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1089 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1091 new_headers_list = NULL;
1092 iter = tny_list_create_iterator (header_list);
1093 while (!tny_iterator_is_done (iter)) {
1094 ModestMsgNotificationData *data;
1098 header = (TnyHeader *) tny_iterator_get_current (iter);
1100 folder = tny_header_get_folder (header);
1105 uid = tny_header_dup_uid (header);
1106 uri = g_strdup_printf ("%s/%s",
1107 tny_folder_get_url_string (folder),
1111 /* Create data & add to list */
1112 data = g_slice_new0 (ModestMsgNotificationData);
1113 data->subject = tny_header_dup_subject (header);
1114 data->from = tny_header_dup_from (header);
1117 new_headers_list = g_list_append (new_headers_list, data);
1119 g_object_unref (folder);
1121 g_object_unref (header);
1123 tny_iterator_next (iter);
1125 g_object_unref (iter);
1127 return new_headers_list;
1131 free_notification_data (gpointer data,
1134 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1136 g_free (notification_data->from);
1137 g_free (notification_data->subject);
1138 g_free (notification_data->uri);
1140 g_slice_free (ModestMsgNotificationData, notification_data);
1144 modest_utils_free_notification_list (GList *notification_list)
1146 g_return_if_fail (g_list_length (notification_list) > 0);
1148 g_list_foreach (notification_list, free_notification_data, NULL);
1149 g_list_free (notification_list);
1153 modest_utils_flush_send_queue (const gchar *account_id)
1155 TnyTransportAccount *account;
1157 /* Get the transport account */
1158 account = (TnyTransportAccount *)
1159 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1161 TNY_ACCOUNT_TYPE_TRANSPORT);
1163 ModestMailOperation *wakeup_op;
1164 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue (account, TRUE);
1167 wakeup_op = modest_mail_operation_new (NULL);
1168 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1170 modest_mail_operation_queue_wakeup (wakeup_op, send_queue);
1172 g_object_unref (account);