Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00039 #include "../trim.h"
00040 #include "parser_f.h"
00041 #include "parse_content.h"
00042 #include "parse_param.h"
00043 #include "keys.h"
00044 #include "parse_body.h"
00045
00047 static inline int get_boundary_param(struct sip_msg *msg, str *boundary)
00048 {
00049 str s;
00050 char *c;
00051 param_t *p, *list;
00052
00053 #define is_boundary(c) \
00054 (((c)[0] == 'b' || (c)[0] == 'B') && \
00055 ((c)[1] == 'o' || (c)[1] == 'O') && \
00056 ((c)[2] == 'u' || (c)[2] == 'U') && \
00057 ((c)[3] == 'n' || (c)[3] == 'N') && \
00058 ((c)[4] == 'd' || (c)[4] == 'D') && \
00059 ((c)[5] == 'a' || (c)[5] == 'A') && \
00060 ((c)[6] == 'r' || (c)[6] == 'R') && \
00061 ((c)[7] == 'y' || (c)[7] == 'Y'))
00062
00063 #define boundary_param_len (sizeof("boundary")-1)
00064
00065
00066 s.s = msg->content_type->body.s;
00067 s.len = msg->content_type->body.len;
00068 c = find_not_quoted(&s, ';');
00069 if (!c)
00070 return -1;
00071 c++;
00072 s.len = s.len - (c - s.s);
00073 s.s = c;
00074 trim_leading(&s);
00075
00076 if (s.len <= 0)
00077 return -1;
00078
00079
00080 if (parse_params(&s, CLASS_ANY, NULL, &list)<0)
00081 return -1;
00082
00083 boundary->s = NULL;
00084 for (p = list; p; p = p->next)
00085 if ((p->name.len == boundary_param_len) &&
00086 is_boundary(p->name.s)
00087 ) {
00088 boundary->s = p->body.s;
00089 boundary->len = p->body.len;
00090 break;
00091 }
00092 free_params(list);
00093 if (!boundary->s || !boundary->len)
00094 return -1;
00095
00096 DBG("boundary is \"%.*s\"\n",
00097 boundary->len, boundary->s);
00098 return 0;
00099 }
00100
00102 static inline char *search_boundary(char *buf, char *buf_end, str *boundary)
00103 {
00104 char *c;
00105
00106 c = buf;
00107 while (c + 2 + boundary->len < buf_end) {
00108 if ((*c == '-') && (*(c+1) == '-') &&
00109 (memcmp(c+2, boundary->s, boundary->len) == 0)
00110 )
00111 return c;
00112
00113
00114 while ((c < buf_end) && (*c != '\n')) c++;
00115 c++;
00116 }
00117 return NULL;
00118 }
00119
00121 inline static char *get_multipart_body(char *buf,
00122 char *buf_end,
00123 str *boundary,
00124 int *len)
00125 {
00126 char *beg, *end;
00127
00128 if (buf >= buf_end)
00129 goto error;
00130
00131 beg = buf;
00132 while ((*beg != '\r') && (*beg != '\n')) {
00133 while ((beg < buf_end) && (*beg != '\n'))
00134 beg++;
00135 beg++;
00136 if (beg >= buf_end)
00137 goto error;
00138 }
00139
00140 while ((beg < buf_end) && (*beg != '\n'))
00141 beg++;
00142 beg++;
00143 if (beg >= buf_end)
00144 goto error;
00145
00146 if (!(end = search_boundary(beg, buf_end, boundary)))
00147 goto error;
00148
00149
00150
00151 if (*(end-1) == '\n') end--;
00152 if (*(end-1) == '\r') end--;
00153
00154 if (end < beg)
00155 goto error;
00156
00157 *len = end-beg;
00158 return beg;
00159 error:
00160 ERR("failed to extract the body from the multipart mime type\n");
00161 return NULL;
00162 }
00163
00164
00166 #define READ(val) \
00167 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00168
00169 #define LOWER_DWORD(d) ((d) | 0x20202020)
00170
00175 char *get_body_part( struct sip_msg *msg,
00176 unsigned short type, unsigned short subtype,
00177 int *len)
00178 {
00179 int mime;
00180 unsigned int umime;
00181 char *c, *c2, *buf_end;
00182 str boundary;
00183
00184 #define content_type_len \
00185 (sizeof("Content-Type") - 1)
00186
00187 if ((mime = parse_content_type_hdr(msg)) <= 0)
00188 return NULL;
00189
00190 if (mime == ((type<<16)|subtype)) {
00191
00192 c = get_body(msg);
00193 if (c)
00194 *len = msg->buf+msg->len - c;
00195 return c;
00196
00197 } else if ((mime>>16) == TYPE_MULTIPART) {
00198
00199
00200 if (get_boundary_param(msg, &boundary)) {
00201 ERR("failed to get boundary parameter\n");
00202 return NULL;
00203 }
00204 if (!(c = get_body(msg)))
00205 return NULL;
00206 buf_end = msg->buf+msg->len;
00207
00208
00209
00210
00211 next_part:
00212 while ((c = search_boundary(c, buf_end, &boundary))) {
00213
00214 c += 2 + boundary.len;
00215
00216 if ((c+2 > buf_end) ||
00217 ((*c == '-') && (*(c+1) == '-'))
00218 )
00219
00220
00221 return NULL;
00222
00223
00224 while ((c < buf_end) && (*c != '\n')) c++;
00225 c++;
00226 if (c >= buf_end)
00227 return NULL;
00228
00229
00230 while ((*c != '\r') && (*c != '\n')) {
00231 if (c + content_type_len >= buf_end)
00232 return NULL;
00233
00234 if ((LOWER_DWORD(READ(c)) == _cont_) &&
00235 (LOWER_DWORD(READ(c+4)) == _ent__) &&
00236 (LOWER_DWORD(READ(c+8)) == _type_)
00237 ) {
00238
00239 c += content_type_len;
00240 while ((c < buf_end) &&
00241 ((*c == ' ') || (*c == '\t'))
00242 )
00243 c++;
00244
00245 if (c + 1 >= buf_end)
00246 return NULL;
00247
00248 if (*c != ':')
00249
00250 goto next_hf;
00251 c++;
00252
00253
00254
00255 c2 = c;
00256 while (((c2 < buf_end) && (*c2 != '\n')) ||
00257 ((c2+1 < buf_end) && (*c2 == '\n') &&
00258 ((*(c2+1) == ' ') || (*(c2+1) == '\t')))
00259 )
00260 c2++;
00261
00262 if (c2 >= buf_end)
00263 return NULL;
00264 if (*(c2-1) == '\r') c2--;
00265
00266 if (!decode_mime_type(c, c2 , &umime)) {
00267 ERR("failed to decode the mime type\n");
00268 return NULL;
00269 }
00270
00271
00272
00273 c = c2;
00274 if ((c < buf_end) && (*c == '\r')) c++;
00275 if ((c < buf_end) && (*c == '\n')) c++;
00276
00277 if (umime != ((type<<16)|subtype)) {
00278
00279 goto next_part;
00280 }
00281
00282
00283 return get_multipart_body(c,
00284 buf_end,
00285 &boundary,
00286 len);
00287 }
00288 next_hf:
00289
00290 while ((c < buf_end) && (*c != '\n')) c++;
00291 c++;
00292 }
00293
00294
00295 }
00296 }
00297 return NULL;
00298 }