Replace functions which called once with their bodies
[pidgin-git.git] / libpurple / protocols / simple / sipmsg.c
blobacbfcc6737f71e5060c40bd1d7baf407919ec98d
1 /**
2 * purple
4 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include "internal.h"
22 #include <purple.h>
24 #include "simple.h"
25 #include "sipmsg.h"
27 #define MAX_CONTENT_LENGTH 30000000
29 struct sipmsg *sipmsg_parse_msg(const gchar *msg) {
30 const char *tmp = strstr(msg, "\r\n\r\n");
31 char *line;
32 struct sipmsg *smsg;
34 if(!tmp) return NULL;
36 line = g_strndup(msg, tmp - msg);
38 smsg = sipmsg_parse_header(line);
39 if(smsg != NULL)
40 smsg->body = g_strdup(tmp + 4);
41 else
42 purple_debug_error("SIMPLE", "No header parsed from line: %s\n", line);
44 g_free(line);
45 return smsg;
48 struct sipmsg *sipmsg_parse_header(const gchar *header) {
49 struct sipmsg *msg;
50 gchar **parts, **lines;
51 gchar *dummy, *dummy2, *tmp;
52 const gchar *tmp2;
53 int i = 1;
55 lines = g_strsplit(header,"\r\n",0);
56 if(!lines[0]) {
57 g_strfreev(lines);
58 return NULL;
61 parts = g_strsplit(lines[0], " ", 3);
62 if(!parts[0] || !parts[1] || !parts[2]) {
63 g_strfreev(parts);
64 g_strfreev(lines);
65 return NULL;
68 msg = g_new0(struct sipmsg,1);
69 if(strstr(parts[0],"SIP")) { /* numeric response */
70 msg->method = g_strdup(parts[2]);
71 msg->response = strtol(parts[1],NULL,10);
72 } else { /* request */
73 msg->method = g_strdup(parts[0]);
74 msg->target = g_strdup(parts[1]);
75 msg->response = 0;
77 g_strfreev(parts);
79 for(i=1; lines[i] && strlen(lines[i])>2; i++) {
80 parts = g_strsplit(lines[i], ":", 2);
81 if(!parts[0] || !parts[1]) {
82 g_strfreev(parts);
83 g_strfreev(lines);
84 sipmsg_free(msg);
85 return NULL;
87 dummy = parts[1];
88 dummy2 = NULL;
89 while(*dummy==' ' || *dummy=='\t') dummy++;
90 dummy2 = g_strdup(dummy);
91 while(lines[i+1] && (lines[i+1][0]==' ' || lines[i+1][0]=='\t')) {
92 i++;
93 dummy = lines[i];
94 while(*dummy==' ' || *dummy=='\t') dummy++;
95 tmp = g_strdup_printf("%s %s",dummy2, dummy);
96 g_free(dummy2);
97 dummy2 = tmp;
99 sipmsg_add_header(msg, parts[0], dummy2);
100 g_free(dummy2);
101 g_strfreev(parts);
103 g_strfreev(lines);
105 tmp2 = sipmsg_find_header(msg, "Content-Length");
106 if (tmp2 != NULL)
107 msg->bodylen = strtol(tmp2, NULL, 10);
108 if (msg->bodylen < 0) {
109 purple_debug_warning("simple", "Invalid body length: %d",
110 msg->bodylen);
111 msg->bodylen = 0;
112 } else if (msg->bodylen > MAX_CONTENT_LENGTH) {
113 purple_debug_warning("simple", "Got Content-Length of %d bytes on "
114 "incoming message (max is %u bytes). Ignoring message body.\n",
115 msg->bodylen, MAX_CONTENT_LENGTH);
116 msg->bodylen = 0;
119 if(msg->response) {
120 tmp2 = sipmsg_find_header(msg, "CSeq");
121 g_free(msg->method);
122 if(!tmp2) {
123 /* SHOULD NOT HAPPEN */
124 msg->method = NULL;
125 } else {
126 parts = g_strsplit(tmp2, " ", 2);
127 msg->method = g_strdup(parts[1]);
128 g_strfreev(parts);
132 return msg;
135 void sipmsg_print(const struct sipmsg *msg) {
136 GSList *cur;
137 struct siphdrelement *elem;
138 purple_debug(PURPLE_DEBUG_MISC, "simple", "SIP MSG\n");
139 purple_debug(PURPLE_DEBUG_MISC, "simple", "response: %d\nmethod: %s\nbodylen: %d\n",msg->response,msg->method,msg->bodylen);
140 if(msg->target) purple_debug(PURPLE_DEBUG_MISC, "simple", "target: %s\n",msg->target);
141 cur = msg->headers;
142 while(cur) {
143 elem = cur->data;
144 purple_debug(PURPLE_DEBUG_MISC, "simple", "name: %s value: %s\n",elem->name, elem->value);
145 cur = g_slist_next(cur);
149 char *sipmsg_to_string(const struct sipmsg *msg) {
150 GSList *cur;
151 GString *outstr = g_string_new("");
152 struct siphdrelement *elem;
154 if(msg->response)
155 g_string_append_printf(outstr, "SIP/2.0 %d Unknown\r\n",
156 msg->response);
157 else
158 g_string_append_printf(outstr, "%s %s SIP/2.0\r\n",
159 msg->method, msg->target);
161 cur = msg->headers;
162 while(cur) {
163 elem = cur->data;
164 g_string_append_printf(outstr, "%s: %s\r\n", elem->name,
165 elem->value);
166 cur = g_slist_next(cur);
169 g_string_append_printf(outstr, "\r\n%s", msg->bodylen ? msg->body : "");
171 return g_string_free(outstr, FALSE);
173 void sipmsg_add_header(struct sipmsg *msg, const gchar *name, const gchar *value) {
174 struct siphdrelement *element = g_new(struct siphdrelement,1);
175 element->name = g_strdup(name);
176 element->value = g_strdup(value);
177 msg->headers = g_slist_append(msg->headers, element);
180 void sipmsg_free(struct sipmsg *msg) {
181 struct siphdrelement *elem;
182 while(msg->headers) {
183 elem = msg->headers->data;
184 msg->headers = g_slist_remove(msg->headers,elem);
185 g_free(elem->name);
186 g_free(elem->value);
187 g_free(elem);
189 g_free(msg->method);
190 g_free(msg->target);
191 g_free(msg->body);
192 g_free(msg);
195 void sipmsg_remove_header(struct sipmsg *msg, const gchar *name) {
196 GSList *tmp = g_slist_find_custom(msg->headers, name, (GCompareFunc)g_ascii_strcasecmp);
197 if(tmp) {
198 struct siphdrelement *elem = tmp->data;
199 msg->headers = g_slist_delete_link(msg->headers, tmp);
200 g_free(elem->name);
201 g_free(elem->value);
202 g_free(elem);
206 const gchar *sipmsg_find_header(struct sipmsg *msg, const gchar *name) {
207 GSList *tmp = g_slist_find_custom(msg->headers, name, (GCompareFunc)g_ascii_strcasecmp);
208 if(tmp) {
209 struct siphdrelement *elem = tmp->data;
210 return elem->value;
212 return NULL;