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-transport-account.h>
40 #include <tny-camel-imap-store-account.h>
41 #include <tny-camel-pop-store-account.h>
43 #include <modest-defs.h>
44 #include "modest-utils.h"
45 #include "modest-platform.h"
46 #include <modest-account-protocol.h>
47 #include "modest-account-mgr-helpers.h"
48 #include "modest-text-utils.h"
49 #include <modest-local-folder-info.h>
50 #include "widgets/modest-header-view.h"
51 #include "widgets/modest-main-window.h"
52 #include "modest-widget-memory.h"
53 #include "widgets/modest-sort-criterium-view.h"
54 #ifdef MODEST_TOOLKIT_HILDON2
55 #include "modest-header-window.h"
60 modest_utils_get_supported_secure_authentication_error_quark (void)
62 return g_quark_from_static_string("modest-utils-get-supported-secure-authentication-error-quark");
66 modest_utils_folder_writable (const gchar *filename)
68 g_return_val_if_fail (filename, FALSE);
73 if (g_strncasecmp (filename, "obex", 4) != 0) {
74 GnomeVFSFileInfo *folder_info = NULL;
75 GnomeVFSResult result = GNOME_VFS_OK;
76 GnomeVFSURI *uri = NULL;
77 GnomeVFSURI *folder_uri = NULL;
79 uri = gnome_vfs_uri_new (filename);
80 folder_uri = gnome_vfs_uri_get_parent (uri);
82 if (folder_uri != NULL) {
83 folder_info = gnome_vfs_file_info_new ();
84 result = gnome_vfs_get_file_info_uri (folder_uri, folder_info,
85 GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS);
86 gnome_vfs_uri_unref (folder_uri);
88 gnome_vfs_uri_unref (uri);
90 if (folder_uri == NULL)
93 if ((result != GNOME_VFS_OK) ||
94 (!((folder_info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE) ||
95 (folder_info->permissions & GNOME_VFS_PERM_USER_WRITE)))) {
97 gnome_vfs_file_info_unref (folder_info);
100 gnome_vfs_file_info_unref (folder_info);
106 modest_utils_file_exists (const gchar *filename)
108 GnomeVFSURI *uri = NULL;
109 gboolean result = FALSE;
111 g_return_val_if_fail (filename, FALSE);
113 uri = gnome_vfs_uri_new (filename);
115 result = gnome_vfs_uri_exists (uri);
116 gnome_vfs_uri_unref (uri);
122 modest_utils_create_temp_stream (const gchar *orig_name, const gchar *hash_base, gchar **path)
125 gchar *filepath = NULL;
129 /* hmmm... maybe we need a modest_text_utils_validate_file_name? */
130 g_return_val_if_fail (orig_name && strlen(orig_name) != 0, NULL);
132 if (strlen(orig_name) > 200) {
133 g_warning ("%s: filename too long ('%s')",
134 __FUNCTION__, orig_name);
138 if (g_strstr_len (orig_name, strlen(orig_name), "/") != NULL) {
139 g_warning ("%s: filename contains '/' character(s) (%s)",
140 __FUNCTION__, orig_name);
144 /* make a random subdir under /tmp or /var/tmp */
145 if (hash_base != NULL) {
146 hash_number = g_str_hash (hash_base);
148 hash_number = (guint) random ();
150 tmpdir = g_strdup_printf ("%s/%u", g_get_tmp_dir (), hash_number);
151 if ((g_access (tmpdir, R_OK) == -1) && (g_mkdir (tmpdir, 0755) == -1)) {
152 g_warning ("%s: failed to create dir '%s': %s",
153 __FUNCTION__, tmpdir, g_strerror(errno));
158 filepath = g_strconcat (tmpdir, "/", orig_name, NULL);
160 /* if file exists, first we try to remove it */
161 if (modest_utils_file_exists (filepath)) {
165 /* don't overwrite if it already exists, even if it is writable */
166 if (modest_utils_file_exists (filepath)) {
175 /* try to write the file there */
176 fd = g_open (filepath, O_CREAT|O_WRONLY|O_TRUNC, 0644);
178 g_warning ("%s: failed to create '%s': %s",
179 __FUNCTION__, filepath, g_strerror(errno));
193 return TNY_FS_STREAM (tny_fs_stream_new (fd));
201 } ModestGetSupportedAuthInfo;
204 on_idle_secure_auth_finished (gpointer user_data)
206 /* Operation has finished, close the dialog. Control continues after
207 * gtk_dialog_run in modest_utils_get_supported_secure_authentication_methods() */
208 gdk_threads_enter(); /* CHECKED */
209 gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
210 gdk_threads_leave(); /* CHECKED */
216 on_camel_account_get_supported_secure_authentication (TnyCamelAccount *self,
222 ModestPairList *pairs;
224 ModestProtocolRegistry *protocol_registry;
225 ModestGetSupportedAuthInfo *info = (ModestGetSupportedAuthInfo*)user_data;
228 g_return_if_fail (user_data);
229 g_return_if_fail (TNY_IS_CAMEL_ACCOUNT(self));
230 g_return_if_fail (TNY_IS_LIST(auth_types));
232 info = (ModestGetSupportedAuthInfo *) user_data;
234 /* Free everything if the actual action was canceled */
236 g_debug ("%s: operation canceled\n", __FUNCTION__);
241 g_debug ("%s: error getting the supported auth methods\n", __FUNCTION__);
246 g_debug ("%s: auth_types is NULL.\n", __FUNCTION__);
250 if (tny_list_get_length(auth_types) == 0) {
251 g_debug ("%s: auth_types is an empty TnyList.\n", __FUNCTION__);
255 protocol_registry = modest_runtime_get_protocol_registry ();
256 pairs = modest_protocol_registry_get_pair_list_by_tag (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS);
258 /* Get the enum value for the strings: */
260 iter = tny_list_create_iterator(auth_types);
261 while (!tny_iterator_is_done(iter)) {
263 const gchar *auth_name;
264 ModestProtocolType protocol_type;
266 pair = TNY_PAIR(tny_iterator_get_current(iter));
269 auth_name = tny_pair_get_name(pair);
270 g_object_unref (pair);
274 g_debug ("%s: auth_name=%s\n", __FUNCTION__, auth_name);
276 protocol_type = modest_protocol_get_type_id (modest_protocol_registry_get_protocol_by_name (protocol_registry,
277 MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS,
280 if (modest_protocol_registry_protocol_type_is_secure (protocol_registry, protocol_type))
281 result = g_list_prepend(result, GINT_TO_POINTER(protocol_type));
283 tny_iterator_next(iter);
285 g_object_unref (iter);
287 modest_pair_list_free (pairs);
288 *(info->result) = result;
291 /* Close the dialog in a main thread */
292 g_idle_add(on_idle_secure_auth_finished, info->dialog);
295 g_slice_free (ModestGetSupportedAuthInfo, info);
300 gboolean not_finished;
304 keep_pulsing (gpointer user_data)
306 KeepPulsing *info = (KeepPulsing *) user_data;
308 if (!info->not_finished) {
309 g_slice_free (KeepPulsing, info);
313 gtk_progress_bar_pulse (GTK_PROGRESS_BAR (info->progress));
318 modest_utils_get_supported_secure_authentication_methods (ModestProtocolType protocol_type,
319 const gchar* hostname,
321 const gchar* username,
322 GtkWindow *parent_window,
325 TnyAccount * tny_account = NULL;
326 ModestProtocolRegistry *protocol_registry;
329 ModestTnyAccountStore *account_store;
330 TnySessionCamel *session = NULL;
331 ModestProtocol *protocol = NULL;
332 GList *result = NULL;
335 g_return_val_if_fail (protocol_type != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID, NULL);
337 protocol_registry = modest_runtime_get_protocol_registry ();
339 /* We need a connection to get the capabilities; */
340 if (!modest_platform_connect_and_wait (GTK_WINDOW (parent_window), NULL))
343 /* Create a TnyCamelAccount so we can use
344 * tny_camel_account_get_supported_secure_authentication(): */
345 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
347 if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
348 tny_account = modest_account_protocol_create_account (MODEST_ACCOUNT_PROTOCOL (protocol));
352 g_printerr ("%s could not create tny account.", __FUNCTION__);
356 /* Set proto, so that the prepare_func() vfunc will work when
357 * we call set_session(): */
358 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, protocol_type);
359 tny_account_set_id (tny_account, "temp_account");
360 tny_account_set_proto (tny_account, modest_protocol_get_name (protocol));
361 tny_account_set_hostname (tny_account, hostname);
362 tny_account_set_user (tny_account, username);
365 tny_account_set_port (tny_account, port);
367 /* Set the session for the account, so we can use it: */
368 account_store = modest_runtime_get_account_store ();
369 session = modest_tny_account_store_get_session (TNY_ACCOUNT_STORE (account_store));
370 g_return_val_if_fail (session, NULL);
371 tny_camel_account_set_session (TNY_CAMEL_ACCOUNT(tny_account), session);
373 dialog = gtk_dialog_new_with_buttons(" ",
375 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
376 _("mcen_bd_dialog_cancel"),
380 /* Ask camel to ask the server, asynchronously: */
381 ModestGetSupportedAuthInfo *info = g_slice_new (ModestGetSupportedAuthInfo);
382 info->result = &result;
383 info->dialog = dialog;
385 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox),
386 gtk_label_new(_("emev_ni_checking_supported_auth_methods")));
387 progress = gtk_progress_bar_new();
388 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(info->dialog)->vbox), progress);
389 gtk_widget_show_all(info->dialog);
391 KeepPulsing *pi = g_slice_new (KeepPulsing);
392 pi->progress = progress;
393 pi->not_finished = TRUE;
395 /* Starts the pulsing of the progressbar */
396 g_timeout_add (500, keep_pulsing, pi);
398 tny_camel_account_get_supported_secure_authentication (TNY_CAMEL_ACCOUNT (tny_account),
399 on_camel_account_get_supported_secure_authentication,
403 retval = gtk_dialog_run (GTK_DIALOG (info->dialog));
405 pi->not_finished = FALSE;
406 /* pi is freed in the timeout itself to avoid a GCond here */
408 gtk_widget_destroy(dialog);
411 tny_account_cancel (tny_account);
412 g_object_unref (tny_account);
418 modest_utils_show_dialog_and_forget (GtkWindow *parent_window,
421 g_return_if_fail (GTK_IS_WINDOW(parent_window));
422 g_return_if_fail (GTK_IS_DIALOG(dialog));
424 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent_window);
426 /* Destroy the dialog when it is closed: */
427 g_signal_connect_swapped (dialog,
429 G_CALLBACK (gtk_widget_destroy),
432 gtk_widget_show (GTK_WIDGET (dialog));
436 modest_utils_toggle_action_set_active_block_notify (GtkToggleAction *action, gboolean value)
438 GSList *proxies = NULL;
440 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
442 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
443 proxies != NULL; proxies = g_slist_next (proxies)) {
444 GtkWidget *widget = (GtkWidget *) proxies->data;
445 gtk_action_block_activate_from (GTK_ACTION (action), widget);
448 gtk_toggle_action_set_active (action, value);
450 for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
451 proxies != NULL; proxies = g_slist_next (proxies)) {
452 GtkWidget *widget = (GtkWidget *) proxies->data;
453 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
460 modest_list_index (TnyList *list, GObject *object)
465 g_return_val_if_fail (TNY_IS_LIST(list), -1);
466 g_return_val_if_fail (G_IS_OBJECT(object), -1);
468 iter = tny_list_create_iterator (list);
469 while (!tny_iterator_is_done (iter)) {
470 GObject *current = tny_iterator_get_current (iter);
472 g_object_unref (current);
473 if (current == object)
476 tny_iterator_next (iter);
480 if (tny_iterator_is_done (iter))
482 g_object_unref (iter);
487 modest_utils_get_available_space (const gchar *maildir_path)
492 GnomeVFSFileSize size;
494 folder = modest_local_folder_info_get_maildir_path (maildir_path);
495 uri_string = gnome_vfs_get_uri_from_local_path (folder);
496 uri = gnome_vfs_uri_new (uri_string);
501 if (gnome_vfs_get_volume_free_space (uri, &size) != GNOME_VFS_OK)
503 gnome_vfs_uri_unref (uri);
508 return (guint64) size;
511 on_destroy_dialog (GtkDialog *dialog)
513 gtk_widget_destroy (GTK_WIDGET(dialog));
514 if (gtk_events_pending ())
515 gtk_main_iteration ();
519 checked_modest_sort_criterium_view_add_sort_key (ModestSortCriteriumView *view, const gchar* key, guint max)
523 g_return_val_if_fail (view && MODEST_IS_SORT_CRITERIUM_VIEW(view), 0);
524 g_return_val_if_fail (key, 0);
526 sort_key = modest_sort_criterium_view_add_sort_key (view, key);
527 if (sort_key < 0 || sort_key >= max) {
528 g_warning ("%s: out of range (%d) for %s", __FUNCTION__, sort_key, key);
531 return (guint)sort_key;
535 launch_sort_headers_dialog (GtkWindow *parent_window,
538 ModestHeaderView *header_view = NULL;
540 GtkSortType sort_type;
542 gint default_key = 0;
544 gboolean outgoing = FALSE;
545 gint current_sort_colid = -1;
546 GtkSortType current_sort_type;
547 gint attachments_sort_id;
548 gint priority_sort_id;
549 GtkTreeSortable *sortable;
551 /* Get header window */
552 if (MODEST_IS_MAIN_WINDOW (parent_window)) {
553 header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_window),
554 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
555 #ifdef MODEST_TOOLKIT_HILDON2
556 } else if (MODEST_IS_HEADER_WINDOW (parent_window)) {
557 header_view = MODEST_HEADER_VIEW (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (parent_window)));
564 /* Add sorting keys */
565 cols = modest_header_view_get_columns (header_view);
568 #define SORT_ID_NUM 6
569 int sort_model_ids[SORT_ID_NUM];
570 int sort_ids[SORT_ID_NUM];
572 outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
573 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
575 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_sender_recipient"),
578 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
579 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
581 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
582 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
585 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_date"),
588 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
589 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
591 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
592 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
594 default_key = sort_key;
596 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_subject"),
598 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
600 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
602 sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
604 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_attachment"),
606 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
607 sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
608 attachments_sort_id = sort_key;
610 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_size"),
612 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
613 sort_ids[sort_key] = 0;
615 sort_key = checked_modest_sort_criterium_view_add_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), _("mcen_li_sort_priority"),
617 sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
618 sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY_MASK;
619 priority_sort_id = sort_key;
621 sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
623 if (!gtk_tree_sortable_get_sort_column_id (sortable,
624 ¤t_sort_colid, ¤t_sort_type)) {
625 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), default_key);
626 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), GTK_SORT_DESCENDING);
628 modest_sort_criterium_view_set_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_type);
629 if (current_sort_colid == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
630 gpointer flags_sort_type_pointer;
631 flags_sort_type_pointer = g_object_get_data (G_OBJECT (cols->data), MODEST_HEADER_VIEW_FLAG_SORT);
632 if (GPOINTER_TO_INT (flags_sort_type_pointer) == TNY_HEADER_FLAG_PRIORITY_MASK)
633 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), priority_sort_id);
635 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), attachments_sort_id);
637 gint current_sort_keyid = 0;
638 while (current_sort_keyid < SORT_ID_NUM) {
639 if (sort_model_ids[current_sort_keyid] == current_sort_colid)
642 current_sort_keyid++;
644 modest_sort_criterium_view_set_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog), current_sort_keyid);
648 result = gtk_dialog_run (GTK_DIALOG (dialog));
649 if (result == GTK_RESPONSE_OK) {
650 sort_key = modest_sort_criterium_view_get_sort_key (MODEST_SORT_CRITERIUM_VIEW (dialog));
651 if (sort_key < 0 || sort_key > SORT_ID_NUM -1) {
652 g_warning ("%s: out of range (%d)", __FUNCTION__, sort_key);
656 sort_type = modest_sort_criterium_view_get_sort_order (MODEST_SORT_CRITERIUM_VIEW (dialog));
657 if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
658 g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
659 GINT_TO_POINTER (sort_ids[sort_key]));
660 /* This is a hack to make it resort rows always when flag fields are
661 * selected. If we do not do this, changing sort field from priority to
662 * attachments does not work */
663 modest_header_view_sort_by_column_id (header_view, 0, sort_type);
665 gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data),
666 sort_model_ids[sort_key]);
669 modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
670 gtk_tree_sortable_sort_column_changed (sortable);
673 modest_widget_memory_save (modest_runtime_get_conf (),
674 G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
681 modest_utils_run_sort_dialog (GtkWindow *parent_window,
682 ModestSortDialogType type)
684 GtkWidget *dialog = NULL;
687 dialog = modest_platform_create_sort_dialog (parent_window);
690 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
691 GTK_WINDOW (dialog), parent_window);
695 case MODEST_SORT_HEADERS:
696 launch_sort_headers_dialog (parent_window,
702 on_destroy_dialog (GTK_DIALOG(dialog));
707 modest_images_cache_get_id (const gchar *account, const gchar *uri)
709 GnomeVFSURI *vfs_uri;
712 vfs_uri = gnome_vfs_uri_new (uri);
716 result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
717 gnome_vfs_uri_unref (vfs_uri);
723 modest_utils_get_account_name_from_recipient (const gchar *from_header, gchar **mailbox)
725 gchar *account_name = NULL;
726 ModestAccountMgr *mgr = NULL;
727 GSList *accounts = NULL, *node = NULL;
731 g_return_val_if_fail (from_header, NULL);
733 mgr = modest_runtime_get_account_mgr ();
734 accounts = modest_account_mgr_account_names (mgr, TRUE);
736 for (node = accounts; node != NULL; node = g_slist_next (node)) {
738 gchar *transport_account;
740 if (!strcmp (from_header, node->data)) {
741 account_name = g_strdup (node->data);
745 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
746 (const gchar *) node->data,
747 TNY_ACCOUNT_TYPE_TRANSPORT);
748 if (transport_account) {
750 proto = modest_account_mgr_get_string (mgr, transport_account, MODEST_ACCOUNT_PROTO, TRUE);
753 ModestProtocol *protocol =
754 modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
755 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
757 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
758 ModestPairList *pair_list;
760 gchar *from_header_email =
761 modest_text_utils_get_email_address (from_header);
762 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
765 pair = modest_pair_list_find_by_first_as_string (pair_list, from_header_email);
767 account_name = g_strdup (node->data);
769 *mailbox = g_strdup (from_header_email);
772 modest_pair_list_free (pair_list);
777 g_free (transport_account);
779 if (mailbox && *mailbox)
783 modest_account_mgr_get_from_string (mgr, node->data, NULL);
787 modest_text_utils_get_email_address (from);
788 gchar *from_header_email =
789 modest_text_utils_get_email_address (from_header);
791 if (from_email && from_header_email) {
792 if (!modest_text_utils_utf8_strcmp (from_header_email, from_email, TRUE)) {
793 account_name = g_strdup (node->data);
800 g_free (from_header_email);
806 g_slist_foreach (accounts, (GFunc) g_free, NULL);
807 g_slist_free (accounts);
813 modest_utils_on_entry_invalid_character (ModestValidatingEntry *self,
814 const gchar* character,
817 gchar *message = NULL;
818 const gchar *show_char = NULL;
821 show_char = character;
826 message = g_strdup_printf (_CS("ckdg_ib_illegal_characters_entered"), show_char);
827 modest_platform_information_banner (GTK_WIDGET (self), NULL, message);
832 modest_utils_open_mcc_mapping_file (gboolean from_lc_messages, gboolean *translated)
836 const gchar *env_list;
837 gchar **parts, **node;
839 if (from_lc_messages) {
840 env_list = setlocale (LC_MESSAGES, NULL);
842 env_list = getenv ("LANG");
844 parts = g_strsplit (env_list, ":", 0);
846 const gchar* path2 = MODEST_MCC_MAPPING;
852 for (node = parts; path == NULL && node != NULL && *node != NULL && **node != '\0'; node++) {
853 path1 = g_strdup_printf ("%s.%s", MODEST_OPERATOR_WIZARD_MCC_MAPPING, *node);
854 if (access (path1, R_OK) == 0) {
865 if (access (MODEST_OPERATOR_WIZARD_MCC_MAPPING, R_OK) == 0) {
866 path = MODEST_OPERATOR_WIZARD_MCC_MAPPING;
869 } else if (access (path2, R_OK) == 0) {
872 g_warning ("%s: neither '%s' nor '%s' is a readable mapping file",
873 __FUNCTION__, path1, path2);
878 result = fopen (path, "r");
880 g_warning ("%s: error opening mapping file '%s': %s",
881 __FUNCTION__, path, strerror(errno));
889 /* cluster mcc's, based on the list
890 * http://en.wikipedia.org/wiki/Mobile_country_code
893 effective_mcc (gint mcc)
896 case 405: return 404; /* india */
897 case 441: return 440; /* japan */
898 case 235: return 234; /* united kingdom */
904 case 316: return 310; /* united states */
909 /* each line is of the form:
912 NOTE: this function is NOT re-entrant, the out-param country
913 are static strings that should NOT be freed. and will change when
914 calling this function again
916 also note, this function will return the "effective mcc", which
917 is the normalized mcc for a country - ie. even if the there
918 are multiple entries for the United States with various mccs,
919 this function will always return 310, even if the real mcc parsed
920 would be 314. see the 'effective_mcc' function above.
923 parse_mcc_mapping_line (const char* line, char** country)
925 char mcc[4]; /* the mcc code, always 3 bytes*/
926 gchar *iter, *tab, *final;
933 /* Go to the first tab (Country separator) */
934 tab = g_utf8_strrchr (line, -1, '\t');
938 *country = g_utf8_find_next_char (tab, NULL);
940 /* Replace by end of string. We need to use strlen, because
941 g_utf8_strrchr expects bytes and not UTF8 characters */
942 final = g_utf8_strrchr (tab, strlen (tab) + 1, '\n');
943 if (G_LIKELY (final))
946 tab[strlen(tab) - 1] = '\0';
949 mcc[0] = g_utf8_get_char (line);
950 iter = g_utf8_find_next_char (line, NULL);
951 mcc[1] = g_utf8_get_char (iter);
952 iter = g_utf8_find_next_char (iter, NULL);
953 mcc[2] = g_utf8_get_char (iter);
956 return effective_mcc ((int) strtol ((const char*)mcc, NULL, 10));
959 #define MCC_FILE_MAX_LINE_LEN 128 /* max length of a line in MCC file */
961 /** Note that the mcc_mapping file is installed
962 * by the operator-wizard-settings package.
965 modest_utils_create_country_model (void)
969 model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
975 modest_utils_fill_country_model (GtkTreeModel *model, gint *locale_mcc)
978 char line[MCC_FILE_MAX_LINE_LEN];
979 guint previous_mcc = 0;
981 GHashTable *country_hash;
984 /* First we need to know our current region */
985 file = modest_utils_open_mcc_mapping_file (FALSE, &translated);
987 g_warning ("Could not open mcc_mapping file");
991 /* Get the territory specified for the current locale */
992 territory = nl_langinfo (_NL_ADDRESS_COUNTRY_NAME);
994 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
996 char *country = NULL;
998 mcc = parse_mcc_mapping_line (line, &country);
999 if (!country || mcc == 0) {
1000 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1004 if (mcc == previous_mcc) {
1005 /* g_warning ("already seen: %s", line); */
1010 if (!(*locale_mcc)) {
1012 if (!g_utf8_collate (country, territory))
1015 gchar *translation = dgettext ("osso-countries", country);
1016 if (!g_utf8_collate (translation, territory))
1023 /* Now we fill the model */
1024 file = modest_utils_open_mcc_mapping_file (TRUE, &translated);
1026 g_warning ("Could not open mcc_mapping file");
1030 country_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1031 while (fgets (line, MCC_FILE_MAX_LINE_LEN, file) != NULL) {
1034 char *country = NULL;
1036 const gchar *name_translated;
1038 mcc = parse_mcc_mapping_line (line, &country);
1039 if (!country || mcc == 0) {
1040 g_warning ("%s: error parsing line: '%s'", __FUNCTION__, line);
1044 if (mcc == previous_mcc ||
1045 g_hash_table_lookup (country_hash, country)) {
1046 g_debug ("already seen: '%s' %d", country, mcc);
1051 g_hash_table_insert (country_hash, g_strdup (country), GINT_TO_POINTER (mcc));
1053 name_translated = dgettext ("osso-countries", country);
1055 /* Add the row to the model: */
1056 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1057 gtk_list_store_set(GTK_LIST_STORE (model), &iter,
1058 MODEST_UTILS_COUNTRY_MODEL_COLUMN_MCC, mcc,
1059 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, name_translated,
1064 g_hash_table_unref (country_hash);
1067 /* Fallback to Finland */
1071 /* Sort the items: */
1072 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
1073 MODEST_UTILS_COUNTRY_MODEL_COLUMN_NAME, GTK_SORT_ASCENDING);
1077 modest_utils_create_notification_list_from_header_list (TnyList *header_list)
1079 GList *new_headers_list;
1082 g_return_val_if_fail (TNY_IS_LIST (header_list), NULL);
1083 g_return_val_if_fail (tny_list_get_length (header_list) > 0, NULL);
1085 new_headers_list = NULL;
1086 iter = tny_list_create_iterator (header_list);
1087 while (!tny_iterator_is_done (iter)) {
1088 ModestMsgNotificationData *data;
1092 header = (TnyHeader *) tny_iterator_get_current (iter);
1094 folder = tny_header_get_folder (header);
1099 uid = tny_header_dup_uid (header);
1100 uri = g_strdup_printf ("%s/%s",
1101 tny_folder_get_url_string (folder),
1105 /* Create data & add to list */
1106 data = g_slice_new0 (ModestMsgNotificationData);
1107 data->subject = tny_header_dup_subject (header);
1108 data->from = tny_header_dup_from (header);
1111 new_headers_list = g_list_append (new_headers_list, data);
1113 g_object_unref (folder);
1115 g_object_unref (header);
1117 tny_iterator_next (iter);
1119 g_object_unref (iter);
1121 return new_headers_list;
1125 free_notification_data (gpointer data,
1128 ModestMsgNotificationData *notification_data = (ModestMsgNotificationData *) data;
1130 g_free (notification_data->from);
1131 g_free (notification_data->subject);
1132 g_free (notification_data->uri);
1136 modest_utils_free_notification_list (GList *notification_list)
1138 g_return_if_fail (g_list_length (notification_list) > 0);
1140 g_list_foreach (notification_list, free_notification_data, NULL);
1141 g_list_free (notification_list);