misc: update copyright years
[rb-79.git] / multipart.c
blob10990d409ee9d4f87e30cb535211a0cc5142f48d
1 /*
2 * Copyright (c) 2017-2018, 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
7 * copies.
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.
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
23 #include <gmime/gmime.h>
25 #include "macros.h"
26 #include "rb79.h"
28 /* User data for callback */
29 struct gmime_cb_data {
30 /* */
31 struct post_cmd pc;
32 int had_error;
35 /* Initialize GMime */
36 int setup_multipart(void)
38 g_mime_init(0);
40 return 0;
43 /* Callback to add things - get stuff out of mime so we can strcmp() it */
44 static void record_argument(GMimeObject *parent, GMimeObject *part, gpointer
45 user_data)
47 UNUSED(parent);
48 struct gmime_cb_data *d = (struct gmime_cb_data *) user_data;
50 if (!(GMIME_IS_PART(part))) {
51 return;
54 if (GMIME_IS_MESSAGE_PART(part)) {
55 GMimeMessage *m = g_mime_message_part_get_message(
56 (GMimeMessagePart *) part);
58 g_mime_message_foreach(m, record_argument, user_data);
61 GMimePart *p = (GMimePart *) part;
62 const char *name = g_mime_object_get_content_disposition_parameter(part,
63 "name");
65 if (!name) {
66 return;
69 char **set_this = 0;
70 size_t *set_this_len = 0;
72 if (!strcmp(name, "action")) {
73 set_this = &d->pc.raw.action;
74 set_this_len = &d->pc.raw.action_len;
75 } else if (!strcmp(name, "board")) {
76 set_this = &d->pc.raw.board;
77 set_this_len = &d->pc.raw.board_len;
78 } else if (!strcmp(name, "thread")) {
79 set_this = &d->pc.raw.thread;
80 set_this_len = &d->pc.raw.thread_len;
81 } else if (!strcmp(name, "post")) {
82 set_this = &d->pc.raw.post;
83 set_this_len = &d->pc.raw.post_len;
84 } else if (!strcmp(name, "name")) {
85 set_this = &d->pc.raw.name;
86 set_this_len = &d->pc.raw.name_len;
87 } else if (!strcmp(name, "email")) {
88 set_this = &d->pc.raw.email;
89 set_this_len = &d->pc.raw.email_len;
90 } else if (!strcmp(name, "subject")) {
91 set_this = &d->pc.raw.subject;
92 set_this_len = &d->pc.raw.subject_len;
93 } else if (!strcmp(name, "comment")) {
94 set_this = &d->pc.raw.comment;
95 set_this_len = &d->pc.raw.comment_len;
96 } else if (!strcmp(name, "comment")) {
97 set_this = &d->pc.raw.comment;
98 set_this_len = &d->pc.raw.comment_len;
99 } else if (!strcmp(name, "challengeid")) {
100 set_this = &d->pc.raw.challenge_id;
101 set_this_len = &d->pc.raw.challenge_id_len;
102 } else if (!strcmp(name, "challengeresponse")) {
103 set_this = &d->pc.raw.challenge_response;
104 set_this_len = &d->pc.raw.challenge_response_len;
105 } else if (!strcmp(name, "file")) {
106 set_this = &d->pc.raw.file_contents;
107 set_this_len = &d->pc.raw.file_contents_len;
108 free(d->pc.raw.file_name);
109 d->pc.raw.file_name = 0;
110 d->pc.raw.file_name_len = 0;
111 const char *file_name = g_mime_part_get_filename(p);
113 if (!file_name) {
114 file_name = "[No filename provided]";
117 if (!(d->pc.raw.file_name = strdup(file_name))) {
118 ERROR_MESSAGE("strdup");
119 d->had_error = 1;
121 return;
124 d->pc.raw.file_name_len = strlen(d->pc.raw.file_name);
127 if (!set_this) {
128 return;
131 GMimeDataWrapper *w = 0;
132 GMimeStream *s = 0;
133 size_t l = 0;
134 char *buf = 0;
136 if (!(w = g_mime_part_get_content_object(p))) {
137 d->had_error = 1;
139 return;
142 if (!(s = g_mime_data_wrapper_get_stream(w))) {
143 d->had_error = 1;
145 return;
148 l = g_mime_stream_length(s);
150 if (l + 1 < l) {
151 ERROR_MESSAGE("overflow");
152 d->had_error = 1;
154 return;
157 if (!(buf = malloc(l + 1))) {
158 PERROR_MESSAGE("malloc");
159 d->had_error = 1;
161 return;
164 g_mime_stream_read(s, buf, l);
165 buf[l] = '\0';
166 free(*set_this);
167 *set_this = buf;
168 *set_this_len = l;
170 /* Don't g_object_unref here. I think. */
174 * This is segmented off because, one day, I want to go full NIH.
175 * No pre/postconditions until then.
177 int multipart_decompose(const char *full_data, size_t full_data_len, struct
178 post_cmd *post_cmd)
180 GMimeStream *s = 0;
181 GMimeParser *p = 0;
182 GMimeMessage *m = 0;
183 int had_error = 0;
184 int ret = -1;
185 struct gmime_cb_data d = { 0 };
187 memcpy(&d, post_cmd, sizeof *post_cmd);
189 if (!(s = g_mime_stream_mem_new_with_buffer(full_data,
190 full_data_len))) {
191 ERROR_MESSAGE("Some kind of GMime error");
192 goto done;
195 if (!(p = g_mime_parser_new_with_stream(s))) {
196 ERROR_MESSAGE("Some kind of GMime error");
197 goto done;
200 if (!(m = g_mime_parser_construct_message(p))) {
201 ERROR_MESSAGE("Some kind of GMime error");
202 goto done;
205 g_mime_message_foreach(m, record_argument, (gpointer) & d);
207 if (had_error) {
208 ERROR_MESSAGE("Some kind of GMime error");
209 goto done;
212 memcpy(post_cmd, &d.pc, sizeof *post_cmd);
213 ret = 0;
214 done:
216 if (s) {
217 g_object_unref(s);
220 if (p) {
221 g_object_unref(p);
224 if (m) {
225 g_object_unref(m);
228 return ret;
231 /* Tear down GMime */
232 int clean_multipart(void)
234 g_mime_shutdown();
236 return 0;