1 %{
2 
3 #include "defs.h"
4 
5 #include <glib.h>
6 #include <ctype.h>
7 
8 #include "procmsg.h"
9 #include "procmime.h"
10 #include "utils.h"
11 
12 #include "quote_fmt.h"
13 #include "quote_fmt_lex.h"
14 
15 /* decl */
16 /*
17 flex quote_fmt.l
18 bison -p quote_fmt quote_fmt.y
19 */
20 
21 int yylex(void);
22 
23 static MsgInfo *msginfo = NULL;
24 static gboolean *visible = NULL;
25 static gint maxsize = 0;
26 static gint stacksize = 0;
27 
28 static gchar *buffer = NULL;
29 static gint bufmax = 0;
30 static gint bufsize = 0;
31 static const gchar *quote_str = NULL;
32 static const gchar *body = NULL;
33 static gint error = 0;
34 
add_visibility(gboolean val)35 static void add_visibility(gboolean val)
36 {
37 	stacksize++;
38 	if (maxsize < stacksize) {
39 		maxsize += 128;
40 		visible = g_realloc(visible, maxsize * sizeof(gboolean));
41 		if (visible == NULL)
42 			maxsize = 0;
43 	}
44 
45 	visible[stacksize - 1] = val;
46 }
47 
remove_visibility(void)48 static void remove_visibility(void)
49 {
50 	stacksize--;
51 }
52 
add_buffer(const gchar * s)53 static void add_buffer(const gchar *s)
54 {
55 	gint len;
56 
57 	len = strlen(s);
58 	if (bufsize + len + 1 > bufmax) {
59 		if (bufmax == 0)
60 			bufmax = 128;
61 		while (bufsize + len + 1 > bufmax)
62 			bufmax *= 2;
63 		buffer = g_realloc(buffer, bufmax);
64 	}
65 	strcpy(buffer + bufsize, s);
66 	bufsize += len;
67 }
68 
69 #if 0
70 static void flush_buffer(void)
71 {
72 	if (buffer != NULL)
73 		*buffer = '\0';
74 	bufsize = 0;
75 }
76 #endif
77 
quote_fmt_get_buffer(void)78 gchar *quote_fmt_get_buffer(void)
79 {
80 	if (error != 0)
81 		return NULL;
82 	else
83 		return buffer;
84 }
85 
86 #define INSERT(buf) \
87 	if (stacksize != 0 && visible[stacksize - 1]) \
88 		add_buffer(buf)
89 
90 #define INSERT_CHARACTER(chr) \
91 	if (stacksize != 0 && visible[stacksize - 1]) { \
92 		gchar tmp[2]; \
93 		tmp[0] = (chr); \
94 		tmp[1] = '\0'; \
95 		add_buffer(tmp); \
96 	}
97 
quote_fmt_init(MsgInfo * info,const gchar * my_quote_str,const gchar * my_body)98 void quote_fmt_init(MsgInfo *info, const gchar *my_quote_str,
99 		    const gchar *my_body)
100 {
101 	quote_str = my_quote_str;
102 	body = my_body;
103 	msginfo = info;
104 	stacksize = 0;
105 	add_visibility(TRUE);
106 	if (buffer != NULL)
107 		*buffer = 0;
108 	bufsize = 0;
109 	error = 0;
110 }
111 
quote_fmterror(char * str)112 void quote_fmterror(char *str)
113 {
114 	g_warning("Error: %s\n", str);
115 	error = 1;
116 }
117 
quote_fmtwrap(void)118 int quote_fmtwrap(void)
119 {
120 	return 1;
121 }
122 
isseparator(int ch)123 static int isseparator(int ch)
124 {
125 	return g_ascii_isspace(ch) || ch == '.' || ch == '-';
126 }
127 %}
128 
129 %union {
130 	char chr;
131 }
132 
133 %token SHOW_NEWSGROUPS
134 %token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME
135 %token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
136 %token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
137 %token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB
138 %token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
139 %token SHOW_EOL SHOW_QUESTION_MARK SHOW_OPARENT SHOW_CPARENT
140 %token QUERY_DATE QUERY_FROM
141 %token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
142 %token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
143 %token OPARENT CPARENT
144 %token CHARACTER
145 
146 %start quote_fmt
147 
148 %token <chr> CHARACTER
149 %type <chr> character
150 
151 %%
152 
153 quote_fmt:
154 	character_or_special_or_query_list;
155 
156 character_or_special_or_query_list:
157 	character_or_special_or_query character_or_special_or_query_list
158 	| character_or_special_or_query ;
159 
160 character_or_special_or_query:
161 	special
162 	| character
163 	{
164 		INSERT_CHARACTER($1);
165 	}
166 	| query ;
167 
168 
169 character:
170 	CHARACTER
171 	;
172 
173 special:
174 	SHOW_NEWSGROUPS
175 	{
176 		if (msginfo->newsgroups)
177 			INSERT(msginfo->newsgroups);
178 	}
179 	| SHOW_DATE
180 	{
181 		if (msginfo->date) {
182 			INSERT(msginfo->date);
183 		} else if (msginfo->size == 0) {
184 			gchar buf[64];
185 
186 			get_rfc822_date(buf, sizeof(buf));
187 			INSERT(buf);
188 		}
189 	}
190 	| SHOW_FROM
191 	{
192 		if (msginfo->from)
193 			INSERT(msginfo->from);
194 	}
195 	| SHOW_FULLNAME
196 	{
197 		if (msginfo->fromname)
198 			INSERT(msginfo->fromname);
199 	}
200 	| SHOW_FIRST_NAME
201 	{
202 		if (msginfo->fromname) {
203 			gchar *p;
204 			gchar *str;
205 
206 			str = alloca(strlen(msginfo->fromname) + 1);
207 			if (str != NULL) {
208 				strcpy(str, msginfo->fromname);
209 				p = str;
210 				while (*p && !g_ascii_isspace(*p)) p++;
211 				*p = '\0';
212 				INSERT(str);
213 			}
214 		}
215 	}
216 	| SHOW_SENDER_INITIAL
217 	{
218 #define MAX_SENDER_INITIAL 20
219 		if (msginfo->fromname) {
220 			gchar tmp[MAX_SENDER_INITIAL];
221 			gchar *p;
222 			gchar *cur;
223 			gint len = 0;
224 
225 			p = msginfo->fromname;
226 			cur = tmp;
227 			while (*p) {
228 				if (*p && g_ascii_isalnum(*p)) {
229 					*cur = g_ascii_toupper(*p);
230 						cur++;
231 					len++;
232 					if (len >= MAX_SENDER_INITIAL - 1)
233 						break;
234 				} else
235 					break;
236 				while (*p && !isseparator(*p)) p++;
237 				while (*p && isseparator(*p)) p++;
238 			}
239 			*cur = '\0';
240 			INSERT(tmp);
241 		}
242 	}
243 	| SHOW_SUBJECT
244 	{
245 		if (msginfo->subject)
246 			INSERT(msginfo->subject);
247 	}
248 	| SHOW_TO
249 	{
250 		if (msginfo->to)
251 			INSERT(msginfo->to);
252 	}
253 	| SHOW_MESSAGEID
254 	{
255 		if (msginfo->msgid)
256 			INSERT(msginfo->msgid);
257 	}
258 	| SHOW_PERCENT
259 	{
260 		INSERT("%");
261 	}
262 	| SHOW_CC
263 	{
264 		if (msginfo->cc)
265 			INSERT(msginfo->cc);
266 	}
267 	| SHOW_REFERENCES
268 	{
269 		/* if (msginfo->references)
270 			INSERT(msginfo->references); */
271 	}
272 	| SHOW_MESSAGE
273 	{
274 		gchar buf[BUFFSIZE];
275 		FILE *fp = NULL;
276 
277 		if (body)
278 			fp = str_open_as_stream(body);
279 		else if (msginfo->size > 0) {
280 			fp = procmime_get_first_text_content(msginfo, NULL);
281 			if (fp == NULL)
282 				g_warning("quote_fmt_parse.y: Can't get text part\n");
283 		}
284 
285 		if (fp) {
286 			while (fgets(buf, sizeof(buf), fp) != NULL) {
287 				strcrchomp(buf);
288 				INSERT(buf);
289 			}
290 			fclose(fp);
291 		}
292 	}
293 	| SHOW_QUOTED_MESSAGE
294 	{
295 		gchar buf[BUFFSIZE];
296 		FILE *fp = NULL;
297 
298 		if (body)
299 			fp = str_open_as_stream(body);
300 		else if (msginfo->size > 0) {
301 			fp = procmime_get_first_text_content(msginfo, NULL);
302 			if (fp == NULL)
303 				g_warning("quote_fmt_parse.y: Can't get text part\n");
304 		}
305 
306 		if (fp) {
307 			while (fgets(buf, sizeof(buf), fp) != NULL) {
308 				strcrchomp(buf);
309 				if (quote_str)
310 					INSERT(quote_str);
311 				INSERT(buf);
312 			}
313 			fclose(fp);
314 		}
315 	}
316 	| SHOW_MESSAGE_NO_SIGNATURE
317 	{
318 		gchar buf[BUFFSIZE];
319 		FILE *fp = NULL;
320 
321 		if (body)
322 			fp = str_open_as_stream(body);
323 		else if (msginfo->size > 0) {
324 			fp = procmime_get_first_text_content(msginfo, NULL);
325 			if (fp == NULL)
326 				g_warning("quote_fmt_parse.y: Can't get text part\n");
327 		}
328 
329 		if (fp) {
330 			while (fgets(buf, sizeof(buf), fp) != NULL) {
331 				strcrchomp(buf);
332 				if (strncmp(buf, "-- \n", 4) == 0)
333 					break;
334 				INSERT(buf);
335 			}
336 			fclose(fp);
337 		}
338 	}
339 	| SHOW_QUOTED_MESSAGE_NO_SIGNATURE
340 	{
341 		gchar buf[BUFFSIZE];
342 		FILE *fp = NULL;
343 
344 		if (body)
345 			fp = str_open_as_stream(body);
346 		else if (msginfo->size > 0) {
347 			fp = procmime_get_first_text_content(msginfo, NULL);
348 			if (fp == NULL)
349 				g_warning("Can't get text part\n");
350 		}
351 
352 		if (fp) {
353 			while (fgets(buf, sizeof(buf), fp) != NULL) {
354 				strcrchomp(buf);
355 				if (strncmp(buf, "-- \n", 4) == 0)
356 					break;
357 				if (quote_str)
358 					INSERT(quote_str);
359 				INSERT(buf);
360 			}
361 			fclose(fp);
362 		}
363 	}
364 	| SHOW_BACKSLASH
365 	{
366 		INSERT("\\");
367 	}
368 	| SHOW_TAB
369 	{
370 		INSERT("\t");
371 	}
372 	| SHOW_EOL
373 	{
374 		INSERT("\n");
375 	}
376 	| SHOW_QUESTION_MARK
377 	{
378 		INSERT("?");
379 	}
380 	| SHOW_OPARENT
381 	{
382 		INSERT("{");
383 	}
384 	| SHOW_CPARENT
385 	{
386 		INSERT("}");
387 	};
388 
389 query:
390 	QUERY_DATE
391 	{
392 		add_visibility(msginfo->date != NULL);
393 	}
394 	OPARENT quote_fmt CPARENT
395 	{
396 		remove_visibility();
397 	}
398 	| QUERY_FROM
399 	{
400 		add_visibility(msginfo->from != NULL);
401 	}
402 	OPARENT quote_fmt CPARENT
403 	{
404 		remove_visibility();
405 	}
406 	| QUERY_FULLNAME
407 	{
408 		add_visibility(msginfo->fromname != NULL);
409 	}
410 	OPARENT quote_fmt CPARENT
411 	{
412 		remove_visibility();
413 	}
414 	| QUERY_SUBJECT
415 	{
416 		add_visibility(msginfo->subject != NULL);
417 	}
418 	OPARENT quote_fmt CPARENT
419 	{
420 		remove_visibility();
421 	}
422 	| QUERY_TO
423 	{
424 		add_visibility(msginfo->to != NULL);
425 	}
426 	OPARENT quote_fmt CPARENT
427 	{
428 		remove_visibility();
429 	}
430 	| QUERY_NEWSGROUPS
431 	{
432 		add_visibility(msginfo->newsgroups != NULL);
433 	}
434 	OPARENT quote_fmt CPARENT
435 	{
436 		remove_visibility();
437 	}
438 	| QUERY_MESSAGEID
439 	{
440 		add_visibility(msginfo->msgid != NULL);
441 	}
442 	OPARENT quote_fmt CPARENT
443 	{
444 		remove_visibility();
445 	}
446 	| QUERY_CC
447 	{
448 		add_visibility(msginfo->cc != NULL);
449 	}
450 	OPARENT quote_fmt CPARENT
451 	{
452 		remove_visibility();
453 	}
454 	| QUERY_REFERENCES
455 	{
456 		/* add_visibility(msginfo->references != NULL); */
457 	}
458 	OPARENT quote_fmt CPARENT
459 	{
460 		remove_visibility();
461 	};
462