Subversion Repositories RepoView

Rev

Rev 42 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
41 nishi 1
/* $Id: multipart.c 44 2024-08-22 05:52:32Z nishi $ */
2
 
3
#include "rv_multipart.h"
4
 
5
#include "rv_util.h"
6
 
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <string.h>
10
 
11
struct multipart_entry** multipart_entries = NULL;
12
 
13
void rv_free_multipart(void) {
14
	if(multipart_entries == NULL) return;
15
	int i;
16
	for(i = 0; multipart_entries[i] != NULL; i++) {
17
		free(multipart_entries[i]->name);
18
		free(multipart_entries[i]->data);
19
		free(multipart_entries[i]);
20
	}
21
	free(multipart_entries);
22
}
23
 
24
struct multipart_entry* rv_get_multipart(const char* name) {
25
	if(multipart_entries == NULL) return NULL;
26
	int i;
27
	for(i = 0; multipart_entries[i] != NULL; i++) {
28
		if(strcmp(multipart_entries[i]->name, name) == 0) {
29
			return multipart_entries[i];
30
		}
31
	}
32
	return NULL;
33
}
34
 
35
void rv_parse_multipart(unsigned char* buffer, char* boundary, unsigned long long length) {
36
	unsigned long long i;
37
	int incr = 0;
38
	int phase = 0;
39
	unsigned long long fstart = 0;
40
	char* b = rv_strcat3("--", boundary, "\r");
41
	char* eb = rv_strcat3("--", boundary, "--\r");
42 nishi 42
	multipart_entries = malloc(sizeof(*multipart_entries));
43
	multipart_entries[0] = NULL;
44
	char* name = NULL;
41 nishi 45
	for(i = 0;; i++) {
46
		if(i == length || buffer[i] == '\n') {
47
			char* line = malloc(i - incr + 1);
48
			memcpy(line, buffer + incr, i - incr);
49
			line[i - incr] = 0;
50
			if(line[0] == '\r' && phase == 0) {
51
				phase = 1;
52
				fstart = i + 1;
53
			} else if(strcmp(b, line) == 0 || strcmp(eb, line) == 0) {
54
				if(phase == 1) {
55
					unsigned long long fend = i - strlen(line) - 2;
44 nishi 56
					char* data = (char*)buffer + fstart;
41 nishi 57
					unsigned long long datalen = fend - fstart;
42 nishi 58
					struct multipart_entry* entry = malloc(sizeof(*entry));
59
					entry->length = datalen;
60
					entry->data = malloc(datalen);
61
					entry->name = rv_strdup(name);
62
					unsigned long long j;
63
					for(j = 0; j < datalen; j++) entry->data[j] = data[j];
64
 
65
					struct multipart_entry** old_entries = multipart_entries;
66
					for(j = 0; old_entries[j] != NULL; j++)
67
						;
68
					multipart_entries = malloc(sizeof(*multipart_entries) * (j + 2));
69
					for(j = 0; old_entries[j] != NULL; j++) {
70
						multipart_entries[j] = old_entries[j];
71
					}
72
					multipart_entries[j] = entry;
73
					multipart_entries[j + 1] = NULL;
74
					free(old_entries);
41 nishi 75
				}
76
				phase = 0;
77
				if(strcmp(eb, line) == 0) {
78
					free(line);
79
					break;
80
				}
81
			} else if(phase == 0) {
82
				line[strlen(line) - 1] = 0;
42 nishi 83
				int j;
84
				for(j = 0; line[j] != 0; j++) {
85
					if(line[j] == ':') {
86
						line[j] = 0;
87
						char* value = "";
88
						j++;
89
						for(; line[j] != 0; j++) {
90
							if(line[j] != ' ' && line[j] != '\t') {
91
								value = line + j;
92
								break;
93
							}
94
						}
95
						if(strcasecmp(line, "Content-Disposition") == 0) {
96
							int j;
97
							int incrval = 0;
98
							for(j = 0;; j++) {
99
								if(value[j] == ';' || value[j] == 0) {
100
									char oldc = value[j];
101
									value[j] = 0;
102
									char* kv = value + incrval;
103
									j++;
104
									for(; value[j] != 0; j++) {
105
										if(value[j] != ' ' && value[j] != '\t') break;
106
									}
107
									incrval = j;
108
									int k;
109
									for(k = 0; kv[k] != 0; k++) {
110
										if(kv[k] == '=') {
111
											kv[k] = 0;
112
											if(strcmp(kv, "name") == 0) {
113
												if(name != NULL) free(name);
114
												name = malloc(strlen(kv + k + 1) + 1);
115
												char* nkv = kv + k + 1;
116
												int l = 0;
117
												int incrn = 0;
118
												for(l = 0; nkv[l] != 0; l++) {
119
													if(nkv[l] != '"') {
120
														name[incrn++] = nkv[l];
121
													}
122
												}
123
												name[incrn] = 0;
124
											}
125
											break;
126
										}
127
									}
128
									if(oldc == 0) break;
129
								}
130
							}
131
						}
132
						break;
133
					}
134
				}
41 nishi 135
			}
136
			free(line);
137
			incr = i + 1;
138
			if(i == length) break;
139
		}
140
	}
42 nishi 141
	if(name != NULL) free(name);
41 nishi 142
	free(b);
143
}