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 filepath = g_build_filename (tmpdir, orig_name, NULL);
165 /* if file exists, first we try to remove it */
166 if (g_access (filepath, F_OK) == 0)
169 /* don't overwrite if it already exists, even if it is writable */
170 if (g_access (filepath, F_OK) == 0) {
179 /* try to write the file there */
180 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
182 g_warning ("%s: failed to create '%s': %s",
183 __FUNCTION__, filepath, g_strerror(errno));
197 return TNY_FS_STREAM (tny_fs_stream_new (fd));
205 } ModestGetSupportedAuthInfo;
208 on_idle_secure_auth_finished (gpointer user_data)
210 /* Operation has finished, close the dialog. Control continues after
211 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
212 gdk_threads_enter(); /* CHECKED */
213 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
214 gdk_threads_leave(); /* CHECKED */
220 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
226 ModestPairList *pairs;
228 ModestProtocolRegistry *protocol_registry;
229 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
232 g_return_if_fail (user_data);
233 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
234 g_return_if_fail (TNY_IS_LIST(auth_types));
236 info = (ModestGetSupportedAuthInfo *) user_data;
238 /* Free everything if the actual action was canceled */
240 g_debug ("%s: operation canceled\n", __FUNCTION__);
245 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
250 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
254 if (tny_list_get_length(auth_types) == 0) {
255 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
259 protocol_registry = modest_runtime_get_protocol_registry ();
260 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
262 /* Get the enum value for the strings: */
264 iter = tny_list_create_iterator(auth_types);
265 while (!tny_iterator_is_done(iter)) {
267 const gchar *auth_name;
268 ModestProtocolType protocol_type;
270 pair = TNY_PAIR(tny_iterator_get_current(iter));
273 auth_name = tny_pair_get_name(pair);
274 g_object_unref (pair);
278 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
280 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
281 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
284 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
285 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
287 tny_iterator_next(iter);
289 g_object_unref (iter);
291 modest_pair_list_free (pairs);
292 *(info->result) = result;
295 /* Close the dialog in a main thread */
296 g_idle_add(on_idle_secure_auth_finished, info->dialog);
299 g_slice_free (ModestGetSupportedAuthInfo, info);
304 gboolean not_finished;
308 keep_pulsing (gpointer user_data)
310 KeepPulsing *info = (KeepPulsing *) user_data;
312 if (!info->not_finished) {
313 g_slice_free (KeepPulsing, info);
317 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
322 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
323 const gchar* hostname,
325 const gchar* username,
326 GtkWindow *parent_window,
329 TnyAccount * tny_account = NULL;
330 ModestProtocolRegistry *protocol_registry;
333 ModestTnyAccountStore *account_store;
334 TnySessionCamel *session = NULL;
335 ModestProtocol *protocol = NULL;
336 GList *result = NULL;
339 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
341 protocol_registry = modest_runtime_get_protocol_registry ();
343 /* We need a connection to get the capabilities; */
344 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
347 /* Create a TnyCamelAccount so we can use
348 * tny_camel_account_get_supported_secure_authentication(): */
349 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
351 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
352 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
356 g_printerr ("%s could not create tny account.", __FUNCTION__);
360 /* Set proto, so that the prepare_func() vfunc will work when
361 * we call set_session(): */
362 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
363 tny_account_set_id (tny_account, "temp_account");
364 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
365 tny_account_set_hostname (tny_account, hostname);
366 tny_account_set_user (tny_account, username);
369 tny_account_set_port (tny_account, port);
371 /* Set the session for the account, so we can use it: */
372 account_store = modest_runtime_get_account_store ();
373 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
374 g_return_val_if_fail (session, NULL);
375 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
377 dialog = gtk_dialog_new_with_buttons(" ",
379 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
380 _("mcen_bd_dialog_cancel"),
384 /* Ask camel to ask the server, asynchronously: */
385 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
386 info->result = &result;
387 info->dialog = dialog;
389 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
390 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
391 progress = gtk_progress_bar_new();
392 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
393 gtk_widget_show_all(info->dialog);
395 KeepPulsing *pi = g_slice_new (KeepPulsing);
396 pi->progress = progress;
397 pi->not_finished = TRUE;
399 /* Starts the pulsing of the progressbar */
400 g_timeout_add (500, keep_pulsing, pi);
402 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
403 on_camel_account_get_supported_secure_authentication,
407 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
409 pi->not_finished = FALSE;
410 /* pi is freed in the timeout itself to avoid a GCond here */
412 gtk_widget_destroy(dialog);
415 tny_account_cancel (tny_account);
416 g_object_unref (tny_account);
422 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
425 g_return_if_fail (GTK_IS_WINDOW(parent_window));
426 g_return_if_fail (GTK_IS_DIALOG(dialog));
428 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
430 /* Destroy the dialog when it is closed: */
431 g_signal_connect_swapped (dialog,
433 G_CALLBACK (gtk_widget_destroy),
436 gtk_widget_show (GTK_WIDGET (dialog));
440 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
442 GSList *proxies = NULL;
444 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
446 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
447 proxies != NULL; proxies = g_slist_next (proxies)) {
448 GtkWidget *widget = (GtkWidget *) proxies->data;
449 gtk_action_block_activate_from (GTK_ACTION (action), widget);
452 gtk_toggle_action_set_active (action, value);
454 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
455 proxies != NULL; proxies = g_slist_next (proxies)) {
456 GtkWidget *widget = (GtkWidget *) proxies->data;
457 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
464 modest_list_index (TnyList *list, GObject *object)
469 g_return_val_if_fail (TNY_IS_LIST(list), -1);
470 g_return_val_if_fail (G_IS_OBJECT(object), -1);
472 iter = tny_list_create_iterator (list);
473 while (!tny_iterator_is_done (iter)) {
474 GObject *current = tny_iterator_get_current (iter);
476 g_object_unref (current);
477 if (current == object)
480 tny_iterator_next (iter);
484 if (tny_iterator_is_done (iter))
486 g_object_unref (iter);
491 modest_utils_get_available_space (const gchar *maildir_path)
496 GnomeVFSFileSize size;
498 folder = modest_local_folder_info_get_maildir_path (maildir_path);
499 uri_string = gnome_vfs_get_uri_from_local_path (folder);
500 uri = gnome_vfs_uri_new (uri_string);
505 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
507 gnome_vfs_uri_unref (uri);
512 return (guint64) size;
515 on_destroy_dialog (GtkDialog *dialog)
517 gtk_widget_destroy (GTK_WIDGET(dialog));
518 if (gtk_events_pending ())
519 gtk_main_iteration ();
523 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
527 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
528 g_return_val_if_fail (key, 0);
530 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
531 if (sort_key < 0 || sort_key >= max) {
532 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
535 return (guint)sort_key;
539 launch_sort_headers_dialog (GtkWindow *parent_window,
542 ModestHeaderView *header_view = NULL;
544 GtkSortType sort_type;
546 gint default_key = 0;
548 gboolean outgoing = FALSE;
549 gint current_sort_colid = -1;
550 GtkSortType current_sort_type;
551 gint attachments_sort_id;
552 gint priority_sort_id;
553 GtkTreeSortable *sortable;
555 /* Get header window */
556 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
557 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
558 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
559 #ifdef MODEST_TOOLKIT_HILDON2
560 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
561 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
568 /* Add sorting keys */
569 cols = modest_header_view_get_columns (header_view);
572 #define SORT_ID_NUM 6
573 int sort_model_ids[SORT_ID_NUM];
574 int sort_ids[SORT_ID_NUM];
576 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
577 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
579 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
582 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
583 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
585 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
586 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
589 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
592 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
593 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
595 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
596 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
598 default_key = sort_key;
600 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
602 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
604 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
606 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
608 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
610 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
611 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
612 attachments_sort_id = sort_key;
614 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
616 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
617 sort_ids[sort_key] = 0;
619 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
621 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
622 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
623 priority_sort_id = sort_key;
625 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
627 if (!gtk_tree_sortable_get_sort_column_id (sortable,
628 ¤t_sort_colid, ¤t_sort_type)) {
629 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
630 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
632 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
633 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
634 gpointer flags_sort_type_pointer;
635 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
636 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
637 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
639 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
641 gint current_sort_keyid = 0;
642 while (current_sort_keyid < SORT_ID_NUM) {
643 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
646 current_sort_keyid++;
648 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
652 result = gtk_dialog_run (GTK_DIALOG (dialog));
653 if (result == GTK_RESPONSE_OK) {
654 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
655 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
656 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
660 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
661 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
662 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
663 GINT_TO_POINTER (sort_ids[sort_key]));
664 /* This is a hack to make it resort rows always when flag fields are
665 * selected. If we do not do this, changing sort field from priority to
666 * attachments does not work */
667 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
669 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
670 sort_model_ids[sort_key]);
673 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
674 gtk_tree_sortable_sort_column_changed (sortable);
677 modest_widget_memory_save (modest_runtime_get_conf (),
678 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
685 modest_utils_run_sort_dialog (GtkWindow *parent_window,
686 ModestSortDialogType type)
688 GtkWidget *dialog = NULL;
691 dialog = modest_platform_create_sort_dialog (parent_window);
694 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
695 GTK_WINDOW (dialog), parent_window);
699 case MODEST_SORT_HEADERS:
700 launch_sort_headers_dialog (parent_window,
706 on_destroy_dialog (GTK_DIALOG(dialog));
711 modest_images_cache_get_id (const gchar *account, const gchar *uri)
713 GnomeVFSURI *vfs_uri;
716 vfs_uri = gnome_vfs_uri_new (uri);
720 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
721 gnome_vfs_uri_unref (vfs_uri);
727 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
729 gchar *account_name = NULL;
730 ModestAccountMgr *mgr = NULL;
731 GSList *accounts = NULL, *node = NULL;
735 g_return_val_if_fail (from_header, NULL);
737 mgr = modest_runtime_get_account_mgr ();
738 accounts = modest_account_mgr_account_names (mgr, TRUE);
740 for (node = accounts; node != NULL; node = g_slist_next (node)) {
742 gchar *transport_account;
744 if (!strcmp (from_header, node->data)) {
745 account_name = g_strdup (node->data);
749 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
750 (const gchar *) node->data,
751 TNY_ACCOUNT_TYPE_TRANSPORT);
752 if (transport_account) {
754 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
757 ModestProtocol *protocol =
758 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
759 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
761 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
762 ModestPairList *pair_list;
764 gchar *from_header_email =
765 modest_text_utils_get_email_address (from_header);
766 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
769 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
771 account_name = g_strdup (node->data);
773 *mailbox = g_strdup (from_header_email);
776 modest_pair_list_free (pair_list);
781 g_free (transport_account);
783 if (mailbox && *mailbox)
787 modest_account_mgr_get_from_string (mgr, node->data, NULL);
791 modest_text_utils_get_email_address (from);
792 gchar *from_header_email =
793 modest_text_utils_get_email_address (from_header);
795 if (from_email && from_header_email) {
796 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
797 account_name = g_strdup (node->data);
804 g_free (from_header_email);
810 g_slist_foreach (accounts, (GFunc) g_free, NULL);
811 g_slist_free (accounts);
817 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
818 const gchar* character,
821 gchar *message = NULL;
822 const gchar *show_char = NULL;
825 show_char = character;
830 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
831 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
836 modest_utils_open_mcc_mapping_file (void)
841 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
842 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
843 } else if (access (MODEST_MCC_MAPPING, R_OK) == 0) {
844 path = MODEST_MCC_MAPPING;
846 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
847 __FUNCTION__, MODEST_OPERATOR_WIZARD_MCC_MAPPING, MODEST_MCC_MAPPING);
851 result = fopen (path, "r");
853 g_warning ("%s: error opening mapping file '%s': %s",
854 __FUNCTION__, path, strerror(errno));
860 /* cluster mcc's, based on the list
861 * http://en.wikipedia.org/wiki/Mobile_country_code
864 effective_mcc (gint mcc)
867 case 405: return 404; /* india */
868 case 441: return 440; /* japan */
869 case 348: /* NOTE: see below */
870 case 235: return 234; /* united kingdom */
871 case 289: return 282; /* georgia */
872 case 549: /* NOTE: see below */
878 case 316: return 310; /* united states */
881 /* NOTE: 348 for UK and 549 for US are not correct, but we do
882 a workaround here as changing operator-wizard package is
886 /* each line is of the form:
889 NOTE: this function is NOT re-entrant, the out-param country
890 are static strings that should NOT be freed. and will change when
891 calling this function again
893 also note, this function will return the "effective mcc", which
894 is the normalized mcc for a country - ie. even if the there
895 are multiple entries for the United States with various mccs,
896 this function will always return 310, even if the real mcc parsed
897 would be 314. see the 'effective_mcc' function above.
900 parse_mcc_mapping_line (const char* line, char** country)
902 char mcc[4]; /* the mcc code, always 3 bytes*/
903 gchar *iter, *tab, *final;
910 /* Go to the first tab (Country separator) */
911 tab = g_utf8_strrchr (line, -1, '\t');
915 *country = g_utf8_find_next_char (tab, NULL);
917 /* Replace by end of string. We need to use strlen, because
918 g_utf8_strrchr expects bytes and not UTF8 characters. File
919 lines end with \r\n */
920 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\r');
921 if (G_LIKELY (final))
924 tab[strlen(tab) - 1] = '\0';
927 mcc[0] = g_utf8_get_char (line);
928 iter = g_utf8_find_next_char (line, NULL);
929 mcc[1] = g_utf8_get_char (iter);
930 iter = g_utf8_find_next_char (iter, NULL);
931 mcc[2] = g_utf8_get_char (iter);
934 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
937 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
939 /** Note that the mcc_mapping file is installed
940 * by the operator-wizard-settings package.
943 modest_utils_create_country_model (void)
947 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
953 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
955 char line[MCC_FILE_MAX_LINE_LEN];
956 guint previous_mcc = 0;
958 GHashTable *country_hash;
961 /* First we need to know our current region */
962 file = modest_utils_open_mcc_mapping_file ();
964 g_warning ("Could not open mcc_mapping file");
968 /* Get the territory specified for the current locale */
969 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
971 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
973 char *country = NULL;
975 mcc = parse_mcc_mapping_line (line, &country);
976 if (!country || mcc == 0) {
977 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
981 if (mcc == previous_mcc) {
982 /* g_warning ("already seen: %s", line); */
987 if (!(*locale_mcc)) {
988 gchar *translation = dgettext ("osso-countries", country);
989 if (!g_utf8_collate (translation, territory))
994 /* Now we fill the model */
996 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
997 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1000 char *country = NULL;
1002 const gchar *name_translated;
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_hash_table_lookup (country_hash, country)) {
1012 g_debug ("already seen: '%s' %d", country, mcc);
1017 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1019 name_translated = dgettext ("osso-countries", country);
1021 /* Add the row to the model if we have translation for it */
1022 if (g_utf8_collate (country, name_translated)) {
1023 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1024 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1025 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1026 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1029 g_debug ("%s no translation for %s", __FUNCTION__, country);
1034 g_hash_table_unref (country_hash);
1037 /* Fallback to Finland */
1041 /* Sort the items: */
1042 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1043 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1047 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1049 GList *new_headers_list;
1052 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1053 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1055 new_headers_list = NULL;
1056 iter = tny_list_create_iterator (header_list);
1057 while (!tny_iterator_is_done (iter)) {
1058 ModestMsgNotificationData *data;
1062 header = (TnyHeader *) tny_iterator_get_current (iter);
1064 folder = tny_header_get_folder (header);
1069 uid = tny_header_dup_uid (header);
1070 uri = g_strdup_printf ("%s/%s",
1071 tny_folder_get_url_string (folder),
1075 /* Create data & add to list */
1076 data = g_slice_new0 (ModestMsgNotificationData);
1077 data->subject = tny_header_dup_subject (header);
1078 data->from = tny_header_dup_from (header);
1081 new_headers_list = g_list_append (new_headers_list, data);
1083 g_object_unref (folder);
1085 g_object_unref (header);
1087 tny_iterator_next (iter);
1089 g_object_unref (iter);
1091 return new_headers_list;
1095 free_notification_data (gpointer data,
1098 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1100 g_free (notification_data->from);
1101 g_free (notification_data->subject);
1102 g_free (notification_data->uri);
1104 g_slice_free (ModestMsgNotificationData, notification_data);
1108 modest_utils_free_notification_list (GList *notification_list)
1110 g_return_if_fail (g_list_length (notification_list) > 0);
1112 g_list_foreach (notification_list, free_notification_data, NULL);
1113 g_list_free (notification_list);
1117 modest_utils_flush_send_queue (const gchar *account_id)
1119 TnyTransportAccount *account;
1121 /* Get the transport account */
1122 account = (TnyTransportAccount *)
1123 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1125 TNY_ACCOUNT_TYPE_TRANSPORT);
1127 ModestMailOperation *wakeup_op;
1128 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue (account, TRUE);
1131 wakeup_op = modest_mail_operation_new (NULL);
1132 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1134 modest_mail_operation_queue_wakeup (wakeup_op, send_queue);
1136 g_object_unref (account);