2 * Copyright (c) 2017-2020, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
23 #include <gmime/gmime.h>
28 /* User data for callback */
29 struct gmime_cb_data
{
35 /* Initialize GMime */
44 /* Callback to add things - get stuff out of mime so we can strcmp() it */
46 record_argument(GMimeObject
*parent
, GMimeObject
*part
, gpointer user_data
)
49 struct gmime_cb_data
*d
= (struct gmime_cb_data
*) user_data
;
51 if (!(GMIME_IS_PART(part
))) {
55 if (GMIME_IS_MESSAGE_PART(part
)) {
56 GMimeMessage
*m
= g_mime_message_part_get_message(
57 (GMimeMessagePart
*) part
);
59 g_mime_message_foreach(m
, record_argument
, user_data
);
62 GMimePart
*p
= (GMimePart
*) part
;
63 const char *name
= g_mime_object_get_content_disposition_parameter(part
,
71 size_t *set_this_len
= 0;
73 if (!strcmp(name
, "action")) {
74 set_this
= &d
->pc
.raw
.action
;
75 set_this_len
= &d
->pc
.raw
.action_len
;
76 } else if (!strcmp(name
, "board")) {
77 set_this
= &d
->pc
.raw
.board
;
78 set_this_len
= &d
->pc
.raw
.board_len
;
79 } else if (!strcmp(name
, "thread")) {
80 set_this
= &d
->pc
.raw
.thread
;
81 set_this_len
= &d
->pc
.raw
.thread_len
;
82 } else if (!strcmp(name
, "post")) {
83 set_this
= &d
->pc
.raw
.post
;
84 set_this_len
= &d
->pc
.raw
.post_len
;
85 } else if (!strcmp(name
, "name")) {
86 set_this
= &d
->pc
.raw
.name
;
87 set_this_len
= &d
->pc
.raw
.name_len
;
88 } else if (!strcmp(name
, "email")) {
89 set_this
= &d
->pc
.raw
.email
;
90 set_this_len
= &d
->pc
.raw
.email_len
;
91 } else if (!strcmp(name
, "subject")) {
92 set_this
= &d
->pc
.raw
.subject
;
93 set_this_len
= &d
->pc
.raw
.subject_len
;
94 } else if (!strcmp(name
, "comment")) {
95 set_this
= &d
->pc
.raw
.comment
;
96 set_this_len
= &d
->pc
.raw
.comment_len
;
97 } else if (!strcmp(name
, "comment")) {
98 set_this
= &d
->pc
.raw
.comment
;
99 set_this_len
= &d
->pc
.raw
.comment_len
;
100 } else if (!strcmp(name
, "challengeid")) {
101 set_this
= &d
->pc
.raw
.challenge_id
;
102 set_this_len
= &d
->pc
.raw
.challenge_id_len
;
103 } else if (!strcmp(name
, "challengeresponse")) {
104 set_this
= &d
->pc
.raw
.challenge_response
;
105 set_this_len
= &d
->pc
.raw
.challenge_response_len
;
106 } else if (!strcmp(name
, "file")) {
107 set_this
= &d
->pc
.raw
.file_contents
;
108 set_this_len
= &d
->pc
.raw
.file_contents_len
;
109 free(d
->pc
.raw
.file_name
);
110 d
->pc
.raw
.file_name
= 0;
111 d
->pc
.raw
.file_name_len
= 0;
112 const char *file_name
= g_mime_part_get_filename(p
);
115 file_name
= "[No filename provided]";
118 if (!(d
->pc
.raw
.file_name
= strdup(file_name
))) {
119 ERROR_MESSAGE("strdup");
125 d
->pc
.raw
.file_name_len
= strlen(d
->pc
.raw
.file_name
);
132 GMimeDataWrapper
*w
= 0;
137 if (!(w
= g_mime_part_get_content(p
))) {
143 if (!(s
= g_mime_data_wrapper_get_stream(w
))) {
149 l
= g_mime_stream_length(s
);
152 ERROR_MESSAGE("overflow");
158 if (!(buf
= malloc(l
+ 1))) {
159 PERROR_MESSAGE("malloc");
165 g_mime_stream_read(s
, buf
, l
);
171 /* Don't g_object_unref here. I think. */
175 * This is segmented off because, one day, I want to go full NIH.
176 * No pre/postconditions until then.
179 multipart_decompose(const char *full_data
, size_t full_data_len
, struct
187 struct gmime_cb_data d
= { 0 };
189 memcpy(&d
, post_cmd
, sizeof *post_cmd
);
191 if (!(s
= g_mime_stream_mem_new_with_buffer(full_data
,
193 ERROR_MESSAGE("Some kind of GMime error");
197 if (!(p
= g_mime_parser_new_with_stream(s
))) {
198 ERROR_MESSAGE("Some kind of GMime error");
202 if (!(m
= g_mime_parser_construct_message(p
, 0))) {
203 ERROR_MESSAGE("Some kind of GMime error");
207 g_mime_message_foreach(m
, record_argument
, (gpointer
) & d
);
210 ERROR_MESSAGE("Some kind of GMime error");
214 memcpy(post_cmd
, &d
.pc
, sizeof *post_cmd
);
233 /* Tear down GMime */
235 clean_multipart(void)