Coverage Report

Created: 2026-05-16 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pidgin/libpurple/protocols/jabber/google/gmail.c
Line
Count
Source
1
/**
2
 * Purple is the legal property of its developers, whose names are too numerous
3
 * to list here.  Please refer to the COPYRIGHT file distributed with this
4
 * source distribution.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
19
 */
20
21
#include "internal.h"
22
#include "debug.h"
23
#include "jabber.h"
24
#include "gmail.h"
25
26
static void
27
jabber_gmail_parse(JabberStream *js, const char *from,
28
                   JabberIqType type, const char *id,
29
                   xmlnode *packet, gpointer nul)
30
0
{
31
0
  xmlnode *child;
32
0
  xmlnode *message;
33
0
  const char *to, *url;
34
0
  const char *in_str;
35
0
  char *to_name;
36
37
0
  int i, count = 1, returned_count;
38
39
0
  const char **tos, **froms, **urls;
40
0
  char **subjects;
41
42
0
  if (type == JABBER_IQ_ERROR)
43
0
    return;
44
45
0
  child = xmlnode_get_child(packet, "mailbox");
46
0
  if (!child)
47
0
    return;
48
49
0
  in_str = xmlnode_get_attrib(child, "total-matched");
50
0
  if (in_str && *in_str)
51
0
    count = atoi(in_str);
52
53
  /* If Gmail doesn't tell us who the mail is to, let's use our JID */
54
0
  to = xmlnode_get_attrib(packet, "to");
55
56
0
  message = xmlnode_get_child(child, "mail-thread-info");
57
58
0
  if (count == 0 || !message) {
59
0
    if (count > 0) {
60
0
      char *bare_jid = jabber_get_bare_jid(to);
61
0
      const char *default_tos[2] = { bare_jid };
62
63
0
      purple_notify_emails(js->gc, count, FALSE, NULL, NULL, default_tos, NULL, NULL, NULL);
64
0
      g_free(bare_jid);
65
0
    } else {
66
0
      purple_notify_emails(js->gc, count, FALSE, NULL, NULL, NULL, NULL, NULL, NULL);
67
0
    }
68
69
0
    return;
70
0
  }
71
72
  /* Loop once to see how many messages were returned so we can allocate arrays
73
   * accordingly */
74
0
  for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message));
75
76
0
  froms    = g_new0(const char* , returned_count + 1);
77
0
  tos      = g_new0(const char* , returned_count + 1);
78
0
  subjects = g_new0(char* , returned_count + 1);
79
0
  urls     = g_new0(const char* , returned_count + 1);
80
81
0
  to = xmlnode_get_attrib(packet, "to");
82
0
  to_name = jabber_get_bare_jid(to);
83
0
  url = xmlnode_get_attrib(child, "url");
84
0
  if (!url || !*url)
85
0
    url = "http://www.gmail.com";
86
87
0
  message= xmlnode_get_child(child, "mail-thread-info");
88
0
  for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
89
0
    xmlnode *sender_node, *subject_node;
90
0
    const char *from, *tid;
91
0
    char *subject;
92
93
0
    subject_node = xmlnode_get_child(message, "subject");
94
0
    sender_node  = xmlnode_get_child(message, "senders");
95
0
    sender_node  = xmlnode_get_child(sender_node, "sender");
96
97
0
    while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") ||
98
0
           purple_strequal(xmlnode_get_attrib(sender_node, "unread"),"0")))
99
0
      sender_node = xmlnode_get_next_twin(sender_node);
100
101
0
    if (!sender_node) {
102
0
      i--;
103
0
      continue;
104
0
    }
105
106
0
    from = xmlnode_get_attrib(sender_node, "name");
107
0
    if (!from || !*from)
108
0
      from = xmlnode_get_attrib(sender_node, "address");
109
0
    subject = xmlnode_get_data(subject_node);
110
    /*
111
     * url = xmlnode_get_attrib(message, "url");
112
     */
113
0
    tos[i] = (to_name != NULL ?  to_name : "");
114
0
    froms[i] = (from != NULL ?  from : "");
115
0
    subjects[i] = (subject != NULL ? subject : g_strdup(""));
116
0
    urls[i] = url;
117
118
0
    tid = xmlnode_get_attrib(message, "tid");
119
0
    if (g_strcmp0(tid, js->gmail_last_tid) > 0) {
120
0
      g_free(js->gmail_last_tid);
121
0
      js->gmail_last_tid = g_strdup(tid);
122
0
    }
123
0
  }
124
125
0
  if (i>0)
126
0
    purple_notify_emails(js->gc, count, count == i, (const char**) subjects, froms, tos,
127
0
        urls, NULL, NULL);
128
129
0
  g_free(to_name);
130
0
  g_free(tos);
131
0
  g_free(froms);
132
0
  for (i = 0; i < returned_count; i++)
133
0
    g_free(subjects[i]);
134
0
  g_free(subjects);
135
0
  g_free(urls);
136
137
0
  in_str = xmlnode_get_attrib(child, "result-time");
138
0
  if (in_str && *in_str) {
139
0
    g_free(js->gmail_last_time);
140
0
    js->gmail_last_time = g_strdup(in_str);
141
0
  }
142
0
}
143
144
void
145
jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
146
                  const char *id, xmlnode *new_mail)
147
0
{
148
0
  xmlnode *query;
149
0
  JabberIq *iq;
150
151
  /* bail if the user isn't interested */
152
0
  if (!purple_account_get_check_mail(js->gc->account))
153
0
    return;
154
155
  /* Is this an initial incoming mail notification? If so, send a request for more info */
156
0
  if (type != JABBER_IQ_SET)
157
0
    return;
158
159
  /* Acknowledge the notification */
160
0
  iq = jabber_iq_new(js, JABBER_IQ_RESULT);
161
0
  if (from)
162
0
    xmlnode_set_attrib(iq->node, "to", from);
163
0
  xmlnode_set_attrib(iq->node, "id", id);
164
0
  jabber_iq_send(iq);
165
166
0
  purple_debug_misc("jabber",
167
0
       "Got new mail notification. Sending request for more info\n");
168
169
0
  iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
170
0
  jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
171
0
  query = xmlnode_get_child(iq->node, "query");
172
173
0
  if (js->gmail_last_time)
174
0
    xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time);
175
0
  if (js->gmail_last_tid)
176
0
    xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid);
177
178
0
  jabber_iq_send(iq);
179
0
  return;
180
0
}
181
182
0
void jabber_gmail_init(JabberStream *js) {
183
0
  JabberIq *iq;
184
0
  xmlnode *usersetting, *mailnotifications;
185
186
0
  if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
187
0
    return;
188
189
  /*
190
   * Quoting http://code.google.com/apis/talk/jep_extensions/usersettings.html:
191
   * To ensure better compatibility with other clients, rather than
192
   * setting this value to "false" to turn off notifications, it is
193
   * recommended that a client set this to "true" and filter incoming
194
   * email notifications itself.
195
   */
196
0
  iq = jabber_iq_new(js, JABBER_IQ_SET);
197
0
  usersetting = xmlnode_new_child(iq->node, "usersetting");
198
0
  xmlnode_set_namespace(usersetting, "google:setting");
199
0
  mailnotifications = xmlnode_new_child(usersetting, "mailnotifications");
200
0
  xmlnode_set_attrib(mailnotifications, "value", "true");
201
0
  jabber_iq_send(iq);
202
203
0
  iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
204
  jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
205
0
  jabber_iq_send(iq);
206
0
}