1 /*
2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2014-2015 Ricardo Mones and the Claws Mail Team
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdio.h>
20
21 #include "libravatar_federation.h"
22 #include "utils.h"
23 #include "gtkutils.h"
24
25 #define MISSING "x"
26
27 static GHashTable *federated = NULL;
28
29 /**
30 * Get the associated avatar URL for a domain.
31 *
32 * @param domain Domain to get the URL for.
33 *
34 * @return The avatar URL for the domain or NULL if not found.
35 */
get_federated_url_for_domain(const gchar * domain)36 static gchar *get_federated_url_for_domain(const gchar *domain)
37 {
38 gchar *found;
39
40 if (federated == NULL) {
41 return NULL;
42 }
43
44 found = (gchar *) g_hash_table_lookup(federated, domain);
45
46 if (found != NULL)
47 debug_print("cached avatar url for domain %s found: %s\n", domain, found);
48 else
49 debug_print("cached avatar url for domain %s not found\n", domain);
50
51 return found;
52 }
53
54 /**
55 * Adds a URL for a domain.
56 *
57 * @param url The computed avatar URL.
58 * @param domain Associated domain.
59 */
add_federated_url_for_domain(const gchar * url,const gchar * domain)60 static void add_federated_url_for_domain(const gchar *url, const gchar *domain)
61 {
62 if (url == NULL)
63 return;
64
65 if (federated == NULL)
66 federated = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
67
68 debug_print("new cached avatar url for domain %s: %s\n", domain, url);
69 g_hash_table_insert(federated, g_strdup(domain), g_strdup(url));
70 }
71
72 /**
73 * Retrieves the federated URL for a given email address.
74 *
75 * @param address The email address.
76 *
77 * @return The avatar URL for the domain of the address.
78 */
federated_url_for_address(const gchar * address)79 gchar *federated_url_for_address(const gchar *address)
80 {
81 #if defined USE_GNUTLS
82 gchar *domain = NULL, *last = NULL, *addr = NULL, *url = NULL;
83 gchar *host = NULL;
84 guint16 port = 0;
85
86 if (address == NULL || *address == '\0')
87 goto invalid_addr;
88
89 addr = g_strdup(address);
90 domain = strchr(addr, '@');
91 if (domain == NULL)
92 goto invalid_addr;
93
94 ++domain;
95 if (strlen(domain) < 5)
96 goto invalid_addr;
97
98 last = domain;
99 while (*last != '\0' && *last != ' ' && *last != '\t' && *last != '>')
100 ++last;
101 *last = '\0';
102
103 /* try cached domains */
104 url = get_federated_url_for_domain(domain);
105 if (url != NULL) {
106 g_free(addr);
107 if (!strcmp(url, MISSING)) {
108 return NULL;
109 }
110 return g_strdup(url);
111 }
112
113 /* not cached, try secure service first */
114 if (auto_configure_service_sync("avatars-sec", domain, &host, &port)) {
115 if (port != 443) {
116 url = g_strdup_printf("https://%s:%d/avatar", host, port);
117 } else {
118 url = g_strdup_printf("https://%s/avatar", host);
119 }
120 } else { /* try standard one if no secure service available */
121 if (auto_configure_service_sync("avatars", domain, &host, &port)) {
122 if (port != 80) {
123 url = g_strdup_printf("http://%s:%d/avatar", host, port);
124 } else {
125 url = g_strdup_printf("http://%s/avatar", host);
126 }
127 } else {
128 debug_print("libravatar federated domain for %s not found\n", domain);
129 }
130 }
131 if (url != NULL) {
132 add_federated_url_for_domain(url, domain);
133 } else {
134 add_federated_url_for_domain(MISSING, domain);
135 }
136
137 g_free(addr);
138 return url;
139
140 invalid_addr:
141 if (addr != NULL)
142 g_free(addr);
143
144 debug_print("invalid address for libravatar federated domain\n");
145 return NULL;
146 #else
147 debug_print("federated domains disabled (built without GnuTLS support)\n");
148 return NULL;
149 #endif
150 }
151
152