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
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <netinet/in.h>
34 #define _LIBC_INTERNAL_
42 #include "accountopt.h"
44 #include "conversation.h"
55 struct sipmsg
*sipmsg_parse_msg(const gchar
*msg
) {
56 const char *tmp
= strstr(msg
, "\r\n\r\n");
62 line
= g_strndup(msg
, tmp
- msg
);
64 smsg
= sipmsg_parse_header(line
);
65 smsg
->body
= g_strdup(tmp
+ 4);
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);
79 if(!lines
[0]) return NULL
;
80 parts
= g_strsplit(lines
[0], " ", 3);
81 if(!parts
[0] || !parts
[1] || !parts
[2]) {
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]);
96 for(i
=1; lines
[i
] && strlen(lines
[i
])>2; i
++) {
97 parts
= g_strsplit(lines
[i
], ":", 2);
98 if(!parts
[0] || !parts
[1]) {
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')) {
111 while(*dummy
==' ' || *dummy
=='\t') dummy
++;
112 tmp
= g_strdup_printf("%s %s",dummy2
, dummy
);
116 sipmsg_add_header(msg
, parts
[0], dummy2
);
120 gchar
*contentlength
= sipmsg_find_header(msg
, "Content-Length");
122 msg
->bodylen
= strtol(contentlength
,NULL
,10);
124 purple_debug_fatal("sipe", "sipmsg_parse_header(): Content-Length header not found\n");
127 tmp
= sipmsg_find_header(msg
, "CSeq");
129 /* SHOULD NOT HAPPEN */
132 parts
= g_strsplit(tmp
, " ", 2);
133 msg
->method
= g_strdup(parts
[1]);
140 void sipmsg_print(const struct sipmsg
*msg
) {
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
);
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
) {
156 GString
*outstr
= g_string_new("");
157 struct siphdrelement
*elem
;
160 g_string_append_printf(outstr
, "SIP/2.0 %d Unknown\r\n",
163 g_string_append_printf(outstr
, "%s %s SIP/2.0\r\n",
164 msg
->method
, msg
->target
);
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,
174 g_string_append_printf(outstr
, "%s: %s\r\n", elem
->name
,
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
);
212 void sipmsg_remove_header(struct sipmsg
*msg
, const gchar
*name
) {
213 struct siphdrelement
*elem
;
214 GSList
*tmp
= msg
->headers
;
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
);
225 tmp
= g_slist_next(tmp
);
230 gchar
*sipmsg_find_header(struct sipmsg
*msg
, const gchar
*name
) {
232 struct siphdrelement
*elem
;
236 // OCS2005 can send the same header in either all caps or mixed case
237 if (g_ascii_strcasecmp(elem
->name
,name
)==0) {
240 tmp
= g_slist_next(tmp
);
246 sipmsg_find_part_of_header(const char *hdr
, const char * before
, const char * after
, const char * def
)
252 //printf("partof %s w/ %s before and %s after\n", hdr, before, after);
256 tmp
= before
== NULL
? hdr
: strstr(hdr
, before
);
258 //printf ("not found, returning null\n");
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);
272 gchar
* res2
= g_strdup(tmp
);
273 //printf("returning %s\n", 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
) {
287 struct siphdrelement
*elem
;
289 int name_len
= strlen(name
);
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);
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
);