6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 #include "accountopt.h"
26 #include "buddylist.h"
27 #include "conversation.h"
38 #define MAX_CONTENT_LENGTH 30000000
40 struct sipmsg
*sipmsg_parse_msg(const gchar
*msg
) {
41 const char *tmp
= strstr(msg
, "\r\n\r\n");
47 line
= g_strndup(msg
, tmp
- msg
);
49 smsg
= sipmsg_parse_header(line
);
51 smsg
->body
= g_strdup(tmp
+ 4);
53 purple_debug_error("SIMPLE", "No header parsed from line: %s\n", line
);
59 struct sipmsg
*sipmsg_parse_header(const gchar
*header
) {
61 gchar
**parts
, **lines
;
62 gchar
*dummy
, *dummy2
, *tmp
;
66 lines
= g_strsplit(header
,"\r\n",0);
72 parts
= g_strsplit(lines
[0], " ", 3);
73 if(!parts
[0] || !parts
[1] || !parts
[2]) {
79 msg
= g_new0(struct sipmsg
,1);
80 if(strstr(parts
[0],"SIP")) { /* numeric response */
81 msg
->method
= g_strdup(parts
[2]);
82 msg
->response
= strtol(parts
[1],NULL
,10);
83 } else { /* request */
84 msg
->method
= g_strdup(parts
[0]);
85 msg
->target
= g_strdup(parts
[1]);
90 for(i
=1; lines
[i
] && strlen(lines
[i
])>2; i
++) {
91 parts
= g_strsplit(lines
[i
], ":", 2);
92 if(!parts
[0] || !parts
[1]) {
100 while(*dummy
==' ' || *dummy
=='\t') dummy
++;
101 dummy2
= g_strdup(dummy
);
102 while(lines
[i
+1] && (lines
[i
+1][0]==' ' || lines
[i
+1][0]=='\t')) {
105 while(*dummy
==' ' || *dummy
=='\t') dummy
++;
106 tmp
= g_strdup_printf("%s %s",dummy2
, dummy
);
110 sipmsg_add_header(msg
, parts
[0], dummy2
);
116 tmp2
= sipmsg_find_header(msg
, "Content-Length");
118 msg
->bodylen
= strtol(tmp2
, NULL
, 10);
119 if (msg
->bodylen
< 0) {
120 purple_debug_warning("simple", "Invalid body length: %d",
123 } else if (msg
->bodylen
> MAX_CONTENT_LENGTH
) {
124 purple_debug_warning("simple", "Got Content-Length of %d bytes on "
125 "incoming message (max is %u bytes). Ignoring message body.\n",
126 msg
->bodylen
, MAX_CONTENT_LENGTH
);
131 tmp2
= sipmsg_find_header(msg
, "CSeq");
134 /* SHOULD NOT HAPPEN */
137 parts
= g_strsplit(tmp2
, " ", 2);
138 msg
->method
= g_strdup(parts
[1]);
146 void sipmsg_print(const struct sipmsg
*msg
) {
148 struct siphdrelement
*elem
;
149 purple_debug(PURPLE_DEBUG_MISC
, "simple", "SIP MSG\n");
150 purple_debug(PURPLE_DEBUG_MISC
, "simple", "response: %d\nmethod: %s\nbodylen: %d\n",msg
->response
,msg
->method
,msg
->bodylen
);
151 if(msg
->target
) purple_debug(PURPLE_DEBUG_MISC
, "simple", "target: %s\n",msg
->target
);
155 purple_debug(PURPLE_DEBUG_MISC
, "simple", "name: %s value: %s\n",elem
->name
, elem
->value
);
156 cur
= g_slist_next(cur
);
160 char *sipmsg_to_string(const struct sipmsg
*msg
) {
162 GString
*outstr
= g_string_new("");
163 struct siphdrelement
*elem
;
166 g_string_append_printf(outstr
, "SIP/2.0 %d Unknown\r\n",
169 g_string_append_printf(outstr
, "%s %s SIP/2.0\r\n",
170 msg
->method
, msg
->target
);
175 g_string_append_printf(outstr
, "%s: %s\r\n", elem
->name
,
177 cur
= g_slist_next(cur
);
180 g_string_append_printf(outstr
, "\r\n%s", msg
->bodylen
? msg
->body
: "");
182 return g_string_free(outstr
, FALSE
);
184 void sipmsg_add_header(struct sipmsg
*msg
, const gchar
*name
, const gchar
*value
) {
185 struct siphdrelement
*element
= g_new(struct siphdrelement
,1);
186 element
->name
= g_strdup(name
);
187 element
->value
= g_strdup(value
);
188 msg
->headers
= g_slist_append(msg
->headers
, element
);
191 void sipmsg_free(struct sipmsg
*msg
) {
192 struct siphdrelement
*elem
;
193 while(msg
->headers
) {
194 elem
= msg
->headers
->data
;
195 msg
->headers
= g_slist_remove(msg
->headers
,elem
);
206 void sipmsg_remove_header(struct sipmsg
*msg
, const gchar
*name
) {
207 struct siphdrelement
*elem
;
208 GSList
*tmp
= msg
->headers
;
211 if(g_ascii_strcasecmp(elem
->name
, name
)==0) {
212 msg
->headers
= g_slist_remove(msg
->headers
, elem
);
218 tmp
= g_slist_next(tmp
);
223 const gchar
*sipmsg_find_header(struct sipmsg
*msg
, const gchar
*name
) {
225 struct siphdrelement
*elem
;
229 if(g_ascii_strcasecmp(elem
->name
, name
)==0) {
232 tmp
= g_slist_next(tmp
);