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 tmp = g_uri_escape_string (orig_name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, FALSE);
139 if (strlen(tmp) > 200) {
141 g_warning ("%s: filename too long ('%s')",
142 __FUNCTION__, orig_name);
146 if (g_strstr_len (tmp, strlen (tmp), "/") != NULL) {
148 g_warning ("%s: filename contains '/' character(s) (%s)",
149 __FUNCTION__, orig_name);
153 /* make a random subdir under /tmp or /var/tmp */
154 if (hash_base != NULL) {
155 hash_number = g_str_hash (hash_base);
157 hash_number = (guint) random ();
159 tmpdir = g_strdup_printf ("%s/%u", g_get_tmp_dir (), hash_number);
160 if ((g_access (tmpdir, R_OK) == -1) && (g_mkdir (tmpdir, 0755) == -1)) {
161 g_warning ("%s: failed to create dir '%s': %s",
162 __FUNCTION__, tmpdir, g_strerror(errno));
167 filepath = g_build_filename (tmpdir, tmp, NULL);
170 /* if file exists, first we try to remove it */
171 if (g_access (filepath, F_OK) == 0)
174 /* don't overwrite if it already exists, even if it is writable */
175 if (g_access (filepath, F_OK) == 0) {
184 /* try to write the file there */
185 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
187 g_warning ("%s: failed to create '%s': %s",
188 __FUNCTION__, filepath, g_strerror(errno));
202 return TNY_FS_STREAM (tny_fs_stream_new (fd));
210 } ModestGetSupportedAuthInfo;
213 on_idle_secure_auth_finished (gpointer user_data)
215 /* Operation has finished, close the dialog. Control continues after
216 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
217 gdk_threads_enter(); /* CHECKED */
218 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
219 gdk_threads_leave(); /* CHECKED */
225 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
231 ModestPairList *pairs;
233 ModestProtocolRegistry *protocol_registry;
234 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
237 g_return_if_fail (user_data);
238 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
239 g_return_if_fail (TNY_IS_LIST(auth_types));
241 info = (ModestGetSupportedAuthInfo *) user_data;
243 /* Free everything if the actual action was canceled */
245 g_debug ("%s: operation canceled\n", __FUNCTION__);
250 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
255 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
259 if (tny_list_get_length(auth_types) == 0) {
260 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
264 protocol_registry = modest_runtime_get_protocol_registry ();
265 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
267 /* Get the enum value for the strings: */
269 iter = tny_list_create_iterator(auth_types);
270 while (!tny_iterator_is_done(iter)) {
272 const gchar *auth_name;
273 ModestProtocolType protocol_type;
275 pair = TNY_PAIR(tny_iterator_get_current(iter));
278 auth_name = tny_pair_get_name(pair);
279 g_object_unref (pair);
283 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
285 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
286 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
289 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
290 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
292 tny_iterator_next(iter);
294 g_object_unref (iter);
296 modest_pair_list_free (pairs);
297 *(info->result) = result;
300 /* Close the dialog in a main thread */
301 g_idle_add(on_idle_secure_auth_finished, info->dialog);
304 g_slice_free (ModestGetSupportedAuthInfo, info);
309 gboolean not_finished;
313 keep_pulsing (gpointer user_data)
315 KeepPulsing *info = (KeepPulsing *) user_data;
317 if (!info->not_finished) {
318 g_slice_free (KeepPulsing, info);
322 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
327 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
328 const gchar* hostname,
330 const gchar* username,
331 GtkWindow *parent_window,
334 TnyAccount * tny_account = NULL;
335 ModestProtocolRegistry *protocol_registry;
338 ModestTnyAccountStore *account_store;
339 TnySessionCamel *session = NULL;
340 ModestProtocol *protocol = NULL;
341 GList *result = NULL;
344 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
346 protocol_registry = modest_runtime_get_protocol_registry ();
348 /* We need a connection to get the capabilities; */
349 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
352 /* Create a TnyCamelAccount so we can use
353 * tny_camel_account_get_supported_secure_authentication(): */
354 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
356 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
357 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
361 g_printerr ("%s could not create tny account.", __FUNCTION__);
365 /* Set proto, so that the prepare_func() vfunc will work when
366 * we call set_session(): */
367 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
368 tny_account_set_id (tny_account, "temp_account");
369 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
370 tny_account_set_hostname (tny_account, hostname);
371 tny_account_set_user (tny_account, username);
374 tny_account_set_port (tny_account, port);
376 /* Set the session for the account, so we can use it: */
377 account_store = modest_runtime_get_account_store ();
378 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
379 g_return_val_if_fail (session, NULL);
380 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
382 dialog = gtk_dialog_new_with_buttons(" ",
384 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
385 _("mcen_bd_dialog_cancel"),
389 /* Ask camel to ask the server, asynchronously: */
390 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
391 info->result = &result;
392 info->dialog = dialog;
394 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
395 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
396 progress = gtk_progress_bar_new();
397 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
398 gtk_widget_show_all(info->dialog);
400 KeepPulsing *pi = g_slice_new (KeepPulsing);
401 pi->progress = progress;
402 pi->not_finished = TRUE;
404 /* Starts the pulsing of the progressbar */
405 g_timeout_add (500, keep_pulsing, pi);
407 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
408 on_camel_account_get_supported_secure_authentication,
412 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
414 pi->not_finished = FALSE;
415 /* pi is freed in the timeout itself to avoid a GCond here */
417 gtk_widget_destroy(dialog);
420 tny_account_cancel (tny_account);
421 g_object_unref (tny_account);
427 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
430 g_return_if_fail (GTK_IS_WINDOW(parent_window));
431 g_return_if_fail (GTK_IS_DIALOG(dialog));
433 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
435 /* Destroy the dialog when it is closed: */
436 g_signal_connect_swapped (dialog,
438 G_CALLBACK (gtk_widget_destroy),
441 gtk_widget_show (GTK_WIDGET (dialog));
445 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
447 GSList *proxies = NULL;
449 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
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_block_activate_from (GTK_ACTION (action), widget);
457 gtk_toggle_action_set_active (action, value);
459 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
460 proxies != NULL; proxies = g_slist_next (proxies)) {
461 GtkWidget *widget = (GtkWidget *) proxies->data;
462 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
469 modest_list_index (TnyList *list, GObject *object)
474 g_return_val_if_fail (TNY_IS_LIST(list), -1);
475 g_return_val_if_fail (G_IS_OBJECT(object), -1);
477 iter = tny_list_create_iterator (list);
478 while (!tny_iterator_is_done (iter)) {
479 GObject *current = tny_iterator_get_current (iter);
481 g_object_unref (current);
482 if (current == object)
485 tny_iterator_next (iter);
489 if (tny_iterator_is_done (iter))
491 g_object_unref (iter);
496 modest_utils_get_available_space (const gchar *maildir_path)
501 GnomeVFSFileSize size;
503 folder = modest_local_folder_info_get_maildir_path (maildir_path);
504 uri_string = gnome_vfs_get_uri_from_local_path (folder);
505 uri = gnome_vfs_uri_new (uri_string);
510 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
512 gnome_vfs_uri_unref (uri);
517 return (guint64) size;
520 on_destroy_dialog (GtkDialog *dialog)
522 gtk_widget_destroy (GTK_WIDGET(dialog));
523 if (gtk_events_pending ())
524 gtk_main_iteration ();
528 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
532 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
533 g_return_val_if_fail (key, 0);
535 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
536 if (sort_key < 0 || sort_key >= max) {
537 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
540 return (guint)sort_key;
544 launch_sort_headers_dialog (GtkWindow *parent_window,
547 ModestHeaderView *header_view = NULL;
549 GtkSortType sort_type;
551 gint default_key = 0;
553 gboolean outgoing = FALSE;
554 gint current_sort_colid = -1;
555 GtkSortType current_sort_type;
556 gint attachments_sort_id;
557 gint priority_sort_id;
558 GtkTreeSortable *sortable;
560 /* Get header window */
561 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
562 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
563 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
564 #ifdef MODEST_TOOLKIT_HILDON2
565 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
566 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
573 /* Add sorting keys */
574 cols = modest_header_view_get_columns (header_view);
577 #define SORT_ID_NUM 6
578 int sort_model_ids[SORT_ID_NUM];
579 int sort_ids[SORT_ID_NUM];
581 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
582 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
584 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
587 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
588 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
590 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
591 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
594 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
597 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
598 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
600 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
601 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
603 default_key = sort_key;
605 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
607 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
609 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
611 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
613 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
615 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
616 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
617 attachments_sort_id = sort_key;
619 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
621 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
622 sort_ids[sort_key] = 0;
624 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
626 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
627 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
628 priority_sort_id = sort_key;
630 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
632 if (!gtk_tree_sortable_get_sort_column_id (sortable,
633 ¤t_sort_colid, ¤t_sort_type)) {
634 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
635 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
637 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
638 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
639 gpointer flags_sort_type_pointer;
640 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
641 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
642 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
644 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
646 gint current_sort_keyid = 0;
647 while (current_sort_keyid < SORT_ID_NUM) {
648 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
651 current_sort_keyid++;
653 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
657 result = gtk_dialog_run (GTK_DIALOG (dialog));
658 if (result == GTK_RESPONSE_OK) {
659 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
660 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
661 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
665 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
666 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
667 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
668 GINT_TO_POINTER (sort_ids[sort_key]));
669 /* This is a hack to make it resort rows always when flag fields are
670 * selected. If we do not do this, changing sort field from priority to
671 * attachments does not work */
672 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
674 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
675 sort_model_ids[sort_key]);
678 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
679 gtk_tree_sortable_sort_column_changed (sortable);
682 modest_widget_memory_save (modest_runtime_get_conf (),
683 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
690 modest_utils_run_sort_dialog (GtkWindow *parent_window,
691 ModestSortDialogType type)
693 GtkWidget *dialog = NULL;
696 dialog = modest_platform_create_sort_dialog (parent_window);
699 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
700 GTK_WINDOW (dialog), parent_window);
704 case MODEST_SORT_HEADERS:
705 launch_sort_headers_dialog (parent_window,
711 on_destroy_dialog (GTK_DIALOG(dialog));
716 modest_images_cache_get_id (const gchar *account, const gchar *uri)
718 GnomeVFSURI *vfs_uri;
721 vfs_uri = gnome_vfs_uri_new (uri);
725 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
726 gnome_vfs_uri_unref (vfs_uri);
732 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
734 gchar *account_name = NULL;
735 ModestAccountMgr *mgr = NULL;
736 GSList *accounts = NULL, *node = NULL;
740 g_return_val_if_fail (from_header, NULL);
742 mgr = modest_runtime_get_account_mgr ();
743 accounts = modest_account_mgr_account_names (mgr, TRUE);
745 for (node = accounts; node != NULL; node = g_slist_next (node)) {
747 gchar *transport_account;
749 if (!strcmp (from_header, node->data)) {
750 account_name = g_strdup (node->data);
754 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
755 (const gchar *) node->data,
756 TNY_ACCOUNT_TYPE_TRANSPORT);
757 if (transport_account) {
759 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
762 ModestProtocol *protocol =
763 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
764 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
766 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
767 ModestPairList *pair_list;
769 gchar *from_header_email =
770 modest_text_utils_get_email_address (from_header);
771 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
774 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
776 account_name = g_strdup (node->data);
778 *mailbox = g_strdup (from_header_email);
781 modest_pair_list_free (pair_list);
786 g_free (transport_account);
788 if (mailbox && *mailbox)
792 modest_account_mgr_get_from_string (mgr, node->data, NULL);
796 modest_text_utils_get_email_address (from);
797 gchar *from_header_email =
798 modest_text_utils_get_email_address (from_header);
800 if (from_email && from_header_email) {
801 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
802 account_name = g_strdup (node->data);
809 g_free (from_header_email);
815 g_slist_foreach (accounts, (GFunc) g_free, NULL);
816 g_slist_free (accounts);
822 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
823 const gchar* character,
826 gchar *message = NULL;
827 const gchar *show_char = NULL;
830 show_char = character;
835 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
836 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
841 modest_utils_open_mcc_mapping_file (gboolean from_lc_messages, gboolean *translated)
845 const gchar *env_list;
846 gchar **parts, **node;
848 if (from_lc_messages) {
849 env_list = setlocale (LC_MESSAGES, NULL);
851 env_list = getenv ("LANG");
853 parts = g_strsplit (env_list, ":", 0);
855 const gchar* path2 = MODEST_MCC_MAPPING;
861 for (node = parts; path == NULL && node != NULL && *node != NULL && **node != '\0'; node++) {
862 path1 = g_strdup_printf ("%s.%s", MODEST_OPERATOR_WIZARD_MCC_MAPPING, *node);
863 if (access (path1, R_OK) == 0) {
874 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
875 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
878 } else if (access (path2, R_OK) == 0) {
881 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
882 __FUNCTION__, path1, path2);
887 result = fopen (path, "r");
889 g_warning ("%s: error opening mapping file '%s': %s",
890 __FUNCTION__, path, strerror(errno));
898 /* cluster mcc's, based on the list
899 * http://en.wikipedia.org/wiki/Mobile_country_code
902 effective_mcc (gint mcc)
905 case 405: return 404; /* india */
906 case 441: return 440; /* japan */
907 case 235: return 234; /* united kingdom */
913 case 316: return 310; /* united states */
918 /* each line is of the form:
921 NOTE: this function is NOT re-entrant, the out-param country
922 are static strings that should NOT be freed. and will change when
923 calling this function again
925 also note, this function will return the "effective mcc", which
926 is the normalized mcc for a country - ie. even if the there
927 are multiple entries for the United States with various mccs,
928 this function will always return 310, even if the real mcc parsed
929 would be 314. see the 'effective_mcc' function above.
932 parse_mcc_mapping_line (const char* line, char** country)
934 char mcc[4]; /* the mcc code, always 3 bytes*/
935 gchar *iter, *tab, *final;
942 /* Go to the first tab (Country separator) */
943 tab = g_utf8_strrchr (line, -1, '\t');
947 *country = g_utf8_find_next_char (tab, NULL);
949 /* Replace by end of string. We need to use strlen, because
950 g_utf8_strrchr expects bytes and not UTF8 characters */
951 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\n');
952 if (G_LIKELY (final))
955 tab[strlen(tab) - 1] = '\0';
958 mcc[0] = g_utf8_get_char (line);
959 iter = g_utf8_find_next_char (line, NULL);
960 mcc[1] = g_utf8_get_char (iter);
961 iter = g_utf8_find_next_char (iter, NULL);
962 mcc[2] = g_utf8_get_char (iter);
965 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
968 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
970 /** Note that the mcc_mapping file is installed
971 * by the operator-wizard-settings package.
974 modest_utils_create_country_model (void)
978 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
984 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
987 char line[MCC_FILE_MAX_LINE_LEN];
988 guint previous_mcc = 0;
990 GHashTable *country_hash;
993 /* First we need to know our current region */
994 file = modest_utils_open_mcc_mapping_file (FALSE, &translated);
996 g_warning ("Could not open mcc_mapping file");
1000 /* Get the territory specified for the current locale */
1001 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
1003 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1005 char *country = NULL;
1007 mcc = parse_mcc_mapping_line (line, &country);
1008 if (!country || mcc == 0) {
1009 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1013 if (mcc == previous_mcc) {
1014 /* g_warning ("already seen: %s", line); */
1019 if (!(*locale_mcc)) {
1021 if (!g_utf8_collate (country, territory))
1024 gchar *translation = dgettext ("osso-countries", country);
1025 if (!g_utf8_collate (translation, territory))
1032 /* Now we fill the model */
1033 file = modest_utils_open_mcc_mapping_file (TRUE, &translated);
1035 g_warning ("Could not open mcc_mapping file");
1039 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1040 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1043 char *country = NULL;
1045 const gchar *name_translated;
1047 mcc = parse_mcc_mapping_line (line, &country);
1048 if (!country || mcc == 0) {
1049 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1053 if (mcc == previous_mcc ||
1054 g_hash_table_lookup (country_hash, country)) {
1055 g_debug ("already seen: '%s' %d", country, mcc);
1060 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1062 name_translated = dgettext ("osso-countries", country);
1064 /* Add the row to the model: */
1065 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1066 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1067 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1068 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1073 g_hash_table_unref (country_hash);
1076 /* Fallback to Finland */
1080 /* Sort the items: */
1081 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1082 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1086 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1088 GList *new_headers_list;
1091 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1092 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1094 new_headers_list = NULL;
1095 iter = tny_list_create_iterator (header_list);
1096 while (!tny_iterator_is_done (iter)) {
1097 ModestMsgNotificationData *data;
1101 header = (TnyHeader *) tny_iterator_get_current (iter);
1103 folder = tny_header_get_folder (header);
1108 uid = tny_header_dup_uid (header);
1109 uri = g_strdup_printf ("%s/%s",
1110 tny_folder_get_url_string (folder),
1114 /* Create data & add to list */
1115 data = g_slice_new0 (ModestMsgNotificationData);
1116 data->subject = tny_header_dup_subject (header);
1117 data->from = tny_header_dup_from (header);
1120 new_headers_list = g_list_append (new_headers_list, data);
1122 g_object_unref (folder);
1124 g_object_unref (header);
1126 tny_iterator_next (iter);
1128 g_object_unref (iter);
1130 return new_headers_list;
1134 free_notification_data (gpointer data,
1137 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1139 g_free (notification_data->from);
1140 g_free (notification_data->subject);
1141 g_free (notification_data->uri);
1143 g_slice_free (ModestMsgNotificationData, notification_data);
1147 modest_utils_free_notification_list (GList *notification_list)
1149 g_return_if_fail (g_list_length (notification_list) > 0);
1151 g_list_foreach (notification_list, free_notification_data, NULL);
1152 g_list_free (notification_list);
1156 modest_utils_flush_send_queue (const gchar *account_id)
1158 TnyTransportAccount *account;
1160 /* Get the transport account */
1161 account = (TnyTransportAccount *)
1162 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1164 TNY_ACCOUNT_TYPE_TRANSPORT);
1166 ModestMailOperation *wakeup_op;
1167 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue (account, TRUE);
1170 wakeup_op = modest_mail_operation_new (NULL);
1171 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1173 modest_mail_operation_queue_wakeup (wakeup_op, send_queue);
1175 g_object_unref (account);