~l3on/ubuntu/precise/epiphany-extensions/new-release

« back to all changes in this revision

Viewing changes to extensions/adblock/adblock-pattern.c

  • Committer: Leo Iannacone
  • Date: 2012-02-26 20:54:06 UTC
  • mfrom: (1.1.45 upstream)
  • Revision ID: l3on@ubuntu.com-20120226205406-4r0k199l2fjwsev4
New release version 3.3.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright © 2004 Adam Hooper
3
 
 *  Copyright © 2005, 2006 Jean-François Rameau
4
 
 *  Copyright © 2009 Xan Lopez <xan@gnome.org>
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2, or (at your option)
9
 
 *  any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 
 *
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include "adblock-pattern.h"
25
 
 
26
 
#include <string.h>
27
 
#include <gio/gio.h>
28
 
 
29
 
#include "ephy-file-helpers.h"
30
 
#include "ephy-debug.h"
31
 
 
32
 
#define DEFAULT_BLACKLIST_FILENAME      "adblock-patterns"
33
 
#define BLACKLIST_FILENAME              "blacklist"
34
 
#define WHITELIST_FILENAME              "whitelist"
35
 
 
36
 
typedef enum
37
 
{
38
 
        OP_LOAD,
39
 
        OP_SAVE
40
 
} OpType;
41
 
 
42
 
void adblock_pattern_save (GSList *patterns, AdblockPatternType type);
43
 
 
44
 
static void
45
 
adblock_pattern_load_from_file (GHashTable *patterns,
46
 
                                const char *filename)
47
 
{
48
 
        char *contents;
49
 
        char **lines;
50
 
        char **t;
51
 
        char *line;
52
 
        GRegex *regex;
53
 
        GError *error = NULL;
54
 
 
55
 
        if (!g_file_get_contents (filename, &contents, NULL, NULL))
56
 
        {
57
 
                g_warning ("Could not read from file '%s'", filename);
58
 
                return;
59
 
        }
60
 
 
61
 
        t = lines = g_strsplit (contents, "\n", 0);
62
 
 
63
 
        while (TRUE)
64
 
        {
65
 
                line = *t++;
66
 
                if (line == NULL) break;
67
 
 
68
 
                if (*line == '#') continue; /* comment */
69
 
 
70
 
                g_strstrip (line);
71
 
 
72
 
                if (*line == '\0') continue; /* empty line */
73
 
 
74
 
                regex = g_regex_new (line, G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0, &error);
75
 
 
76
 
                if (regex == NULL)
77
 
                {
78
 
                        g_warning ("Could not compile expression \"%s\"\n"
79
 
                                   "Error: %s",
80
 
                                   line, error->message);
81
 
                        g_error_free (error);
82
 
                        error = NULL;
83
 
                        continue;
84
 
                }
85
 
 
86
 
                g_hash_table_insert (patterns, g_strdup (line), regex);
87
 
        }
88
 
 
89
 
        g_strfreev (lines);
90
 
        g_free (contents);
91
 
}
92
 
 
93
 
static char *
94
 
adblock_pattern_filename (AdblockPatternType type, OpType op)
95
 
{
96
 
        char *filename = NULL;
97
 
 
98
 
        switch (type)
99
 
        {
100
 
                case PATTERN_BLACKLIST:
101
 
                        filename = g_build_filename (ephy_dot_dir (), "extensions", "data",
102
 
                                                     "adblock", BLACKLIST_FILENAME,
103
 
                                                     NULL);
104
 
                        break;
105
 
                case PATTERN_WHITELIST:
106
 
                        filename = g_build_filename (ephy_dot_dir (), "extensions", "data",
107
 
                                                     "adblock", WHITELIST_FILENAME,
108
 
                                                     NULL);
109
 
                        break;
110
 
                case PATTERN_DEFAULT_BLACKLIST:
111
 
                        /* We first try the user's one */
112
 
                        filename = g_build_filename (ephy_dot_dir (), "extensions", "data",
113
 
                                                     "adblock", DEFAULT_BLACKLIST_FILENAME,
114
 
                                                     NULL);
115
 
                        if (op == OP_LOAD && !g_file_test (filename, G_FILE_TEST_IS_REGULAR))
116
 
                        {
117
 
                                g_free (filename);
118
 
                                /* Then, try the global one */
119
 
                                filename = g_build_filename (SHARE_DIR,
120
 
                                                             DEFAULT_BLACKLIST_FILENAME,
121
 
                                                             NULL);
122
 
                        }
123
 
                        break;
124
 
        }
125
 
 
126
 
        return filename;
127
 
}
128
 
 
129
 
static gboolean
130
 
adblock_pattern_foreach_save (const char *pattern,
131
 
                              GIOChannel *channel)
132
 
