Merge branch 'mob' of git+ssh://mob@repo.or.cz/srv/git/siplcs into mob
[siplcs.git] / src / sipmsg.c
blob543474fb8f3cd958f05efb3a4927b1e3470c6448
1 /**
2 * @file sipmsg.c
4 * gaim
6 * Copyright (C) 2008 Novell, Inc.
7 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #ifndef _WIN32
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <netinet/in.h>
29 #include <net/if.h>
30 #else /* _WIN32 */
31 #ifdef _DLL
32 #define _WS2TCPIP_H_
33 #define _WINSOCK2API_
34 #define _LIBC_INTERNAL_
35 #endif /* _DLL */
37 #include "internal.h"
38 #endif /* _WIN32 */
40 #include <string.h>
42 #include "accountopt.h"
43 #include "blist.h"
44 #include "conversation.h"
45 #include "debug.h"
46 #include "notify.h"
47 #include "prpl.h"
48 #include "plugin.h"
49 #include "util.h"
50 #include "version.h"
52 #include "sipe.h"
53 #include "sipmsg.h"
55 struct sipmsg *sipmsg_parse_msg(const gchar *msg) {
56 const char *tmp = strstr(msg, "\r\n\r\n");
57 char *line;
58 struct sipmsg *smsg;
60 if(!tmp) return NULL;
62 line = g_strndup(msg, tmp - msg);
64 smsg = sipmsg_parse_header(line);
65 smsg->body = g_strdup(tmp + 4);
67 g_free(line);
68 return smsg;
71 struct sipmsg *sipmsg_parse_header(const gchar *header) {
72 struct sipmsg *msg = g_new0(struct sipmsg,1);
73 gchar **lines = g_strsplit(header,"\r\n",0);
74 gchar **parts;
75 gchar *dummy;
76 gchar *dummy2;
77 gchar *tmp;
78 int i=1;
79 if(!lines[0]) return NULL;
80 parts = g_strsplit(lines[0], " ", 3);
81 if(!parts[0] || !parts[1] || !parts[2]) {
82 g_strfreev(parts);
83 g_strfreev(lines);
84 g_free(msg);
85 return NULL;
87 if(strstr(parts[0],"SIP")) { /* numeric response */
88 msg->method = g_strdup(parts[2]);
89 msg->response = strtol(parts[1],NULL,10);
90 } else { /* request */
91 msg->method = g_strdup(parts[0]);
92 msg->target = g_strdup(parts[1]);
93 msg->response = 0;
95 g_strfreev(parts);
96 for(i=1; lines[i] && strlen(lines[i])>2; i++) {
97 parts = g_strsplit(lines[i], ":", 2);
98 if(!parts[0] || !parts[1]) {
99 g_strfreev(parts);
100 g_strfreev(lines);
101 g_free(msg);
102 return NULL;
104 dummy = parts[1];
105 dummy2 = 0;
106 while(*dummy==' ' || *dummy=='\t') dummy++;
107 dummy2 = g_strdup(dummy);
108 while(lines[i+1] && (lines[i+1][0]==' ' || lines[i+1][0]=='\t')) {
109 i++;
110 dummy = lines[i];
111 while(*dummy==' ' || *dummy=='\t') dummy++;
112 tmp = g_strdup_printf("%s %s",dummy2, dummy);
113 g_free(dummy2);
114 dummy2 = tmp;
116 sipmsg_add_header(msg, parts[0], dummy2);
117 g_strfreev(parts);
119 g_strfreev(lines);
120 gchar *contentlength = sipmsg_find_header(msg, "Content-Length");
121 if (contentlength) {
122 msg->bodylen = strtol(contentlength,NULL,10);
123 } else {
124 purple_debug_fatal("sipe", "sipmsg_parse_header(): Content-Length header not found\n");
126 if(msg->response) {
127 tmp = sipmsg_find_header(msg, "CSeq");
128 if(!tmp) {
129 /* SHOULD NOT HAPPEN */
130 msg->method = 0;
131 } else {
132 parts = g_strsplit(tmp, " ", 2);
133 msg->method = g_strdup(parts[1]);
134 g_strfreev(parts);
137 return msg;
140 void sipmsg_print(const struct sipmsg *msg) {
141 GSList *cur;
142 struct siphdrelement *elem;
143 purple_debug(PURPLE_DEBUG_MISC, "sipe", "SIP MSG\n");
144 purple_debug(PURPLE_DEBUG_MISC, "sipe", "response: %d\nmethod: %s\nbodylen: %d\n",msg->response,msg->method,msg->bodylen);
145 if(msg->target) purple_debug(PURPLE_DEBUG_MISC, "sipe", "target: %s\n",msg->target);
146 cur = msg->headers;
147 while(cur) {
148 elem = cur->data;
149 purple_debug(PURPLE_DEBUG_MISC, "sipe", "name: %s value: %s\n",elem->name, elem->value);
150 cur = g_slist_next(cur);
154 char *sipmsg_to_string(const struct sipmsg *msg) {
155 GSList *cur;
156 GString *outstr = g_string_new("");
157 struct siphdrelement *elem;
159 if(msg->response)
160 g_string_append_printf(outstr, "SIP/2.0 %d Unknown\r\n",
161 msg->response);
162 else
163 g_string_append_printf(outstr, "%s %s SIP/2.0\r\n",
164 msg->method, msg->target);
166 cur = msg->headers;
167 while(cur) {
168 elem = cur->data;
169 /*Todo: remove the LFCR in a good way*/
170 /*if(!strcmp(elem->name,"Proxy-Authorization"))
171 g_string_append_printf(outstr, "%s: %s", elem->name,
172 elem->value);
173 else */
174 g_string_append_printf(outstr, "%s: %s\r\n", elem->name,
175 elem->value);
176 cur = g_slist_next(cur);
179 g_string_append_printf(outstr, "\r\n%s", msg->bodylen ? msg->body : "");
181 return g_string_free(outstr, FALSE);
183 void sipmsg_add_header(struct sipmsg *msg, const gchar *name, const gchar *value) {
184 struct siphdrelement *element = g_new0(struct siphdrelement,1);
185 element->name = g_strdup(name);
186 element->value = g_strdup(value);
187 msg->headers = g_slist_append(msg->headers, element);
190 void sipmsg_add_header_pos(struct sipmsg *msg, const gchar *name, const gchar *value, int pos) {
191 struct siphdrelement *element = g_new0(struct siphdrelement,1);
192 element->name = g_strdup(name);
193 element->value = g_strdup(value);
194 msg->headers = g_slist_insert(msg->headers, element,pos);
197 void sipmsg_free(struct sipmsg *msg) {
198 struct siphdrelement *elem;
199 while(msg->headers) {
200 elem = msg->headers->data;
201 msg->headers = g_slist_remove(msg->headers,elem);
202 g_free(elem->name);
203 g_free(elem->value);
204 g_free(elem);
206 g_free(msg->method);
207 g_free(msg->target);
208 g_free(msg->body);
209 g_free(msg);
212 void sipmsg_remove_header(struct sipmsg *msg, const gchar *name) {
213 struct siphdrelement *elem;
214 GSList *tmp = msg->headers;
215 while(tmp) {
216 elem = tmp->data;
217 // OCS2005 can send the same header in either all caps or mixed case
218 if (g_ascii_strcasecmp(elem->name, name)==0) {
219 msg->headers = g_slist_remove(msg->headers, elem);
220 g_free(elem->name);
221 g_free(elem->value);
222 g_free(elem);
223 return;
225 tmp = g_slist_next(tmp);
227 return;
230 gchar *sipmsg_find_header(struct sipmsg *msg, const gchar *name) {
231 GSList *tmp;
232 struct siphdrelement *elem;
233 tmp = msg->headers;
234 while(tmp) {
235 elem = tmp->data;
236 // OCS2005 can send the same header in either all caps or mixed case
237 if (g_ascii_strcasecmp(elem->name,name)==0) {
238 return elem->value;
240 tmp = g_slist_next(tmp);
242 return NULL;
245 gchar *
246 sipmsg_find_part_of_header(const char *hdr, const char * before, const char * after, const char * def)
248 if (!hdr) {
249 return NULL;
252 //printf("partof %s w/ %s before and %s after\n", hdr, before, after);
253 const char *tmp;
254 const char *tmp2;
256 tmp = before == NULL ? hdr : strstr(hdr, before);
257 if (!tmp) {
258 //printf ("not found, returning null\n");
259 return (gchar *)def;
262 if (before != NULL) {
263 tmp += strlen(before);
264 //printf ("tmp now %s\n", tmp);
267 if (after != NULL && (tmp2 = strstr(tmp, after))) {
268 gchar * res = g_strndup(tmp, tmp2 - tmp);
269 //printf("returning %s\n", res);
270 return res;
272 gchar * res2 = g_strdup(tmp);
273 //printf("returning %s\n", res2);
274 return res2;
278 * sipmsg_find_auth_header will return the particular WWW-Authenticate
279 * header specified by *name.
281 * Use this function when you want to look for a specific authentication
282 * method such as NTLM or Kerberos
285 gchar *sipmsg_find_auth_header(struct sipmsg *msg, const gchar *name) {
286 GSList *tmp;
287 struct siphdrelement *elem;
288 tmp = msg->headers;
289 int name_len = strlen(name);
290 while(tmp) {
291 elem = tmp->data;
292 //purple_debug(PURPLE_DEBUG_MISC, "sipmsg", "Current header: %s\r\n", elem->value);
293 if (elem && elem->name && !g_ascii_strcasecmp(elem->name,"WWW-Authenticate")) {
294 if (!g_strncasecmp((gchar *)elem->value, name, name_len)) {
295 //purple_debug(PURPLE_DEBUG_MISC, "sipmsg", "elem->value: %s\r\n", elem->value);
296 return elem->value;
299 //purple_debug(PURPLE_DEBUG_MISC, "sipmsg", "moving to next header\r\n");
300 tmp = g_slist_next(tmp);
302 purple_debug(PURPLE_DEBUG_MISC, "sipmsg", "Did not found auth header %s\r\n", name);
303 return NULL;