Add a plugin method to allow updating stored passwords on master password change.
[claws.git] / src / plugins / libravatar / libravatar_federation.c
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  */
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  */
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  */
79 gchar *federated_url_for_address(const gchar *address)
80 {
81         gchar *domain = NULL, *last = NULL, *addr = NULL, *url = NULL;
82         gchar *host = NULL;
83         guint16 port = 0;
84
85         if (address == NULL || *address == '\0')
86                 goto invalid_addr;
87
88         addr = g_strdup(address);
89         domain = strchr(addr, '@');
90         if (domain == NULL)
91                 goto invalid_addr;
92  
93         ++domain;
94         if (strlen(domain) < 5)
95                 goto invalid_addr;
96
97         last = domain;
98         while (*last != '\0' && *last != ' ' && *last != '\t' && *last != '>')
99                 ++last;
100         *last = '\0';
101
102         /* try cached domains */
103         url = get_federated_url_for_domain(domain);
104         if (url != NULL) {
105                 g_free(addr);
106                 if (!strcmp(url, MISSING)) {
107                         return NULL;
108                 }
109                 return g_strdup(url);
110         }
111
112         /* not cached, try secure service first */
113         if (auto_configure_service_sync("avatars-sec", domain, &host, &port)) {
114                 if (port != 443) {
115                         url = g_strdup_printf("https://%s:%d/avatar", host, port);
116                 } else {
117                         url = g_strdup_printf("https://%s/avatar", host);
118                 }
119         } else { /* try standard one if no secure service available */
120                 if (auto_configure_service_sync("avatars", domain, &host, &port)) {
121                         if (port != 80) {
122                                 url = g_strdup_printf("http://%s:%d/avatar", host, port);
123                         } else {
124                                 url = g_strdup_printf("http://%s/avatar", host);
125                         }
126                 } else {
127                         debug_print("libravatar federated domain for %s not found\n", domain);
128                 }
129         }
130         if (url != NULL) {
131                 add_federated_url_for_domain(url, domain);
132         } else {
133                 add_federated_url_for_domain(MISSING, domain);
134         }
135
136         g_free(addr);
137         return url;
138
139 invalid_addr:
140         if (addr != NULL)
141                 g_free(addr);
142
143         debug_print("invalid address for libravatar federated domain\n");
144         return NULL;
145 }
146