filetransfer: do not append message body to SIP headers
[siplcs.git] / src / core / sipe-dialog.c
blobd7bd03dc4829d080be9524a775860ad90cb7781a
1 /**
2 * @file sipe-dialog.c
4 * pidgin-sipe
6 * Copyright (C) 2009 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <string.h>
24 #include <glib.h>
26 #include "debug.h"
28 #include "sipe.h"
29 #include "sipe-utils.h"
30 #include "sipe-dialog.h"
31 #include "sipe-session.h"
32 #include "sipmsg.h"
34 void sipe_dialog_free(struct sip_dialog *dialog)
36 GSList *entry;
37 void *data;
39 if (!dialog) return;
41 g_free(dialog->with);
42 g_free(dialog->endpoint_GUID);
43 entry = dialog->routes;
44 while (entry) {
45 data = entry->data;
46 entry = g_slist_remove(entry, data);
47 g_free(data);
49 entry = dialog->supported;
50 while (entry) {
51 data = entry->data;
52 entry = g_slist_remove(entry, data);
53 g_free(data);
56 g_free(dialog->callid);
57 g_free(dialog->ourtag);
58 g_free(dialog->theirtag);
59 g_free(dialog->theirepid);
60 g_free(dialog->request);
62 g_free(dialog);
65 void sipe_subscription_free(struct sip_subscription *subscription)
67 if (!subscription) return;
69 g_free(subscription->event);
70 /* NOTE: use cast to prevent BAD_FREE warning from Coverity */
71 sipe_dialog_free((struct sip_dialog *) subscription);
74 struct sip_dialog *sipe_dialog_add(struct sip_session *session)
76 struct sip_dialog *dialog = g_new0(struct sip_dialog, 1);
77 session->dialogs = g_slist_append(session->dialogs, dialog);
78 return(dialog);
81 static struct sip_dialog *
82 sipe_dialog_find_3(struct sip_session *session,
83 struct sip_dialog *dialog_in)
85 if (session && dialog_in) {
86 SIPE_DIALOG_FOREACH {
87 if ( dialog_in->callid &&
88 dialog_in->ourtag &&
89 dialog_in->theirtag &&
91 dialog->callid &&
92 dialog->ourtag &&
93 dialog->theirtag &&
95 !g_ascii_strcasecmp(dialog_in->callid, dialog->callid) &&
96 !g_ascii_strcasecmp(dialog_in->ourtag, dialog->ourtag) &&
97 !g_ascii_strcasecmp(dialog_in->theirtag, dialog->theirtag))
99 purple_debug_info("sipe", "sipe_dialog_find_3 who='%s'\n",
100 dialog->with ? dialog->with : "");
101 return dialog;
103 } SIPE_DIALOG_FOREACH_END;
105 return NULL;
108 struct sip_dialog *sipe_dialog_find(struct sip_session *session,
109 const gchar *who)
111 if (session && who) {
112 SIPE_DIALOG_FOREACH {
113 if (dialog->with && !g_ascii_strcasecmp(who, dialog->with)) {
114 purple_debug_info("sipe", "sipe_dialog_find who='%s'\n", who);
115 return dialog;
117 } SIPE_DIALOG_FOREACH_END;
119 return NULL;
122 void sipe_dialog_remove(struct sip_session *session, const gchar *who)
124 struct sip_dialog *dialog = sipe_dialog_find(session, who);
125 if (dialog) {
126 purple_debug_info("sipe", "sipe_dialog_remove who='%s' with='%s'\n", who, dialog->with ? dialog->with : "");
127 session->dialogs = g_slist_remove(session->dialogs, dialog);
128 sipe_dialog_free(dialog);
132 void
133 sipe_dialog_remove_3(struct sip_session *session,
134 struct sip_dialog *dialog_in)
136 struct sip_dialog *dialog = sipe_dialog_find_3(session, dialog_in);
137 if (dialog) {
138 purple_debug_info("sipe", "sipe_dialog_remove_3 with='%s'\n",
139 dialog->with ? dialog->with : "");
140 session->dialogs = g_slist_remove(session->dialogs, dialog);
141 sipe_dialog_free(dialog);
145 void sipe_dialog_remove_all(struct sip_session *session)
147 GSList *entry = session->dialogs;
148 while (entry) {
149 struct sip_dialog *dialog = entry->data;
150 entry = g_slist_remove(entry, dialog);
151 sipe_dialog_free(dialog);
155 static void sipe_get_route_header(const struct sipmsg *msg,
156 struct sip_dialog *dialog,
157 gboolean outgoing)
159 GSList *hdr = msg->headers;
160 gchar *contact = sipmsg_find_part_of_header(sipmsg_find_header(msg, "Contact"), "<", ">", NULL);
162 while (hdr) {
163 struct sipnameval *elem = hdr->data;
164 if(!g_ascii_strcasecmp(elem->name, "Record-Route")) {
165 gchar **parts = g_strsplit(elem->value, ",", 0);
166 gchar **part = parts;
168 while (*part) {
169 gchar *route = sipmsg_find_part_of_header(*part, "<", ">", NULL);
170 purple_debug_info("sipe", "sipe_get_route_header: route %s \n", route);
171 dialog->routes = g_slist_append(dialog->routes, route);
172 part++;
175 g_strfreev(parts);
177 hdr = g_slist_next(hdr);
179 if (outgoing) {
180 dialog->routes = g_slist_reverse(dialog->routes);
183 if (contact) {
184 dialog->request = contact;
187 /* logic for strict router only - RFC3261 - 12.2.1.1 */
188 /* @TODO: proper check for presence of 'lr' PARAMETER in URI */
189 if (dialog->routes && !strstr(dialog->routes->data, ";lr")) {
190 dialog->request = dialog->routes->data;
191 dialog->routes = g_slist_remove(dialog->routes, dialog->routes->data);
192 if (contact) {
193 dialog->routes = g_slist_append(dialog->routes, contact);
198 static void
199 sipe_get_supported_header(const struct sipmsg *msg,
200 struct sip_dialog *dialog,
201 SIPE_UNUSED_PARAMETER gboolean outgoing)
203 GSList *hdr = msg->headers;
204 struct sipnameval *elem;
205 while(hdr)
207 elem = hdr->data;
208 if(!g_ascii_strcasecmp(elem->name, "Supported")
209 && !g_slist_find_custom(dialog->supported, elem->value, (GCompareFunc)g_ascii_strcasecmp))
211 dialog->supported = g_slist_append(dialog->supported, g_strdup(elem->value));
214 hdr = g_slist_next(hdr);
218 static gchar *find_tag(const gchar *hdr)
220 gchar * tag = sipmsg_find_part_of_header (hdr, "tag=", ";", NULL);
221 if (!tag) {
222 // In case it's at the end and there's no trailing ;
223 tag = sipmsg_find_part_of_header (hdr, "tag=", NULL, NULL);
225 return tag;
228 void sipe_dialog_parse(struct sip_dialog *dialog,
229 const struct sipmsg *msg,
230 gboolean outgoing)
232 gchar *us = outgoing ? "From" : "To";
233 gchar *them = outgoing ? "To" : "From";
234 const gchar *session_expires_header;
236 g_free(dialog->ourtag);
237 g_free(dialog->theirtag);
239 dialog->ourtag = find_tag(sipmsg_find_header(msg, us));
240 dialog->theirtag = find_tag(sipmsg_find_header(msg, them));
241 if (!dialog->theirepid) {
242 dialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), "epid=", ";", NULL);
243 if (!dialog->theirepid) {
244 dialog->theirepid = sipmsg_find_part_of_header(sipmsg_find_header(msg, them), "epid=", NULL, NULL);
248 // Catch a tag on the end of the To Header and get rid of it.
249 if (dialog->theirepid && strstr(dialog->theirepid, "tag=")) {
250 dialog->theirepid = strtok(dialog->theirepid, ";");
253 if ((session_expires_header = sipmsg_find_header(msg, "Session-Expires"))) {
254 dialog->expires = atoi(session_expires_header);
257 sipe_get_route_header(msg, dialog, outgoing);
258 sipe_get_supported_header(msg, dialog, outgoing);
262 Local Variables:
263 mode: c
264 c-file-style: "bsd"
265 indent-tabs-mode: t
266 tab-width: 8
267 End: