Subversion Repositories Okuu

Rev

Rev 10 | Rev 13 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 10 Rev 11
Line 1... Line 1...
1
/* $Id: news.c 10 2024-09-11 10:17:32Z nishi $ */
1
/* $Id: news.c 11 2024-09-11 10:24:20Z nishi $ */
2
 
2
 
3
#define OK_NEWS_SRC
3
#define OK_NEWS_SRC
4
#include "ok_news.h"
4
#include "ok_news.h"
5
 
5
 
6
#include "ok_util.h"
6
#include "ok_util.h"
Line 31... Line 31...
31
 
31
 
32
struct news_entry news_entry;
32
struct news_entry news_entry;
33
 
33
 
34
void ok_close(int sock);
34
void ok_close(int sock);
35
 
35
 
36
void ok_news_init(void){
36
void ok_news_init(void) {
37
	news_entry.from = NULL;
37
	news_entry.from = NULL;
38
	news_entry.content = NULL;
38
	news_entry.content = NULL;
39
}
39
}
40
 
40
 
41
int ok_news_read(const char* path){
41
int ok_news_read(const char* path) {
42
	if(news_entry.from != NULL){
42
	if(news_entry.from != NULL) {
43
		free(news_entry.from);
43
		free(news_entry.from);
44
		news_entry.from = NULL;
44
		news_entry.from = NULL;
45
	}
45
	}
46
	if(news_entry.content != NULL){
46
	if(news_entry.content != NULL) {
47
		free(news_entry.content);
47
		free(news_entry.content);
48
		news_entry.content = NULL;
48
		news_entry.content = NULL;
49
	}
49
	}
50
 
50
 
51
	struct stat s;
51
	struct stat s;
52
	if(stat(path, &s) == 0){
52
	if(stat(path, &s) == 0) {
53
		char* boundary = NULL;
53
		char* boundary = NULL;
54
		char* buffer = malloc(s.st_size + 1);
54
		char* buffer = malloc(s.st_size + 1);
55
		buffer[s.st_size] = 0;
55
		buffer[s.st_size] = 0;
56
		FILE* f = fopen(path, "r");
56
		FILE* f = fopen(path, "r");
57
		fread(buffer, s.st_size, 1, f);
57
		fread(buffer, s.st_size, 1, f);
Line 62... Line 62...
62
		char* l = malloc(1);
62
		char* l = malloc(1);
63
		l[0] = 0;
63
		l[0] = 0;
64
		bool header = true;
64
		bool header = true;
65
		bool ignore = false;
65
		bool ignore = false;
66
		bool bheader = false;
66
		bool bheader = false;
67
		for(i = 0; i < s.st_size; i++){
67
		for(i = 0; i < s.st_size; i++) {
68
			if(buffer[i] == '\r'){
68
			if(buffer[i] == '\r') {
69
				if(buffer[i + 1] == '\n'){
69
				if(buffer[i + 1] == '\n') {
70
					/* newline */
70
					/* newline */
71
					i++;
71
					i++;
72
					if(!header){
72
					if(!header) {
73
						char* line = malloc(i - 1 - incr + 1);
73
						char* line = malloc(i - 1 - incr + 1);
74
						line[i - 1 - incr] = 0;
74
						line[i - 1 - incr] = 0;
75
						memcpy(line, buffer + incr, i - 1 - incr);
75
						memcpy(line, buffer + incr, i - 1 - incr);
76
 
76
 
77
						if(strcmp(line, ".") == 0){
77
						if(strcmp(line, ".") == 0) {
78
							free(line);
78
							free(line);
79
							break;
79
							break;
80
						}else{
80
						} else {
81
							char* ln = line;
81
							char* ln = line;
82
							if(line[0] == '.'){
82
							if(line[0] == '.') {
83
								ln++;
83
								ln++;
84
							}
84
							}
85
 
85
 
86
							if(news_entry.content == NULL){
86
							if(news_entry.content == NULL) {
87
								news_entry.content = malloc(1);
87
								news_entry.content = malloc(1);
88
								news_entry.content[0] = 0;
88
								news_entry.content[0] = 0;
89
							}
89
							}
90
 
90
 
91
							if(boundary != NULL && strcmp(ln, boundary) == 0){
91
							if(boundary != NULL && strcmp(ln, boundary) == 0) {
92
								bheader = true;
92
								bheader = true;
93
								ignore = true;
93
								ignore = true;
94
							}else if(boundary != NULL && bheader && strlen(ln) == 0){
94
							} else if(boundary != NULL && bheader && strlen(ln) == 0) {
95
								bheader = false;
95
								bheader = false;
96
								free(line);
96
								free(line);
97
								incr = i + 1;
97
								incr = i + 1;
98
								newline = true;
98
								newline = true;
99
								continue;
99
								continue;
100
							}else if(boundary != NULL && bheader){
100
							} else if(boundary != NULL && bheader) {
101
								int j;
101
								int j;
102
								for(j = 0; j < strlen(ln); j++){
102
								for(j = 0; j < strlen(ln); j++) {
103
									if(ln[j] == ':'){
103
									if(ln[j] == ':') {
104
										ln[j] = 0;
104
										ln[j] = 0;
105
										if(strcasecmp(ln, "Content-Type") == 0){
105
										if(strcasecmp(ln, "Content-Type") == 0) {
106
											ignore = false;
106
											ignore = false;
107
											j++;
107
											j++;
108
											for(; ln[j] != 0 && (ln[j] == ' ' || ln[j] == '\t'); j++);
108
											for(; ln[j] != 0 && (ln[j] == ' ' || ln[j] == '\t'); j++)
-
 
109
												;
109
											if(ln[j] != 0){
110
											if(ln[j] != 0) {
110
												char* v = ln + j;
111
												char* v = ln + j;
111
												int k;
112
												int k;
112
												for(k = 0; v[k] != 0; k++){
113
												for(k = 0; v[k] != 0; k++) {
113
													if(v[k] == ';'){
114
													if(v[k] == ';') {
114
														v[k] = 0;
115
														v[k] = 0;
115
														break;
116
														break;
116
													}
117
													}
117
												}
118
												}
118
												if(strcasecmp(v, "text/plain") == 0){
119
												if(strcasecmp(v, "text/plain") == 0) {
119
												}else{
120
												} else {
120
													ignore = true;
121
													ignore = true;
121
												}
122
												}
122
											}
123
											}
123
										}
124
										}
124
										break;
125
										break;
125
									}
126
									}
126
								}
127
								}
127
							}
128
							}
128
 
129
 
129
							if(!ignore && !bheader){
130
							if(!ignore && !bheader) {
130
								char* tmp = news_entry.content;
131
								char* tmp = news_entry.content;
131
								news_entry.content = ok_strcat3(tmp, ln, "\n");
132
								news_entry.content = ok_strcat3(tmp, ln, "\n");
132
								free(tmp);
133
								free(tmp);
133
							}
134
							}
134
						}
135
						}
135
 
136
 
136
						free(line);
137
						free(line);
137
					}else if(newline){
138
					} else if(newline) {
138
						header = false;
139
						header = false;
139
					}else{
140
					} else {
140
						char* line = malloc(i - 1 - incr + 1);
141
						char* line = malloc(i - 1 - incr + 1);
141
						line[i - 1 - incr] = 0;
142
						line[i - 1 - incr] = 0;
142
						memcpy(line, buffer + incr, i - 1 - incr);
143
						memcpy(line, buffer + incr, i - 1 - incr);
143
 
144
 
144
						char* last = ok_strdup(l);
145
						char* last = ok_strdup(l);
145
						char* tmp = l;
146
						char* tmp = l;
146
						l = ok_strcat(tmp, line);
147
						l = ok_strcat(tmp, line);
147
						free(tmp);
148
						free(tmp);
148
						bool al = false;
149
						bool al = false;
149
						if(('a' <= line[0] && line[0] <= 'z') || ('A' <= line[0] && line[0] <= 'Z')){
150
						if(('a' <= line[0] && line[0] <= 'z') || ('A' <= line[0] && line[0] <= 'Z')) {
150
							free(l);
151
							free(l);
151
							l = ok_strdup(line);
152
							l = ok_strdup(line);
152
							al = true;
153
							al = true;
153
						}
154
						}
154
						if(al){
155
						if(al) {
155
							char* ln = ok_strdup(l);
156
							char* ln = ok_strdup(l);
156
							int j;
157
							int j;
157
							for(j = 0; ln[j] != 0; j++){
158
							for(j = 0; ln[j] != 0; j++) {
158
								if(ln[j] == ':'){
159
								if(ln[j] == ':') {
159
									char* key = ln;
160
									char* key = ln;
160
									char* value = "";
161
									char* value = "";
161
									ln[j] = 0;
162
									ln[j] = 0;
162
									j++;
163
									j++;
163
									for(; ln[j] != 0 && (ln[j] == '\t' || ln[j] == ' '); j++);
164
									for(; ln[j] != 0 && (ln[j] == '\t' || ln[j] == ' '); j++)
-
 
165
										;
164
									if(ln[j] != 0) value = ln + j;
166
									if(ln[j] != 0) value = ln + j;
165
									if(strcasecmp(key, "From") == 0){
167
									if(strcasecmp(key, "From") == 0) {
166
										if(news_entry.from != NULL) free(news_entry.from);
168
										if(news_entry.from != NULL) free(news_entry.from);
167
										news_entry.from = ok_strdup(value);
169
										news_entry.from = ok_strdup(value);
168
									}else if(strcasecmp(key, "Content-Type") == 0){
170
									} else if(strcasecmp(key, "Content-Type") == 0) {
169
										int k = 0;
171
										int k = 0;
170
										int incr2 = 0;
172
										int incr2 = 0;
171
										for(k = 0; k <= strlen(value); k++){
173
										for(k = 0; k <= strlen(value); k++) {
172
											if(value[k] == ';' || value[k] == 0){
174
											if(value[k] == ';' || value[k] == 0) {
173
												char* attr = malloc(k - incr2 + 1);
175
												char* attr = malloc(k - incr2 + 1);
174
												attr[k - incr2] = 0;
176
												attr[k - incr2] = 0;
175
												memcpy(attr, value + incr2, k - incr2);
177
												memcpy(attr, value + incr2, k - incr2);
176
 
178
 
177
												int in;
179
												int in;
178
												for(in = 0; attr[in] != 0; in++){
180
												for(in = 0; attr[in] != 0; in++) {
179
													if(attr[in] == '='){
181
													if(attr[in] == '=') {
180
														attr[in] = 0;
182
														attr[in] = 0;
181
 
183
 
182
														if(strcasecmp(attr, "boundary") == 0){
184
														if(strcasecmp(attr, "boundary") == 0) {
183
															boundary = ok_strcat("--", attr + in + 1 + 1);
185
															boundary = ok_strcat("--", attr + in + 1 + 1);
184
															boundary[strlen(attr + in + 1 + 1) - 1 + 2] = 0;
186
															boundary[strlen(attr + in + 1 + 1) - 1 + 2] = 0;
185
															ignore = true;
187
															ignore = true;
186
														}
188
														}
187
 
189
 
Line 189... Line 191...
189
													}
191
													}
190
												}
192
												}
191
 
193
 
192
												free(attr);
194
												free(attr);
193
												k++;
195
												k++;
194
												for(; value[k] != 0 && (value[k] == ' ' || value[k] == '\t'); k++);
196
												for(; value[k] != 0 && (value[k] == ' ' || value[k] == '\t'); k++)
-
 
197
													;
195
												incr2 = k;
198
												incr2 = k;
196
											}
199
											}
197
										}
200
										}
198
									}
201
									}
199
								}
202
								}
Line 203... Line 206...
203
						free(last);
206
						free(last);
204
						free(line);
207
						free(line);
205
					}
208
					}
206
					incr = i + 1;
209
					incr = i + 1;
207
					newline = true;
210
					newline = true;
208
				}else{
211
				} else {
209
					newline = false;
212
					newline = false;
210
				}
213
				}
211
			}else{
214
			} else {
212
				newline = false;
215
				newline = false;
213
			}
216
			}
214
		}
217
		}
215
		free(l);
218
		free(l);
216
 
219
 
217
		free(buffer);
220
		free(buffer);
218
		if(boundary != NULL) free(boundary);
221
		if(boundary != NULL) free(boundary);
219
		return 0;
222
		return 0;
220
	}else{
223
	} else {
221
		return 1;
224
		return 1;
222
	}
225
	}
223
}
226
}
224
 
227
 
225
int ok_news_parse(int sock){
228
int ok_news_parse(int sock) {
226
	char c;
229
	char c;
227
	int sta = 0;
230
	int sta = 0;
228
	bool st = false;
231
	bool st = false;
229
	while(1){
232
	while(1) {
230
		if(recv(sock, &c, 1, 0) <= 0){
233
		if(recv(sock, &c, 1, 0) <= 0) {
231
			return -1;
234
			return -1;
232
		}
235
		}
233
		if(c == '\n') break;
236
		if(c == '\n') break;
234
		if(!st){
237
		if(!st) {
235
			if('0' <= c && c <= '9'){
238
			if('0' <= c && c <= '9') {
236
				sta *= 10;
239
				sta *= 10;
237
				sta += c - '0';
240
				sta += c - '0';
238
			}else if(c == ' '){
241
			} else if(c == ' ') {
239
				st = true;
242
				st = true;
240
			}
243
			}
241
		}
244
		}
242
	}
245
	}
243
	return sta == 0 ? -1 : sta;
246
	return sta == 0 ? -1 : sta;
244
}
247
}
245
 
248
 
246
int ok_news_write(const char* nick, const char* message){
249
int ok_news_write(const char* nick, const char* message) {
247
	int nt_sock;
250
	int nt_sock;
248
	struct sockaddr_in nt_addr;
251
	struct sockaddr_in nt_addr;
249
	if((nt_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
252
	if((nt_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
250
		fprintf(stderr, "Socket creation failure\n");
253
		fprintf(stderr, "Socket creation failure\n");
251
		return 1;
254
		return 1;
252
	}
255
	}
253
 
256
 
254
	bzero((char*)&nt_addr, sizeof(nt_addr));
257
	bzero((char*)&nt_addr, sizeof(nt_addr));
Line 262... Line 265...
262
		fprintf(stderr, "setsockopt failure");
265
		fprintf(stderr, "setsockopt failure");
263
		ok_close(nt_sock);
266
		ok_close(nt_sock);
264
		return 1;
267
		return 1;
265
	}
268
	}
266
 
269
 
267
	if(connect(nt_sock, (struct sockaddr*)&nt_addr, sizeof(nt_addr)) < 0){
270
	if(connect(nt_sock, (struct sockaddr*)&nt_addr, sizeof(nt_addr)) < 0) {
268
		fprintf(stderr, "Connection failure\n");
271
		fprintf(stderr, "Connection failure\n");
269
		ok_close(nt_sock);
272
		ok_close(nt_sock);
270
		return 1;
273
		return 1;
271
	}
274
	}
272
 
275
 
273
	int sta;
276
	int sta;
274
 
277
 
275
	sta = ok_news_parse(nt_sock);
278
	sta = ok_news_parse(nt_sock);
276
	if(sta == 200 || sta == 201){
279
	if(sta == 200 || sta == 201) {
277
		char construct[1024];
280
		char construct[1024];
278
		if(nntpuser != NULL){
281
		if(nntpuser != NULL) {
279
			sprintf(construct, "AUTHINFO USER %s\r\n", nntpuser);
282
			sprintf(construct, "AUTHINFO USER %s\r\n", nntpuser);
280
			send(nt_sock, construct, strlen(construct), 0);
283
			send(nt_sock, construct, strlen(construct), 0);
281
			sta = ok_news_parse(nt_sock);
284
			sta = ok_news_parse(nt_sock);
282
			if(sta != 381){
285
			if(sta != 381) {
283
				goto cleanup;
286
				goto cleanup;
284
			}
287
			}
285
		}
288
		}
286
		if(nntppass != NULL){
289
		if(nntppass != NULL) {
287
			sprintf(construct, "AUTHINFO PASS %s\r\n", nntppass);
290
			sprintf(construct, "AUTHINFO PASS %s\r\n", nntppass);
288
			send(nt_sock, construct, strlen(construct), 0);
291
			send(nt_sock, construct, strlen(construct), 0);
289
			sta = ok_news_parse(nt_sock);
292
			sta = ok_news_parse(nt_sock);
290
			if(sta != 281){
293
			if(sta != 281) {
291
				goto cleanup;
294
				goto cleanup;
292
			}
295
			}
293
		}
296
		}
294
		send(nt_sock, "MODE READER\r\n", 4 + 1 + 6 + 2, 0);	
297
		send(nt_sock, "MODE READER\r\n", 4 + 1 + 6 + 2, 0);
295
		sta = ok_news_parse(nt_sock);
298
		sta = ok_news_parse(nt_sock);
296
		if(sta == 200 || sta == 201){
299
		if(sta == 200 || sta == 201) {
297
			send(nt_sock, "POST\r\n", 4 + 2, 0);
300
			send(nt_sock, "POST\r\n", 4 + 2, 0);
298
			sta = ok_news_parse(nt_sock);
301
			sta = ok_news_parse(nt_sock);
299
			if(sta == 340){
302
			if(sta == 340) {
300
				sprintf(construct, "From: %s\r\n", nntpfrom);
303
				sprintf(construct, "From: %s\r\n", nntpfrom);
301
				send(nt_sock, construct, strlen(construct), 0);
304
				send(nt_sock, construct, strlen(construct), 0);
302
				sprintf(construct, "Newsgroups: %s\r\n", nntpgroup);
305
				sprintf(construct, "Newsgroups: %s\r\n", nntpgroup);
303
				send(nt_sock, construct, strlen(construct), 0);
306
				send(nt_sock, construct, strlen(construct), 0);
304
				sprintf(construct, "Subject: [IRC] Message from %s\r\n", nick);
307
				sprintf(construct, "Subject: [IRC] Message from %s\r\n", nick);
Line 307... Line 310...
307
				send(nt_sock, construct, strlen(construct), 0);
310
				send(nt_sock, construct, strlen(construct), 0);
308
				send(nt_sock, "\r\n", 2, 0);
311
				send(nt_sock, "\r\n", 2, 0);
309
				char c;
312
				char c;
310
				int i;
313
				int i;
311
				bool first = true;
314
				bool first = true;
312
				for(i = 0; message[i] != 0; i++){
315
				for(i = 0; message[i] != 0; i++) {
313
					if(message[i] == '\n'){
316
					if(message[i] == '\n') {
314
						send(nt_sock, "\r\n", 2, 0);
317
						send(nt_sock, "\r\n", 2, 0);
315
						first = true;
318
						first = true;
316
					}else{
319
					} else {
317
						if(first && message[i] == '.'){
320
						if(first && message[i] == '.') {
318
							send(nt_sock, message + i, 1, 0);
321
							send(nt_sock, message + i, 1, 0);
319
						}
322
						}
320
						send(nt_sock, message + i, 1, 0);
323
						send(nt_sock, message + i, 1, 0);
321
						first = false;
324
						first = false;
322
					}
325
					}
Line 326... Line 329...
326
				sta = ok_news_parse(nt_sock);
329
				sta = ok_news_parse(nt_sock);
327
				if(sta != 240) goto cleanup;
330
				if(sta != 240) goto cleanup;
328
				send(nt_sock, "QUIT\r\n", 6, 0);
331
				send(nt_sock, "QUIT\r\n", 6, 0);
329
				sta = ok_news_parse(nt_sock);
332
				sta = ok_news_parse(nt_sock);
330
				if(sta != 205) goto cleanup;
333
				if(sta != 205) goto cleanup;
331
			}else{
334
			} else {
332
				goto cleanup;
335
				goto cleanup;
333
			}
336
			}
334
		}else{
337
		} else {
335
			goto cleanup;
338
			goto cleanup;
336
		}
339
		}
337
	}else{
340
	} else {
338
		goto cleanup;
341
		goto cleanup;
339
	}
342
	}
340
 
343
 
341
	ok_close(nt_sock);
344
	ok_close(nt_sock);
342
	return 0;
345
	return 0;