scoring dialog box finished
[claws.git] / src / scoring.c
1 #include <ctype.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include "intl.h"
7 #include "utils.h"
8 #include "defs.h"
9 #include "procheader.h"
10 #include "matcher.h"
11 #include "scoring.h"
12 #include "prefs.h"
13
14 #define PREFSBUFSIZE            1024
15
16 GSList * prefs_scoring = NULL;
17
18 ScoringProp * scoringprop_parse(gchar ** str)
19 {
20         gchar * tmp;
21         gint key;
22         ScoringProp * scoring;
23         gint score;
24         MatcherList * matchers;
25
26         tmp = * str;
27
28         matchers = matcherlist_parse(&tmp);
29         if (tmp == NULL) {
30                 * str = NULL;
31                 return NULL;
32         }
33
34         key = matcher_parse_keyword(&tmp);
35
36         if (tmp == NULL) {
37                 matcherlist_free(matchers);
38                 * str = NULL;
39                 return NULL;
40         }
41
42         if (key != MATCHING_SCORE) {
43                 matcherlist_free(matchers);
44                 * str = NULL;
45                 return NULL;
46         }
47
48         score = matcher_parse_number(&tmp);
49
50         if (tmp == NULL) {
51                 matcherlist_free(matchers);
52                 * str = NULL;
53                 return NULL;
54         }
55
56         scoring = scoringprop_new(matchers, score);
57
58         * str = tmp;
59         return scoring;
60 }
61
62
63 ScoringProp * scoringprop_new(MatcherList * matchers, int score)
64 {
65         ScoringProp * scoring;
66
67         scoring = g_new0(ScoringProp, 1);
68         scoring->matchers = matchers;
69         scoring->score = score;
70
71         return scoring;
72 }
73
74 void scoringprop_free(ScoringProp * prop)
75 {
76         matcherlist_free(prop->matchers);
77         g_free(prop);
78 }
79
80 gint scoringprop_score_message(ScoringProp * scoring, MsgInfo * info)
81 {
82         if (matcherlist_match(scoring->matchers, info))
83                 return scoring->score;
84         else
85                 return 0;
86 }
87
88 gint score_message(GSList * scoring_list, MsgInfo * info)
89 {
90         gint score = 0;
91         gint add_score;
92         GSList * l;
93
94         for(l = scoring_list ; l != NULL ; l = g_slist_next(l)) {
95                 ScoringProp * scoring = (ScoringProp *) l->data;
96                 
97                 add_score = (scoringprop_score_message(scoring, info));
98                 if (add_score == MAX_SCORE || add_score == MIN_SCORE) {
99                         score = add_score;
100                         break;
101                 }
102                 score += add_score;
103         }
104         return score;
105 }
106
107 #ifdef 0
108 static void scoringprop_print(ScoringProp * prop)
109 {
110         GSList * l;
111
112         if (prop == NULL) {
113                 printf("no scoring\n");
114                 return;
115         }
116
117         printf("----- scoring ------\n");
118         for(l = prop->matchers ; l != NULL ; l = g_slist_next(l)) {
119                 matcherprop_print((MatcherProp *) l->data);
120         }
121         printf("cond: %s\n", prop->bool_and ? "and" : "or");
122         printf("score: %i\n", prop->score);
123 }
124 #endif
125
126 /*
127   syntax for scoring config
128
129   file ~/.sylpheed/scoringrc
130
131   header "x-mailing" match "toto" score -10
132   subject match "regexp" & to regexp "regexp" score 50
133   subject match "regexp" | to regexpcase "regexp" | age_sup 5 score 30
134
135   if score is = MIN_SCORE (-999), no more match is done in the list
136   if score is = MAX_SCORE (-999), no more match is done in the list
137  */
138
139 void prefs_scoring_read_config(void)
140 {
141         gchar *rcpath;
142         FILE *fp;
143         gchar buf[PREFSBUFSIZE];
144
145         debug_print(_("Reading headers configuration...\n"));
146
147         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, SCORING_RC, NULL);
148         if ((fp = fopen(rcpath, "r")) == NULL) {
149                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
150                 g_free(rcpath);
151                 prefs_scoring = NULL;
152                 return;
153         }
154         g_free(rcpath);
155
156         /* remove all scoring */
157         while (prefs_scoring != NULL) {
158                 ScoringProp * scoring = (ScoringProp *) prefs_scoring->data;
159                 scoringprop_free(scoring);
160                 prefs_scoring = g_slist_remove(prefs_scoring, scoring);
161         }
162
163         while (fgets(buf, sizeof(buf), fp) != NULL) {
164                 ScoringProp * scoring;
165                 gchar * tmp;
166
167                 g_strchomp(buf);
168
169                 if ((*buf != '#') && (*buf != '\0')) {
170                         tmp = buf;
171                         scoring = scoringprop_parse(&tmp);
172                         if (tmp != NULL) {
173                                 prefs_scoring = g_slist_append(prefs_scoring,
174                                                                scoring);
175                         }
176                         else {
177                                 /* debug */
178                                 g_warning(_("syntax error : %s\n"), buf);
179                         }
180                 }
181         }
182
183         fclose(fp);
184 }
185
186 gchar * scoringprop_to_string(ScoringProp * prop)
187 {
188         gchar * list_str;
189         gchar * score_str;
190         gchar * scoring_str;
191
192         list_str = matcherlist_to_string(prop->matchers);
193
194         if (list_str == NULL)
195                 return NULL;
196
197         score_str = itos(prop->score);
198         scoring_str = g_strconcat(list_str, " score ", score_str, NULL);
199         g_free(list_str);
200
201         return scoring_str;
202 }
203
204 void prefs_scoring_write_config(void)
205 {
206         gchar *rcpath;
207         PrefFile *pfile;
208         GSList *cur;
209         ScoringProp * prop;
210
211         debug_print(_("Writing scoring configuration...\n"));
212
213         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, SCORING_RC, NULL);
214
215         if ((pfile = prefs_write_open(rcpath)) == NULL) {
216                 g_warning(_("failed to write configuration to file\n"));
217                 g_free(rcpath);
218                 return;
219         }
220
221         for (cur = prefs_scoring; cur != NULL; cur = cur->next) {
222                 gchar *scoring_str;
223
224                 prop = (ScoringProp *) cur->data;
225                 scoring_str = scoringprop_to_string(prop);
226                 if (fputs(scoring_str, pfile->fp) == EOF ||
227                     fputc('\n', pfile->fp) == EOF) {
228                         FILE_OP_ERROR(rcpath, "fputs || fputc");
229                         prefs_write_close_revert(pfile);
230                         g_free(rcpath);
231                         g_free(scoring_str);
232                         return;
233                 }
234                 g_free(scoring_str);
235         }
236
237         g_free(rcpath);
238
239         if (prefs_write_close(pfile) < 0) {
240                 g_warning(_("failed to write configuration to file\n"));
241                 return;
242         }
243 }