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 escaped = g_uri_escape_string (filename, NULL, FALSE);
115 if (g_access (escaped, F_OK) == 0)
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 tmp = g_uri_escape_string (orig_name, NULL, FALSE);
160 filepath = g_build_filename (tmpdir, tmp, NULL);
163 /* if file exists, first we try to remove it */
164 if (g_access (filepath, F_OK) == 0)
167 /* don't overwrite if it already exists, even if it is writable */
168 if (g_access (filepath, F_OK) == 0) {
177 /* try to write the file there */
178 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
180 g_warning ("%s: failed to create '%s': %s",
181 __FUNCTION__, filepath, g_strerror(errno));
195 return TNY_FS_STREAM (tny_fs_stream_new (fd));
203 } ModestGetSupportedAuthInfo;
206 on_idle_secure_auth_finished (gpointer user_data)
208 /* Operation has finished, close the dialog. Control continues after
209 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
210 gdk_threads_enter(); /* CHECKED */
211 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
212 gdk_threads_leave(); /* CHECKED */
218 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
224 ModestPairList *pairs;
226 ModestProtocolRegistry *protocol_registry;
227 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
230 g_return_if_fail (user_data);
231 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
232 g_return_if_fail (TNY_IS_LIST(auth_types));
234 info = (ModestGetSupportedAuthInfo *) user_data;
236 /* Free everything if the actual action was canceled */
238 g_debug ("%s: operation canceled\n", __FUNCTION__);
243 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
248 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
252 if (tny_list_get_length(auth_types) == 0) {
253 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
257 protocol_registry = modest_runtime_get_protocol_registry ();
258 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
260 /* Get the enum value for the strings: */
262 iter = tny_list_create_iterator(auth_types);
263 while (!tny_iterator_is_done(iter)) {
265 const gchar *auth_name;
266 ModestProtocolType protocol_type;
268 pair = TNY_PAIR(tny_iterator_get_current(iter));
271 auth_name = tny_pair_get_name(pair);
272 g_object_unref (pair);
276 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
278 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
279 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
282 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
283 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
285 tny_iterator_next(iter);
287 g_object_unref (iter);
289 modest_pair_list_free (pairs);
290 *(info->result) = result;
293 /* Close the dialog in a main thread */
294 g_idle_add(on_idle_secure_auth_finished, info->dialog);
297 g_slice_free (ModestGetSupportedAuthInfo, info);
302 gboolean not_finished;
306 keep_pulsing (gpointer user_data)
308 KeepPulsing *info = (KeepPulsing *) user_data;
310 if (!info->not_finished) {
311 g_slice_free (KeepPulsing, info);
315 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
320 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
321 const gchar* hostname,
323 const gchar* username,
324 GtkWindow *parent_window,
327 TnyAccount * tny_account = NULL;
328 ModestProtocolRegistry *protocol_registry;
331 ModestTnyAccountStore *account_store;
332 TnySessionCamel *session = NULL;
333 ModestProtocol *protocol = NULL;
334 GList *result = NULL;
337 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
339 protocol_registry = modest_runtime_get_protocol_registry ();
341 /* We need a connection to get the capabilities; */
342 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
345 /* Create a TnyCamelAccount so we can use
346 * tny_camel_account_get_supported_secure_authentication(): */
347 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
349 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
350 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
354 g_printerr ("%s could not create tny account.", __FUNCTION__);
358 /* Set proto, so that the prepare_func() vfunc will work when
359 * we call set_session(): */
360 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
361 tny_account_set_id (tny_account, "temp_account");
362 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
363 tny_account_set_hostname (tny_account, hostname);
364 tny_account_set_user (tny_account, username);
367 tny_account_set_port (tny_account, port);
369 /* Set the session for the account, so we can use it: */
370 account_store = modest_runtime_get_account_store ();
371 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
372 g_return_val_if_fail (session, NULL);
373 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
375 dialog = gtk_dialog_new_with_buttons(" ",
377 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
378 _("mcen_bd_dialog_cancel"),
382 /* Ask camel to ask the server, asynchronously: */
383 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
384 info->result = &result;
385 info->dialog = dialog;
387 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
388 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
389 progress = gtk_progress_bar_new();
390 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
391 gtk_widget_show_all(info->dialog);
393 KeepPulsing *pi = g_slice_new (KeepPulsing);
394 pi->progress = progress;
395 pi->not_finished = TRUE;
397 /* Starts the pulsing of the progressbar */
398 g_timeout_add (500, keep_pulsing, pi);
400 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
401 on_camel_account_get_supported_secure_authentication,
405 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
407 pi->not_finished = FALSE;
408 /* pi is freed in the timeout itself to avoid a GCond here */
410 gtk_widget_destroy(dialog);
413 tny_account_cancel (tny_account);
414 g_object_unref (tny_account);
420 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
423 g_return_if_fail (GTK_IS_WINDOW(parent_window));
424 g_return_if_fail (GTK_IS_DIALOG(dialog));
426 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
428 /* Destroy the dialog when it is closed: */
429 g_signal_connect_swapped (dialog,
431 G_CALLBACK (gtk_widget_destroy),
434 gtk_widget_show (GTK_WIDGET (dialog));
438 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
440 GSList *proxies = NULL;
442 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
444 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
445 proxies != NULL; proxies = g_slist_next (proxies)) {
446 GtkWidget *widget = (GtkWidget *) proxies->data;
447 gtk_action_block_activate_from (GTK_ACTION (action), widget);
450 gtk_toggle_action_set_active (action, value);
452 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
453 proxies != NULL; proxies = g_slist_next (proxies)) {
454 GtkWidget *widget = (GtkWidget *) proxies->data;
455 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
462 modest_list_index (TnyList *list, GObject *object)
467 g_return_val_if_fail (TNY_IS_LIST(list), -1);
468 g_return_val_if_fail (G_IS_OBJECT(object), -1);
470 iter = tny_list_create_iterator (list);
471 while (!tny_iterator_is_done (iter)) {
472 GObject *current = tny_iterator_get_current (iter);
474 g_object_unref (current);
475 if (current == object)
478 tny_iterator_next (iter);
482 if (tny_iterator_is_done (iter))
484 g_object_unref (iter);
489 modest_utils_get_available_space (const gchar *maildir_path)
494 GnomeVFSFileSize size;
496 folder = modest_local_folder_info_get_maildir_path (maildir_path);
497 uri_string = gnome_vfs_get_uri_from_local_path (folder);
498 uri = gnome_vfs_uri_new (uri_string);
503 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
505 gnome_vfs_uri_unref (uri);
510 return (guint64) size;
513 on_destroy_dialog (GtkDialog *dialog)
515 gtk_widget_destroy (GTK_WIDGET(dialog));
516 if (gtk_events_pending ())
517 gtk_main_iteration ();
521 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
525 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
526 g_return_val_if_fail (key, 0);
528 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
529 if (sort_key < 0 || sort_key >= max) {
530 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
533 return (guint)sort_key;
537 launch_sort_headers_dialog (GtkWindow *parent_window,
540 ModestHeaderView *header_view = NULL;
542 GtkSortType sort_type;
544 gint default_key = 0;
546 gboolean outgoing = FALSE;
547 gint current_sort_colid = -1;
548 GtkSortType current_sort_type;
549 gint attachments_sort_id;
550 gint priority_sort_id;
551 GtkTreeSortable *sortable;
553 /* Get header window */
554 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
555 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
556 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
557 #ifdef MODEST_TOOLKIT_HILDON2
558 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
559 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
566 /* Add sorting keys */
567 cols = modest_header_view_get_columns (header_view);
570 #define SORT_ID_NUM 6
571 int sort_model_ids[SORT_ID_NUM];
572 int sort_ids[SORT_ID_NUM];
574 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
575 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
577 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
580 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
581 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
583 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
584 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
587 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
590 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
591 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
593 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
594 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
596 default_key = sort_key;
598 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
600 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
602 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
604 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
606 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
608 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
609 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
610 attachments_sort_id = sort_key;
612 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
614 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
615 sort_ids[sort_key] = 0;
617 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
619 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
620 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
621 priority_sort_id = sort_key;
623 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
625 if (!gtk_tree_sortable_get_sort_column_id (sortable,
626 ¤t_sort_colid, ¤t_sort_type)) {
627 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
628 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
630 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
631 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
632 gpointer flags_sort_type_pointer;
633 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
634 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
635 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
637 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
639 gint current_sort_keyid = 0;
640 while (current_sort_keyid < SORT_ID_NUM) {
641 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
644 current_sort_keyid++;
646 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
650 result = gtk_dialog_run (GTK_DIALOG (dialog));
651 if (result == GTK_RESPONSE_OK) {
652 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
653 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
654 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
658 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
659 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
660 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
661 GINT_TO_POINTER (sort_ids[sort_key]));
662 /* This is a hack to make it resort rows always when flag fields are
663 * selected. If we do not do this, changing sort field from priority to
664 * attachments does not work */
665 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
667 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
668 sort_model_ids[sort_key]);
671 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
672 gtk_tree_sortable_sort_column_changed (sortable);
675 modest_widget_memory_save (modest_runtime_get_conf (),
676 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
683 modest_utils_run_sort_dialog (GtkWindow *parent_window,
684 ModestSortDialogType type)
686 GtkWidget *dialog = NULL;
689 dialog = modest_platform_create_sort_dialog (parent_window);
692 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
693 GTK_WINDOW (dialog), parent_window);
697 case MODEST_SORT_HEADERS:
698 launch_sort_headers_dialog (parent_window,
704 on_destroy_dialog (GTK_DIALOG(dialog));
709 modest_images_cache_get_id (const gchar *account, const gchar *uri)
711 GnomeVFSURI *vfs_uri;
714 vfs_uri = gnome_vfs_uri_new (uri);
718 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
719 gnome_vfs_uri_unref (vfs_uri);
725 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
727 gchar *account_name = NULL;
728 ModestAccountMgr *mgr = NULL;
729 GSList *accounts = NULL, *node = NULL;
733 g_return_val_if_fail (from_header, NULL);
735 mgr = modest_runtime_get_account_mgr ();
736 accounts = modest_account_mgr_account_names (mgr, TRUE);
738 for (node = accounts; node != NULL; node = g_slist_next (node)) {
740 gchar *transport_account;
742 if (!strcmp (from_header, node->data)) {
743 account_name = g_strdup (node->data);
747 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
748 (const gchar *) node->data,
749 TNY_ACCOUNT_TYPE_TRANSPORT);
750 if (transport_account) {
752 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
755 ModestProtocol *protocol =
756 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
757 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
759 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
760 ModestPairList *pair_list;
762 gchar *from_header_email =
763 modest_text_utils_get_email_address (from_header);
764 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
767 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
769 account_name = g_strdup (node->data);
771 *mailbox = g_strdup (from_header_email);
774 modest_pair_list_free (pair_list);
779 g_free (transport_account);
781 if (mailbox && *mailbox)
785 modest_account_mgr_get_from_string (mgr, node->data, NULL);
789 modest_text_utils_get_email_address (from);
790 gchar *from_header_email =
791 modest_text_utils_get_email_address (from_header);
793 if (from_email && from_header_email) {
794 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
795 account_name = g_strdup (node->data);
802 g_free (from_header_email);
808 g_slist_foreach (accounts, (GFunc) g_free, NULL);
809 g_slist_free (accounts);
815 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
816 const gchar* character,
819 gchar *message = NULL;
820 const gchar *show_char = NULL;
823 show_char = character;
828 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
829 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
834 modest_utils_open_mcc_mapping_file (gboolean from_lc_messages, gboolean *translated)
838 const gchar *env_list;
839 gchar **parts, **node;
841 if (from_lc_messages) {
842 env_list = setlocale (LC_MESSAGES, NULL);
844 env_list = getenv ("LANG");
846 parts = g_strsplit (env_list, ":", 0);
848 const gchar* path2 = MODEST_MCC_MAPPING;
854 for (node = parts; path == NULL && node != NULL && *node != NULL && **node != '\0'; node++) {
855 path1 = g_strdup_printf ("%s.%s", MODEST_OPERATOR_WIZARD_MCC_MAPPING, *node);
856 if (access (path1, R_OK) == 0) {
867 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
868 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
871 } else if (access (path2, R_OK) == 0) {
874 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
875 __FUNCTION__, path1, path2);
880 result = fopen (path, "r");
882 g_warning ("%s: error opening mapping file '%s': %s",
883 __FUNCTION__, path, strerror(errno));
891 /* cluster mcc's, based on the list
892 * http://en.wikipedia.org/wiki/Mobile_country_code
895 effective_mcc (gint mcc)
898 case 405: return 404; /* india */
899 case 441: return 440; /* japan */
900 case 235: return 234; /* united kingdom */
906 case 316: return 310; /* united states */
911 /* each line is of the form:
914 NOTE: this function is NOT re-entrant, the out-param country
915 are static strings that should NOT be freed. and will change when
916 calling this function again
918 also note, this function will return the "effective mcc", which
919 is the normalized mcc for a country - ie. even if the there
920 are multiple entries for the United States with various mccs,
921 this function will always return 310, even if the real mcc parsed
922 would be 314. see the 'effective_mcc' function above.
925 parse_mcc_mapping_line (const char* line, char** country)
927 char mcc[4]; /* the mcc code, always 3 bytes*/
928 gchar *iter, *tab, *final;
935 /* Go to the first tab (Country separator) */
936 tab = g_utf8_strrchr (line, -1, '\t');
940 *country = g_utf8_find_next_char (tab, NULL);
942 /* Replace by end of string. We need to use strlen, because
943 g_utf8_strrchr expects bytes and not UTF8 characters */
944 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\n');
945 if (G_LIKELY (final))
948 tab[strlen(tab) - 1] = '\0';
951 mcc[0] = g_utf8_get_char (line);
952 iter = g_utf8_find_next_char (line, NULL);
953 mcc[1] = g_utf8_get_char (iter);
954 iter = g_utf8_find_next_char (iter, NULL);
955 mcc[2] = g_utf8_get_char (iter);
958 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
961 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
963 /** Note that the mcc_mapping file is installed
964 * by the operator-wizard-settings package.
967 modest_utils_create_country_model (void)
971 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
977 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
980 char line[MCC_FILE_MAX_LINE_LEN];
981 guint previous_mcc = 0;
983 GHashTable *country_hash;
986 /* First we need to know our current region */
987 file = modest_utils_open_mcc_mapping_file (FALSE, &translated);
989 g_warning ("Could not open mcc_mapping file");
993 /* Get the territory specified for the current locale */
994 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
996 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
998 char *country = NULL;
1000 mcc = parse_mcc_mapping_line (line, &country);
1001 if (!country || mcc == 0) {
1002 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1006 if (mcc == previous_mcc) {
1007 /* g_warning ("already seen: %s", line); */
1012 if (!(*locale_mcc)) {
1014 if (!g_utf8_collate (country, territory))
1017 gchar *translation = dgettext ("osso-countries", country);
1018 if (!g_utf8_collate (translation, territory))
1025 /* Now we fill the model */
1026 file = modest_utils_open_mcc_mapping_file (TRUE, &translated);
1028 g_warning ("Could not open mcc_mapping file");
1032 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1033 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1036 char *country = NULL;
1038 const gchar *name_translated;
1040 mcc = parse_mcc_mapping_line (line, &country);
1041 if (!country || mcc == 0) {
1042 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1046 if (mcc == previous_mcc ||
1047 g_hash_table_lookup (country_hash, country)) {
1048 g_debug ("already seen: '%s' %d", country, mcc);
1053 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1055 name_translated = dgettext ("osso-countries", country);
1057 /* Add the row to the model: */
1058 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1059 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1060 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1061 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1066 g_hash_table_unref (country_hash);
1069 /* Fallback to Finland */
1073 /* Sort the items: */
1074 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1075 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1079 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1081 GList *new_headers_list;
1084 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1085 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1087 new_headers_list = NULL;
1088 iter = tny_list_create_iterator (header_list);
1089 while (!tny_iterator_is_done (iter)) {
1090 ModestMsgNotificationData *data;
1094 header = (TnyHeader *) tny_iterator_get_current (iter);
1096 folder = tny_header_get_folder (header);
1101 uid = tny_header_dup_uid (header);
1102 uri = g_strdup_printf ("%s/%s",
1103 tny_folder_get_url_string (folder),
1107 /* Create data & add to list */
1108 data = g_slice_new0 (ModestMsgNotificationData);
1109 data->subject = tny_header_dup_subject (header);
1110 data->from = tny_header_dup_from (header);
1113 new_headers_list = g_list_append (new_headers_list, data);
1115 g_object_unref (folder);
1117 g_object_unref (header);
1119 tny_iterator_next (iter);
1121 g_object_unref (iter);
1123 return new_headers_list;
1127 free_notification_data (gpointer data,
1130 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1132 g_free (notification_data->from);
1133 g_free (notification_data->subject);
1134 g_free (notification_data->uri);
1136 g_slice_free (ModestMsgNotificationData, notification_data);
1140 modest_utils_free_notification_list (GList *notification_list)
1142 g_return_if_fail (g_list_length (notification_list) > 0);
1144 g_list_foreach (notification_list, free_notification_data, NULL);
1145 g_list_free (notification_list);
1149 modest_utils_flush_send_queue (const gchar *account_id)
1151 TnyTransportAccount *account;
1153 /* Get the transport account */
1154 account = (TnyTransportAccount *)
1155 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1157 TNY_ACCOUNT_TYPE_TRANSPORT);
1159 ModestMailOperation *wakeup_op;
1160 ModestTnySendQueue *send_queue = modest_runtime_get_send_queue (account, TRUE);
1163 wakeup_op = modest_mail_operation_new (NULL);
1164 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1166 modest_mail_operation_queue_wakeup (wakeup_op, send_queue);
1168 g_object_unref (account);