Subversion Repositories Okuu

Rev

Rev 5 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 nishi 1
/* $Id: news.c 3 2024-09-10 19:21:48Z nishi $ */
2
 
3
#define OK_NEWS_SRC
4
#include "ok_news.h"
5
 
6
#include "ok_util.h"
7
 
8
#include <stdio.h>
9
#include <stdbool.h>
10
#include <string.h>
11
#include <stdlib.h>
12
#include <stdint.h>
13
#include <sys/stat.h>
14
 
15
struct news_entry news_entry;
16
 
17
void ok_news_init(void){
18
	news_entry.from = NULL;
19
	news_entry.content = NULL;
20
}
21
 
22
int ok_news_read(const char* path){
23
 
24
	if(news_entry.from != NULL){
25
		free(news_entry.from);
26
		news_entry.from = NULL;
27
	}
28
	if(news_entry.content != NULL){
29
		free(news_entry.content);
30
		news_entry.content = NULL;
31
	}
32
 
33
	struct stat s;
34
	if(stat(path, &s) == 0){
35
		char* boundary = NULL;
36
		char* buffer = malloc(s.st_size + 1);
37
		buffer[s.st_size] = 0;
38
		FILE* f = fopen(path, "r");
39
		fread(buffer, s.st_size, 1, f);
40
 
41
		uint64_t i;
42
		bool newline = false;
43
		int incr = 0;
44
		char* l = malloc(1);
45
		l[0] = 0;
46
		bool header = true;
47
		bool ignore = false;
48
		bool bheader = false;
49
		for(i = 0; i < s.st_size; i++){
50
			if(buffer[i] == '\r'){
51
				if(buffer[i + 1] == '\n'){
52
					/* newline */
53
					i++;
54
					if(!header){
55
						char* line = malloc(i - 1 - incr + 1);
56
						line[i - 1 - incr] = 0;
57
						memcpy(line, buffer + incr, i - 1 - incr);
58
 
59
						if(strcmp(line, ".") == 0){
60
							free(line);
61
							break;
62
						}else{
63
							char* ln = line;
64
							if(line[0] == '.'){
65
								ln++;
66
							}
67
 
68
							if(news_entry.content == NULL){
69
								news_entry.content = malloc(1);
70
								news_entry.content[0] = 0;
71
							}
72
 
73
							if(boundary != NULL && strcmp(ln, boundary) == 0){
74
								bheader = true;
75
								ignore = true;
76
							}else if(boundary != NULL && bheader && strlen(ln) == 0){
77
								bheader = false;
78
								free(line);
79
								incr = i + 1;
80
								newline = true;
81
								continue;
82
							}else if(boundary != NULL && bheader){
83
								int j;
84
								for(j = 0; j < strlen(ln); j++){
85
									if(ln[j] == ':'){
86
										ln[j] = 0;
87
										if(strcasecmp(ln, "Content-Type") == 0){
88
											ignore = false;
89
											j++;
90
											for(; ln[j] != 0 && (ln[j] == ' ' || ln[j] == '\t'); j++);
91
											if(ln[j] != 0){
92
												char* v = ln + j;
93
												int k;
94
												for(k = 0; v[k] != 0; k++){
95
													if(v[k] == ';'){
96
														v[k] = 0;
97
														break;
98
													}
99
												}
100
												if(strcasecmp(v, "text/plain") == 0){
101
												}else{
102
													ignore = true;
103
												}
104
											}
105
										}
106
										break;
107
									}
108
								}
109
							}
110
 
111
							if(!ignore && !bheader){
112
								char* tmp = news_entry.content;
113
								news_entry.content = ok_strcat3(tmp, ln, "\n");
114
								free(tmp);
115
							}
116
						}
117
 
118
						free(line);
119
					}else if(newline){
120
						header = false;
121
					}else{
122
						char* line = malloc(i - 1 - incr + 1);
123
						line[i - 1 - incr] = 0;
124
						memcpy(line, buffer + incr, i - 1 - incr);
125
 
126
						char* last = ok_strdup(l);
127
						char* tmp = l;
128
						l = ok_strcat(tmp, line);
129
						free(tmp);
130
						bool al = false;
131
						if(('a' <= line[0] && line[0] <= 'z') || ('A' <= line[0] && line[0] <= 'Z')){
132
							free(l);
133
							l = ok_strdup(line);
134
							al = true;
135
						}
136
						if(al){
137
							char* ln = ok_strdup(l);
138
							int j;
139
							for(j = 0; ln[j] != 0; j++){
140
								if(ln[j] == ':'){
141
									char* key = ln;
142
									char* value = "";
143
									ln[j] = 0;
144
									j++;
145
									for(; ln[j] != 0 && (ln[j] == '\t' || ln[j] == ' '); j++);
146
									if(ln[j] != 0) value = ln + j;
147
									if(strcasecmp(key, "From") == 0){
148
										if(news_entry.from != NULL) free(news_entry.from);
149
										news_entry.from = ok_strdup(value);
150
									}else if(strcasecmp(key, "Content-Type") == 0){
151
										int k = 0;
152
										int incr2 = 0;
153
										for(k = 0; k <= strlen(value); k++){
154
											if(value[k] == ';' || value[k] == 0){
155
												char* attr = malloc(k - incr2 + 1);
156
												attr[k - incr2] = 0;
157
												memcpy(attr, value + incr2, k - incr2);
158
 
159
												int in;
160
												for(in = 0; attr[in] != 0; in++){
161
													if(attr[in] == '='){
162
														attr[in] = 0;
163
 
164
														if(strcasecmp(attr, "boundary") == 0){
165
															boundary = ok_strcat("--", attr + in + 1 + 1);
166
															boundary[strlen(attr + in + 1 + 1) - 1 + 2] = 0;
167
															ignore = true;
168
														}
169
 
170
														break;
171
													}
172
												}
173
 
174
												free(attr);
175
												k++;
176
												for(; value[k] != 0 && (value[k] == ' ' || value[k] == '\t'); k++);
177
												incr2 = k;
178
											}
179
										}
180
									}
181
								}
182
							}
183
							free(ln);
184
						}
185
						free(last);
186
						free(line);
187
					}
188
					incr = i + 1;
189
					newline = true;
190
				}else{
191
					newline = false;
192
				}
193
			}else{
194
				newline = false;
195
			}
196
		}
197
		free(l);
198
 
199
		free(buffer);
200
		if(boundary != NULL) free(boundary);
201
		return 0;
202
	}else{
203
		return 1;
204
	}
205
}