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_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 GnomeVFSURI *uri = NULL;
110 gboolean result = FALSE;
112 g_return_val_if_fail (filename, FALSE);
114 uri = gnome_vfs_uri_new (filename);
116 result = gnome_vfs_uri_exists (uri);
117 gnome_vfs_uri_unref (uri);
123 modest_utils_create_temp_stream (const gchar *orig_name, const gchar *hash_base, gchar **path)
126 gchar *filepath = NULL;
130 /* hmmm... maybe we need a modest_text_utils_validate_file_name? */
131 g_return_val_if_fail (orig_name && strlen(orig_name) != 0, NULL);
133 if (strlen(orig_name) > 200) {
134 g_warning ("%s: filename too long ('%s')",
135 __FUNCTION__, orig_name);
139 if (g_strstr_len (orig_name, strlen(orig_name), "/") != NULL) {
140 g_warning ("%s: filename contains '/' character(s) (%s)",
141 __FUNCTION__, orig_name);
145 /* make a random subdir under /tmp or /var/tmp */
146 if (hash_base != NULL) {
147 hash_number = g_str_hash (hash_base);
149 hash_number = (guint) random ();
151 tmpdir = g_strdup_printf ("%s/%u", g_get_tmp_dir (), hash_number);
152 if ((g_access (tmpdir, R_OK) == -1) && (g_mkdir (tmpdir, 0755) == -1)) {
153 g_warning ("%s: failed to create dir '%s': %s",
154 __FUNCTION__, tmpdir, g_strerror(errno));
159 filepath = g_strconcat (tmpdir, "/", orig_name, NULL);
161 /* if file exists, first we try to remove it */
162 if (modest_utils_file_exists (filepath)) {
166 /* don't overwrite if it already exists, even if it is writable */
167 if (modest_utils_file_exists (filepath)) {
176 /* try to write the file there */
177 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
179 g_warning ("%s: failed to create '%s': %s",
180 __FUNCTION__, filepath, g_strerror(errno));
194 return TNY_FS_STREAM (tny_fs_stream_new (fd));
202 } ModestGetSupportedAuthInfo;
205 on_idle_secure_auth_finished (gpointer user_data)
207 /* Operation has finished, close the dialog. Control continues after
208 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
209 gdk_threads_enter(); /* CHECKED */
210 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
211 gdk_threads_leave(); /* CHECKED */
217 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
223 ModestPairList *pairs;
225 ModestProtocolRegistry *protocol_registry;
226 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
229 g_return_if_fail (user_data);
230 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
231 g_return_if_fail (TNY_IS_LIST(auth_types));
233 info = (ModestGetSupportedAuthInfo *) user_data;
235 /* Free everything if the actual action was canceled */
237 g_debug ("%s: operation canceled\n", __FUNCTION__);
242 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
247 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
251 if (tny_list_get_length(auth_types) == 0) {
252 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
256 protocol_registry = modest_runtime_get_protocol_registry ();
257 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
259 /* Get the enum value for the strings: */
261 iter = tny_list_create_iterator(auth_types);
262 while (!tny_iterator_is_done(iter)) {
264 const gchar *auth_name;
265 ModestProtocolType protocol_type;
267 pair = TNY_PAIR(tny_iterator_get_current(iter));
270 auth_name = tny_pair_get_name(pair);
271 g_object_unref (pair);
275 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
277 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
278 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
281 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
282 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
284 tny_iterator_next(iter);
286 g_object_unref (iter);
288 modest_pair_list_free (pairs);
289 *(info->result) = result;
292 /* Close the dialog in a main thread */
293 g_idle_add(on_idle_secure_auth_finished, info->dialog);
296 g_slice_free (ModestGetSupportedAuthInfo, info);
301 gboolean not_finished;
305 keep_pulsing (gpointer user_data)
307 KeepPulsing *info = (KeepPulsing *) user_data;
309 if (!info->not_finished) {
310 g_slice_free (KeepPulsing, info);
314 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
319 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
320 const gchar* hostname,
322 const gchar* username,
323 GtkWindow *parent_window,
326 TnyAccount * tny_account = NULL;
327 ModestProtocolRegistry *protocol_registry;
330 ModestTnyAccountStore *account_store;
331 TnySessionCamel *session = NULL;
332 ModestProtocol *protocol = NULL;
333 GList *result = NULL;
336 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
338 protocol_registry = modest_runtime_get_protocol_registry ();
340 /* We need a connection to get the capabilities; */
341 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
344 /* Create a TnyCamelAccount so we can use
345 * tny_camel_account_get_supported_secure_authentication(): */
346 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
348 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
349 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
353 g_printerr ("%s could not create tny account.", __FUNCTION__);
357 /* Set proto, so that the prepare_func() vfunc will work when
358 * we call set_session(): */
359 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
360 tny_account_set_id (tny_account, "temp_account");
361 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
362 tny_account_set_hostname (tny_account, hostname);
363 tny_account_set_user (tny_account, username);
366 tny_account_set_port (tny_account, port);
368 /* Set the session for the account, so we can use it: */
369 account_store = modest_runtime_get_account_store ();
370 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
371 g_return_val_if_fail (session, NULL);
372 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
374 dialog = gtk_dialog_new_with_buttons(" ",
376 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
377 _("mcen_bd_dialog_cancel"),
381 /* Ask camel to ask the server, asynchronously: */
382 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
383 info->result = &result;
384 info->dialog = dialog;
386 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
387 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
388 progress = gtk_progress_bar_new();
389 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
390 gtk_widget_show_all(info->dialog);
392 KeepPulsing *pi = g_slice_new (KeepPulsing);
393 pi->progress = progress;
394 pi->not_finished = TRUE;
396 /* Starts the pulsing of the progressbar */
397 g_timeout_add (500, keep_pulsing, pi);
399 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
400 on_camel_account_get_supported_secure_authentication,
404 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
406 pi->not_finished = FALSE;
407 /* pi is freed in the timeout itself to avoid a GCond here */
409 gtk_widget_destroy(dialog);
412 tny_account_cancel (tny_account);
413 g_object_unref (tny_account);
419 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
422 g_return_if_fail (GTK_IS_WINDOW(parent_window));
423 g_return_if_fail (GTK_IS_DIALOG(dialog));
425 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
427 /* Destroy the dialog when it is closed: */
428 g_signal_connect_swapped (dialog,
430 G_CALLBACK (gtk_widget_destroy),
433 gtk_widget_show (GTK_WIDGET (dialog));
437 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
439 GSList *proxies = NULL;
441 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
443 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
444 proxies != NULL; proxies = g_slist_next (proxies)) {
445 GtkWidget *widget = (GtkWidget *) proxies->data;
446 gtk_action_block_activate_from (GTK_ACTION (action), widget);
449 gtk_toggle_action_set_active (action, value);
451 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
452 proxies != NULL; proxies = g_slist_next (proxies)) {
453 GtkWidget *widget = (GtkWidget *) proxies->data;
454 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
461 modest_list_index (TnyList *list, GObject *object)
466 g_return_val_if_fail (TNY_IS_LIST(list), -1);
467 g_return_val_if_fail (G_IS_OBJECT(object), -1);
469 iter = tny_list_create_iterator (list);
470 while (!tny_iterator_is_done (iter)) {
471 GObject *current = tny_iterator_get_current (iter);
473 g_object_unref (current);
474 if (current == object)
477 tny_iterator_next (iter);
481 if (tny_iterator_is_done (iter))
483 g_object_unref (iter);
488 modest_utils_get_available_space (const gchar *maildir_path)
493 GnomeVFSFileSize size;
495 folder = modest_local_folder_info_get_maildir_path (maildir_path);
496 uri_string = gnome_vfs_get_uri_from_local_path (folder);
497 uri = gnome_vfs_uri_new (uri_string);
502 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
504 gnome_vfs_uri_unref (uri);
509 return (guint64) size;
512 on_destroy_dialog (GtkDialog *dialog)
514 gtk_widget_destroy (GTK_WIDGET(dialog));
515 if (gtk_events_pending ())
516 gtk_main_iteration ();
520 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
524 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
525 g_return_val_if_fail (key, 0);
527 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
528 if (sort_key < 0 || sort_key >= max) {
529 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
532 return (guint)sort_key;
536 launch_sort_headers_dialog (GtkWindow *parent_window,
539 ModestHeaderView *header_view = NULL;
541 GtkSortType sort_type;
543 gint default_key = 0;
545 gboolean outgoing = FALSE;
546 gint current_sort_colid = -1;
547 GtkSortType current_sort_type;
548 gint attachments_sort_id;
549 gint priority_sort_id;
550 GtkTreeSortable *sortable;
552 /* Get header window */
553 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
554 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
555 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
556 #ifdef MODEST_TOOLKIT_HILDON2
557 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
558 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
565 /* Add sorting keys */
566 cols = modest_header_view_get_columns (header_view);
569 #define SORT_ID_NUM 6
570 int sort_model_ids[SORT_ID_NUM];
571 int sort_ids[SORT_ID_NUM];
573 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
574 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
576 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
579 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
580 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
582 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
583 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
586 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
589 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
590 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
592 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
593 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
595 default_key = sort_key;
597 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
599 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
601 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
603 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
605 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
607 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
608 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
609 attachments_sort_id = sort_key;
611 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
613 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
614 sort_ids[sort_key] = 0;
616 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
618 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
619 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
620 priority_sort_id = sort_key;
622 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
624 if (!gtk_tree_sortable_get_sort_column_id (sortable,
625 ¤t_sort_colid, ¤t_sort_type)) {
626 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
627 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
629 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
630 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
631 gpointer flags_sort_type_pointer;
632 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
633 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
634 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
636 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
638 gint current_sort_keyid = 0;
639 while (current_sort_keyid < SORT_ID_NUM) {
640 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
643 current_sort_keyid++;
645 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
649 result = gtk_dialog_run (GTK_DIALOG (dialog));
650 if (result == GTK_RESPONSE_OK) {
651 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
652 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
653 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
657 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
658 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
659 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
660 GINT_TO_POINTER (sort_ids[sort_key]));
661 /* This is a hack to make it resort rows always when flag fields are
662 * selected. If we do not do this, changing sort field from priority to
663 * attachments does not work */
664 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
666 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
667 sort_model_ids[sort_key]);
670 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
671 gtk_tree_sortable_sort_column_changed (sortable);
674 modest_widget_memory_save (modest_runtime_get_conf (),
675 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
682 modest_utils_run_sort_dialog (GtkWindow *parent_window,
683 ModestSortDialogType type)
685 GtkWidget *dialog = NULL;
688 dialog = modest_platform_create_sort_dialog (parent_window);
691 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
692 GTK_WINDOW (dialog), parent_window);
696 case MODEST_SORT_HEADERS:
697 launch_sort_headers_dialog (parent_window,
703 on_destroy_dialog (GTK_DIALOG(dialog));
708 modest_images_cache_get_id (const gchar *account, const gchar *uri)
710 GnomeVFSURI *vfs_uri;
713 vfs_uri = gnome_vfs_uri_new (uri);
717 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
718 gnome_vfs_uri_unref (vfs_uri);
724 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
726 gchar *account_name = NULL;
727 ModestAccountMgr *mgr = NULL;
728 GSList *accounts = NULL, *node = NULL;
732 g_return_val_if_fail (from_header, NULL);
734 mgr = modest_runtime_get_account_mgr ();
735 accounts = modest_account_mgr_account_names (mgr, TRUE);
737 for (node = accounts; node != NULL; node = g_slist_next (node)) {
739 gchar *transport_account;
741 if (!strcmp (from_header, node->data)) {
742 account_name = g_strdup (node->data);
746 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
747 (const gchar *) node->data,
748 TNY_ACCOUNT_TYPE_TRANSPORT);
749 if (transport_account) {
751 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
754 ModestProtocol *protocol =
755 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
756 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
758 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
759 ModestPairList *pair_list;
761 gchar *from_header_email =
762 modest_text_utils_get_email_address (from_header);
763 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
766 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
768 account_name = g_strdup (node->data);
770 *mailbox = g_strdup (from_header_email);
773 modest_pair_list_free (pair_list);
778 g_free (transport_account);
780 if (mailbox && *mailbox)
784 modest_account_mgr_get_from_string (mgr, node->data, NULL);
788 modest_text_utils_get_email_address (from);
789 gchar *from_header_email =
790 modest_text_utils_get_email_address (from_header);
792 if (from_email && from_header_email) {
793 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
794 account_name = g_strdup (node->data);
801 g_free (from_header_email);
807 g_slist_foreach (accounts, (GFunc) g_free, NULL);
808 g_slist_free (accounts);
814 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
815 const gchar* character,
818 gchar *message = NULL;
819 const gchar *show_char = NULL;
822 show_char = character;
827 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
828 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
833 modest_utils_open_mcc_mapping_file (gboolean from_lc_messages, gboolean *translated)
837 const gchar *env_list;
838 gchar **parts, **node;
840 if (from_lc_messages) {
841 env_list = setlocale (LC_MESSAGES, NULL);
843 env_list = getenv ("LANG");
845 parts = g_strsplit (env_list, ":", 0);
847 const gchar* path2 = MODEST_MCC_MAPPING;
853 for (node = parts; path == NULL && node != NULL && *node != NULL && **node != '\0'; node++) {
854 path1 = g_strdup_printf ("%s.%s", MODEST_OPERATOR_WIZARD_MCC_MAPPING, *node);
855 if (access (path1, R_OK) == 0) {
866 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
867 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
870 } else if (access (path2, R_OK) == 0) {
873 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
874 __FUNCTION__, path1, path2);
879 result = fopen (path, "r");
881 g_warning ("%s: error opening mapping file '%s': %s",
882 __FUNCTION__, path, strerror(errno));
890 /* cluster mcc's, based on the list
891 * http://en.wikipedia.org/wiki/Mobile_country_code
894 effective_mcc (gint mcc)
897 case 405: return 404; /* india */
898 case 441: return 440; /* japan */
899 case 235: return 234; /* united kingdom */
905 case 316: return 310; /* united states */
910 /* each line is of the form:
913 NOTE: this function is NOT re-entrant, the out-param country
914 are static strings that should NOT be freed. and will change when
915 calling this function again
917 also note, this function will return the "effective mcc", which
918 is the normalized mcc for a country - ie. even if the there
919 are multiple entries for the United States with various mccs,
920 this function will always return 310, even if the real mcc parsed
921 would be 314. see the 'effective_mcc' function above.
924 parse_mcc_mapping_line (const char* line, char** country)
926 char mcc[4]; /* the mcc code, always 3 bytes*/
927 gchar *iter, *tab, *final;
934 /* Go to the first tab (Country separator) */
935 tab = g_utf8_strrchr (line, -1, '\t');
939 *country = g_utf8_find_next_char (tab, NULL);
941 /* Replace by end of string. We need to use strlen, because
942 g_utf8_strrchr expects bytes and not UTF8 characters */
943 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\n');
944 if (G_LIKELY (final))
947 tab[strlen(tab) - 1] = '\0';
950 mcc[0] = g_utf8_get_char (line);
951 iter = g_utf8_find_next_char (line, NULL);
952 mcc[1] = g_utf8_get_char (iter);
953 iter = g_utf8_find_next_char (iter, NULL);
954 mcc[2] = g_utf8_get_char (iter);
957 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
960 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
962 /** Note that the mcc_mapping file is installed
963 * by the operator-wizard-settings package.
966 modest_utils_create_country_model (void)
970 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
976 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
979 char line[MCC_FILE_MAX_LINE_LEN];
980 guint previous_mcc = 0;
982 GHashTable *country_hash;
985 /* First we need to know our current region */
986 file = modest_utils_open_mcc_mapping_file (FALSE, &translated);
988 g_warning ("Could not open mcc_mapping file");
992 /* Get the territory specified for the current locale */
993 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
995 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
997 char *country = NULL;
999 mcc = parse_mcc_mapping_line (line, &country);
1000 if (!country || mcc == 0) {
1001 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1005 if (mcc == previous_mcc) {
1006 /* g_warning ("already seen: %s", line); */
1011 if (!(*locale_mcc)) {
1013 if (!g_utf8_collate (country, territory))
1016 gchar *translation = dgettext ("osso-countries", country);
1017 if (!g_utf8_collate (translation, territory))
1024 /* Now we fill the model */
1025 file = modest_utils_open_mcc_mapping_file (TRUE, &translated);
1027 g_warning ("Could not open mcc_mapping file");
1031 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1032 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1035 char *country = NULL;
1037 const gchar *name_translated;
1039 mcc = parse_mcc_mapping_line (line, &country);
1040 if (!country || mcc == 0) {
1041 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1045 if (mcc == previous_mcc ||
1046 g_hash_table_lookup (country_hash, country)) {
1047 g_debug ("already seen: '%s' %d", country, mcc);
1052 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1054 name_translated = dgettext ("osso-countries", country);
1056 /* Add the row to the model: */
1057 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1058 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1059 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1060 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1065 g_hash_table_unref (country_hash);
1068 /* Fallback to Finland */
1072 /* Sort the items: */
1073 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1074 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1078 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1080 GList *new_headers_list;
1083 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1084 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1086 new_headers_list = NULL;
1087 iter = tny_list_create_iterator (header_list);
1088 while (!tny_iterator_is_done (iter)) {
1089 ModestMsgNotificationData *data;
1093 header = (TnyHeader *) tny_iterator_get_current (iter);
1095 folder = tny_header_get_folder (header);
1100 uid = tny_header_dup_uid (header);
1101 uri = g_strdup_printf ("%s/%s",
1102 tny_folder_get_url_string (folder),
1106 /* Create data & add to list */
1107 data = g_slice_new0 (ModestMsgNotificationData);
1108 data->subject = tny_header_dup_subject (header);
1109 data->from = tny_header_dup_from (header);
1112 new_headers_list = g_list_append (new_headers_list, data);
1114 g_object_unref (folder);
1116 g_object_unref (header);
1118 tny_iterator_next (iter);
1120 g_object_unref (iter);
1122 return new_headers_list;
1126 free_notification_data (gpointer data,
1129 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1131 g_free (notification_data->from);
1132 g_free (notification_data->subject);
1133 g_free (notification_data->uri);
1137 modest_utils_free_notification_list (GList *notification_list)
1139 g_return_if_fail (g_list_length (notification_list) > 0);
1141 g_list_foreach (notification_list, free_notification_data, NULL);
1142 g_list_free (notification_list);
1146 modest_utils_flush_send_queue (const gchar *account_id)
1148 TnyTransportAccount *account;
1150 /* Get the transport account */
1151 account = (TnyTransportAccount *)
1152 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1154 TNY_ACCOUNT_TYPE_TRANSPORT);
1156 ModestMailOperation *wakeup_op;
1157 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue (account, TRUE);
1160 wakeup_op = modest_mail_operation_new (NULL);
1161 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1163 modest_mail_operation_queue_wakeup (wakeup_op, send_queue);
1165 g_object_unref (account);