{
133
 
        GIOStatus status;
134
 
        gsize bytes_written;
135
 
 
136
 
        status = g_io_channel_write_chars (channel, pattern, -1, &bytes_written, NULL);
137
 
        status = g_io_channel_write_chars (channel, "\n", -1, &bytes_written, NULL);
138
 
 
139
 
        return FALSE;
140
 
}
141
 
 
142
 
static char *
143
 
adblock_pattern_replace_dot (const char *line)
144
 
{
145
 
        char **sub;
146
 
        char *res;
147
 
 
148
 
        g_return_val_if_fail (line != NULL, NULL);
149
 
 
150
 
        sub = g_strsplit (line, ".", 0);
151
 
        res = g_strjoinv ("\\.", sub);
152
 
 
153
 
        g_strfreev (sub);
154
 
 
155
 
        return res;
156
 
}
157
 
 
158
 
static void
159
 
adblock_pattern_rewrite_patterns (const char *contents)
160
 
{
161
 
        char **lines, **t;
162
 
        char *line;
163
 
        GRegex *regex1, *regex2;
164
 
        GError *error = NULL;
165
 
        gboolean match;
166
 
        GSList *patterns = NULL;
167
 
 
168
 
        /* We don't care about some specific rules */
169
 
        regex1 = g_regex_new ("^\\[Adblock\\]", 0, 0, &error);
170
 
        if (regex1 == NULL)
171
 
        {
172
 
                g_warning ("Could not compile expression ^\\[Adblock]\n" "Error: %s",
173
 
                           error->message);
174
 
                g_error_free (error);
175
 
                return;
176
 
        }
177
 
        regex2 = g_regex_new ("^\\!Filterset", 0, 0, &error);
178
 
        if (regex2 == NULL)
179
 
        {
180
 
                g_warning ("Could not compile expression ^\\!Filterset\n" "Error: %s",
181
 
                           error->message);
182
 
                g_error_free (error);
183
 
                return;
184
 
        }
185
 
 
186
 
        t = lines = g_strsplit (contents, "\n", 0);
187
 
 
188
 
        while (TRUE)
189
 
        {
190
 
                line = *t++;
191
 
                if (line == NULL) break;
192
 
 
193
 
                if (*line == '#') continue; /* comment */
194
 
 
195
 
                g_strstrip (line);
196
 
 
197
 
                if (*line == '\0') continue; /* empty line */
198
 
 
199
 
                match = g_regex_match (regex1, line, 0, NULL);
200
 
 
201
 
                if (match) continue;
202
 
 
203
 
                match = g_regex_match (regex2, line, 0, NULL);
204
 
 
205
 
                if (match) continue;
206
 
 
207
 
                if (*line == '/')
208
 
                {
209
 
                        *(line + strlen (line) -1) = '\0';
210
 
                        line += 1;
211
 
                        patterns = g_slist_prepend (patterns, g_strdup (line));
212
 
                        continue;
213
 
                }
214
 
                line = adblock_pattern_replace_dot (line);
215
 
 
216
 
                patterns = g_slist_prepend (patterns, g_strdup (line));
217
 
        }
218
 
 
219
 
        g_strfreev (lines);
220
 
        g_regex_unref (regex1);
221
 
        g_regex_unref (regex2);
222
 
 
223
 
        adblock_pattern_save (patterns, PATTERN_DEFAULT_BLACKLIST);
224
 
 
225
 
        g_slist_foreach (patterns, (GFunc)g_free, NULL);
226
 
}
227
 
 
228
 
static char *
229
 
adblock_pattern_get_filterg_patterns (const char *date)
230
 
{
231
 
        gsize size;
232
 
        char *contents = NULL, *url = NULL;
233
 
        GFile *file;
234
 
        GFileInfo *info;
235
 
        GFileInputStream *input_stream;
236
 
        gboolean res = TRUE;
237
 
 
238
 
        url = g_strdup_printf ("http://www.pierceive.com/filtersetg/%s", date);
239
 
        file = g_file_new_for_uri (url);
240
 
        info = g_file_query_info (file,
241
 
                                  G_FILE_ATTRIBUTE_STANDARD_SIZE,
242
 
                                  0, 0, NULL);
243
 
        if (info == NULL)
244
 
        {
245
 
                g_warning ("Could not get rules file from filterg site");
246
 
                goto out;
247
 
        }
248
 
        else
249
 
        {
250
 
                size = (gsize) g_file_info_get_size (info);
251
 
                g_object_unref (info);
252
 
        }
253
 
 
254
 
        /* First, get the changelog so we can build the url pointing to the last rules */
255
 
        input_stream = g_file_read (file, NULL, NULL);
256
 
        if (input_stream != NULL)
257
 
        {
258
 
                gsize bytes_read;
259
 
 
260
 
                contents = g_malloc (size);
261
 
                res = g_input_stream_read_all (G_INPUT_STREAM (input_stream),
262
 
                                               contents,
263
 
                                               size,
264
 
                                               &bytes_read,
265
 
                                               NULL, NULL);
266
 
                if (!res)
267
 
                {       
268
 
                        g_warning ("Could not get rules file from filterg site");
269
 
                }
270
 
                g_object_unref (input_stream);
271
 
        }
272
 
        else
273
 
        {
274
 
                g_warning ("Could not get rules file from filterg site");
275
 
        }
276
 
 
277
 
out:
278
 
        g_free (url);
279
 
        g_object_unref (file);
280
 
 
281
 
        return contents;
282
 
}
283
 
 
284
 
