mark PurpleImageClass as private
[pidgin-git.git] / libpurple / protocols / simple / sipmsg.c
blobd7fe906b01214642de814d9cdd405418fc8d178c
1 /**
2 * @file sipmsg.c
4 * purple
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
23 #include "internal.h"
25 #include "accountopt.h"
26 #include "buddylist.h"
27 #include "conversation.h"
28 #include "debug.h"
29 #include "notify.h"
30 #include "protocol.h"
31 #include "plugins.h"
32 #include "util.h"
33 #include "version.h"
35 #include "simple.h"
36 #include "sipmsg.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");
42 char *line;
43 struct sipmsg *smsg;
45 if(!tmp) return NULL;
47 line = g_strndup(msg, tmp - msg);
49 smsg = sipmsg_parse_header(line);
50 if(smsg != NULL)
51 smsg->body = g_strdup(tmp + 4);
52 else
53 purple_debug_error("SIMPLE", "No header parsed from line: %s\n", line);
55 g_free(line);
56 return smsg;
59 struct sipmsg *sipmsg_parse_header(const gchar *header) {
60 struct sipmsg *msg;
61 gchar **parts, **lines;
62 gchar *dummy, *dummy2, *tmp;
63 const gchar *tmp2;
64 int i = 1;
66 lines = g_strsplit(header,"\r\n",0);
67 if(!lines[0]) {
68 g_strfreev(lines);
69 return NULL;
72 parts = g_strsplit(lines[0], " ", 3);
73 if(!parts[0] || !parts[1] || !parts[2]) {
74 g_strfreev(parts);
75 g_strfreev(lines);
76 return NULL;
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]);
86 msg->response = 0;
88 g_strfreev(parts);
90 for(i=1; lines[i] && strlen(lines[i])>2; i++) {
91 parts = g_strsplit(lines[i], ":", 2);
92 if(!parts[0] || !parts[1]) {
93 g_strfreev(parts);
94 g_strfreev(lines);
95 sipmsg_free(msg);
96 return NULL;
98 dummy = parts[1];
99 dummy2 = NULL;
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')) {
103 i++;
104 dummy = lines[i];
105 while(*dummy==' ' || *dummy=='\t') dummy++;
106 tmp = g_strdup_printf("%s %s",dummy2, dummy);
107 g_free(dummy2);
108 dummy2 = tmp;
110 sipmsg_add_header(msg, parts[0], dummy2);
111 g_free(dummy2);
112 g_strfreev(parts);
114 g_strfreev(lines);
116 tmp2 = sipmsg_find_header(msg, "Content-Length");
117 if (tmp2 != NULL)
118 msg->bodylen = strtol(tmp2, NULL, 10);
119 if (msg->bodylen < 0) {
120 purple_debug_warning("simple", "Invalid body length: %d",
121 msg->bodylen);
122 msg->bodylen = 0;
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);
127 msg->bodylen = 0;
130 if(msg->response) {
131 tmp2 = sipmsg_find_header(msg, "CSeq");
132 g_free(msg->method);
133 if(!tmp2) {
134 /* SHOULD NOT HAPPEN */
135 msg->method = NULL;
136 } else {
137 parts = g_strsplit(tmp2, " ", 2);
138 msg->method = g_strdup(parts[1]);
139 g_strfreev(parts);
143 return msg;
146 void sipmsg_print(const struct sipmsg *msg) {
147 GSList *cur;
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);
152 cur = msg->headers;
153 while(cur) {
154 elem = cur->data;
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) {
161 GSList *cur;
162 GString *outstr = g_string_new("");
163 struct siphdrelement *elem;
165 if(msg->response)
166 g_string_append_printf(outstr, "SIP/2.0 %d Unknown\r\n",
167 msg->response);
168 else
169 g_string_append_printf(outstr, "%s %s SIP/2.0\r\n",
170 msg->method, msg->target);
172 cur = msg->headers;
173 while(cur) {
174 elem = cur->data;
175 g_string_append_printf(outstr, "%s: %s\r\n", elem->name,
176 elem->value);
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);
196 g_free(elem->name);
197 g_free(elem->value);
198 g_free(elem);
200 g_free(msg->method);
201 g_free(msg->target);
202 g_free(msg->body);
203 g_free(msg);
206 void sipmsg_remove_header(struct sipmsg *msg, const gchar *name) {
207 struct siphdrelement *elem;
208 GSList *tmp = msg->headers;
209 while(tmp) {
210 elem = tmp->data;
211 if(g_ascii_strcasecmp(elem->name, name)==0) {
212 msg->headers = g_slist_remove(msg->headers, elem);
213 g_free(elem->name);
214 g_free(elem->value);
215 g_free(elem);
216 return;
218 tmp = g_slist_next(tmp);
220 return;
223 const gchar *sipmsg_find_header(struct sipmsg *msg, const gchar *name) {
224 GSList *tmp;
225 struct siphdrelement *elem;
226 tmp = msg->headers;
227 while(tmp) {
228 elem = tmp->data;
229 if(g_ascii_strcasecmp(elem->name, name)==0) {
230 return elem->value;
232 tmp = g_slist_next(tmp);
234 return NULL;