static char *
285
 
adblock_pattern_get_filterg_date (void)
286
 
{
287
 
        gsize size;
288
 
        char *contents = NULL;
289
 
        char **lines;
290
 
        char *date = NULL;
291
 
        GFile *file;
292
 
        GFileInfo *info;
293
 
        GFileInputStream *input_stream;
294
 
        gboolean res = TRUE;
295
 
 
296
 
        file = g_file_new_for_uri ("http://www.pierceive.com/filtersetg/latest.txt");
297
 
        info = g_file_query_info (file,
298
 
                                  G_FILE_ATTRIBUTE_STANDARD_SIZE,
299
 
                                  0, 0, NULL);
300
 
        if (info == NULL)
301
 
        {
302
 
                g_warning ("Could not get latest.txt file from filterg site");
303
 
                goto out;
304
 
        }
305
 
        else
306
 
        {
307
 
                size = (gsize) g_file_info_get_size (info);
308
 
                g_object_unref (info);
309
 
        }
310
 
 
311
 
        /* First, get the changelog so we can build the url pointing to the last rules */
312
 
        input_stream = g_file_read (file, NULL, NULL);
313
 
        if (input_stream != NULL)
314
 
        {
315
 
                gsize bytes_read;
316
 
 
317
 
                contents = g_malloc (size);
318
 
                res = g_input_stream_read_all (G_INPUT_STREAM (input_stream),
319
 
                                               contents,
320
 
                                               size,
321
 
                                               &bytes_read,
322
 
                                               NULL, NULL);
323
 
                if (!res)
324
 
                {       
325
 
                        g_warning ("Could not get latest.txt file from filterg site");
326
 
                        goto out;
327
 
                }
328
 
                g_object_unref (input_stream);
329
 
                lines = g_strsplit (contents, "\n", 0);
330
 
                date = g_strdup (lines [0]);
331
 
 
332
 
                g_free (contents);
333
 
                g_strfreev (lines);
334
 
        }
335
 
        else
336
 
        {
337
 
                g_warning ("Could not get latest.txt file from filterg site");
338
 
                goto out;
339
 
        }
340
 
 
341
 
out:
342
 
        g_object_unref (file);
343
 
 
344
 
        return date;
345
 
}
346
 
 
347
 
/* Public */
348
 
 
349
 
void
350
 
adblock_pattern_load (GHashTable *patterns,
351
 
                      AdblockPatternType type)
352
 
{
353
 
        char *filename = NULL;
354
 
 
355
 
        filename = adblock_pattern_filename (type, OP_LOAD);
356
 
 
357
 
        if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
358
 
        {
359
 
                LOG ("Loading patterns from %s", filename);
360
 
 
361
 
                adblock_pattern_load_from_file (patterns, filename);
362
 
        }
363
 
        g_free (filename);
364
 
}
365
 
 
366
 
 
367
 
void
368
 
adblock_pattern_save (GSList *patterns, AdblockPatternType type)
369
 
{
370
 
        GError *error = NULL;
371
 
        char *filename = NULL;
372
 
 
373
 
        filename = adblock_pattern_filename (type, OP_SAVE);
374
 
 
375
 
        GIOChannel *channel = g_io_channel_new_file (filename, "w", NULL);
376
 
 
377
 
        g_slist_foreach (patterns,
378
 
                         (GFunc)adblock_pattern_foreach_save,
379
 
                         channel);
380
 
 
381
 
        g_io_channel_shutdown (channel, TRUE, &error);
382
 
}
383
 
 
384
 
void
385
 
adblock_pattern_get_filtersetg_patterns (void)
386
 
{
387
 
        char *date, *patterns;
388
 
 
389
 
        date = adblock_pattern_get_filterg_date ();
390
 
        if (date == NULL)
391
 
        {
392
 
                g_warning ("Could not get the last update");
393
 
                return;
394
 
        }
395
 
 
396
 
        patterns = adblock_pattern_get_filterg_patterns (date);
397
 
        if (patterns == NULL)
398
 
        {
399
 
                g_warning ("Could not get content from last update");
400
 
                return;
401
 
        }
402
 
 
403
 
        adblock_pattern_rewrite_patterns (patterns);
404
 
 
405
 
        g_free (date);
406
 
        g_free (patterns);
407
 
}