7bb9f261491f3b13884c16a8d5aaf59ee35a72fa
[privoxy.git] / doc / webserver / user-manual / filter-file.html
1 <HTML
2 ><HEAD
3 ><TITLE
4 >The Filter File</TITLE
5 ><META
6 NAME="GENERATOR"
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.60"><LINK
8 REL="HOME"
9 TITLE="Privoxy User Manual"
10 HREF="index.html"><LINK
11 REL="PREVIOUS"
12 TITLE="Actions Files"
13 HREF="actions-file.html"><LINK
14 REL="NEXT"
15 TITLE="Templates"
16 HREF="templates.html"><LINK
17 REL="STYLESHEET"
18 TYPE="text/css"
19 HREF="../p_doc.css"></HEAD
20 ><BODY
21 CLASS="SECT1"
22 BGCOLOR="#EEEEEE"
23 TEXT="#000000"
24 LINK="#0000FF"
25 VLINK="#840084"
26 ALINK="#0000FF"
27 ><DIV
28 CLASS="NAVHEADER"
29 ><TABLE
30 WIDTH="100%"
31 BORDER="0"
32 CELLPADDING="0"
33 CELLSPACING="0"
34 ><TR
35 ><TH
36 COLSPAN="3"
37 ALIGN="center"
38 >Privoxy User Manual</TH
39 ></TR
40 ><TR
41 ><TD
42 WIDTH="10%"
43 ALIGN="left"
44 VALIGN="bottom"
45 ><A
46 HREF="actions-file.html"
47 >Prev</A
48 ></TD
49 ><TD
50 WIDTH="80%"
51 ALIGN="center"
52 VALIGN="bottom"
53 ></TD
54 ><TD
55 WIDTH="10%"
56 ALIGN="right"
57 VALIGN="bottom"
58 ><A
59 HREF="templates.html"
60 >Next</A
61 ></TD
62 ></TR
63 ></TABLE
64 ><HR
65 ALIGN="LEFT"
66 WIDTH="100%"></DIV
67 ><DIV
68 CLASS="SECT1"
69 ><H1
70 CLASS="SECT1"
71 ><A
72 NAME="FILTER-FILE"
73 >9. The Filter File</A
74 ></H1
75 ><P
76 > All text substitutions that can be invoked through the
77  <TT
78 CLASS="LITERAL"
79 ><A
80 HREF="actions-file.html#FILTER"
81 >filter</A
82 ></TT
83 > action
84  must first be defined in the filter file, which is typically
85  called <TT
86 CLASS="FILENAME"
87 >default.filter</TT
88 > and which can be
89  selected through the <TT
90 CLASS="LITERAL"
91 > <A
92 HREF="config.html#FILTERFILE"
93 >filterfile</A
94 ></TT
95 > config
96  option.</P
97 ><P
98 > Typical reasons for doing such substitutions are to eliminate
99  common annoyances in HTML and JavaScript, such as pop-up windows,
100  exit consoles, crippled windows without navigation tools, the
101  infamous &#60;BLINK&#62; tag etc, to suppress images with certain
102  width and height attributes (standard banner sizes or web-bugs),
103  or just to have fun. The possibilities are endless.</P
104 ><P
105 > Filtering works on any text-based document type, including plain
106  text, HTML, JavaScript, CSS etc. (all <TT
107 CLASS="LITERAL"
108 >text/*</TT
109 >
110  MIME types). Substitutions are made at the source level, so if
111  you want to <SPAN
112 CLASS="QUOTE"
113 >"roll your own"</SPAN
114 > filters, you should be
115  familiar with HTML syntax.</P
116 ><P
117 > Just like the <A
118 HREF="actions-file.html"
119 >actions files</A
120 >, the
121  filter file is organized in sections, which are called <I
122 CLASS="EMPHASIS"
123 >filters</I
124 >
125  here. Each filter consists of a heading line, that starts with the
126  <I
127 CLASS="EMPHASIS"
128 >keyword</I
129 > <TT
130 CLASS="LITERAL"
131 >FILTER:</TT
132 >, followed by
133  the filter's <I
134 CLASS="EMPHASIS"
135 >name</I
136 >, and a short (one line) 
137  <I
138 CLASS="EMPHASIS"
139 >description</I
140 > of what it does. Below that line
141  come the <I
142 CLASS="EMPHASIS"
143 >jobs</I
144 >, i.e. lines that define the actual
145  text substitutions. By convention, the name of a filter
146  should describe what the filter <I
147 CLASS="EMPHASIS"
148 >eliminates</I
149 >. The
150  comment is used in the <A
151 HREF="http://config.privoxy.org/"
152 TARGET="_top"
153 >web-based
154  user interface</A
155 >.</P
156 ><P
157 > Once a filter called <TT
158 CLASS="REPLACEABLE"
159 ><I
160 >name</I
161 ></TT
162 > has been defined
163  in the filter file, it can be invoked by using an action of the form
164  +<TT
165 CLASS="LITERAL"
166 ><A
167 HREF="actions-file.html#FILTER"
168 >filter</A
169 >{<TT
170 CLASS="REPLACEABLE"
171 ><I
172 >name</I
173 ></TT
174 >}</TT
175 >
176  in any <A
177 HREF="actions-file.html"
178 >actions file</A
179 >.</P
180 ><P
181 > A filter header line for a filter called <SPAN
182 CLASS="QUOTE"
183 >"foo"</SPAN
184 > could look
185  like this:</P
186 ><P
187 > <TABLE
188 BORDER="0"
189 BGCOLOR="#E0E0E0"
190 WIDTH="100%"
191 ><TR
192 ><TD
193 ><PRE
194 CLASS="SCREEN"
195 >FILTER: foo Replace all "foo" with "bar"</PRE
196 ></TD
197 ></TR
198 ></TABLE
199 ></P
200 ><P
201 > Below that line, and up to the next header line, come the jobs that
202  define what text replacements the filter executes. They are specified
203  in a syntax that imitates <A
204 HREF="http://www.perl.org/"
205 TARGET="_top"
206 >Perl</A
207 >'s
208  <TT
209 CLASS="LITERAL"
210 >s///</TT
211 > operator. If you are familiar with Perl, you
212  will find this to be quite intuitive, and may want to look at the
213  <A
214 HREF="http://www.oesterhelt.org/pcrs/pcrs.1.html"
215 TARGET="_top"
216 >PCRS man page</A
217 >
218  for the subtle differences to Perl behaviour. Most notably, the non-standard
219  option letter <TT
220 CLASS="LITERAL"
221 >U</TT
222 > is supported, which turns the default
223  to ungreedy matching.</P
224 ><P
225 > If you are new to regular expressions, you might want to take a look at
226  the <A
227 HREF="appendix.html#REGEX"
228 >Appendix on regular expressions</A
229 >, and
230  see the <A
231 HREF="http://perldoc.com/perl5.6.1/pod/perl.html"
232 TARGET="_top"
233 >Perl
234  manual</A
235 > for
236  <A
237 HREF="http://perldoc.com/perl5.6.1/pod/perlop.html#s-PATTERN-REPLACEMENT-egimosx"
238 TARGET="_top"
239 >the 
240  <TT
241 CLASS="LITERAL"
242 >s///</TT
243 > operator's syntax</A
244 > and <A
245 HREF="http://perldoc.com/perl5.6.1/pod/perlre.html"
246 TARGET="_top"
247 >Perl-style regular
248  expressions</A
249 > in general.
250  The below examples might also help to get you started.</P
251 ><DIV
252 CLASS="SECT2"
253 ><H2
254 CLASS="SECT2"
255 ><A
256 NAME="AEN2778"
257 >9.1. Filter File Tutorial</A
258 ></H2
259 ><P
260 > Now, let's complete our <SPAN
261 CLASS="QUOTE"
262 >"foo"</SPAN
263 > filter. We have already defined
264  the heading, but the jobs are still missing. Since all it does is to replace
265  <SPAN
266 CLASS="QUOTE"
267 >"foo"</SPAN
268 > with <SPAN
269 CLASS="QUOTE"
270 >"bar"</SPAN
271 >, there is only one (trivial) job
272  needed:</P
273 ><P
274 > <TABLE
275 BORDER="0"
276 BGCOLOR="#E0E0E0"
277 WIDTH="100%"
278 ><TR
279 ><TD
280 ><PRE
281 CLASS="SCREEN"
282 >s/foo/bar/</PRE
283 ></TD
284 ></TR
285 ></TABLE
286 ></P
287 ><P
288 > But wait! Didn't the comment say that <I
289 CLASS="EMPHASIS"
290 >all</I
291 > occurrences
292  of <SPAN
293 CLASS="QUOTE"
294 >"foo"</SPAN
295 > should be replaced? Our current job will only take
296  care of the first <SPAN
297 CLASS="QUOTE"
298 >"foo"</SPAN
299 > on each page. For global substitution,
300  we'll need to add the <TT
301 CLASS="LITERAL"
302 >g</TT
303 > option:</P
304 ><P
305 > <TABLE
306 BORDER="0"
307 BGCOLOR="#E0E0E0"
308 WIDTH="100%"
309 ><TR
310 ><TD
311 ><PRE
312 CLASS="SCREEN"
313 >s/foo/bar/g</PRE
314 ></TD
315 ></TR
316 ></TABLE
317 ></P
318 ><P
319 > Our complete filter now looks like this:</P
320 ><P
321 > <TABLE
322 BORDER="0"
323 BGCOLOR="#E0E0E0"
324 WIDTH="100%"
325 ><TR
326 ><TD
327 ><PRE
328 CLASS="SCREEN"
329 >FILTER: foo Replace all "foo" with "bar"
330 s/foo/bar/g</PRE
331 ></TD
332 ></TR
333 ></TABLE
334 ></P
335 ><P
336 > Let's look at some real filters for more interesting examples. Here you see
337  a filter that protects against some common annoyances that arise from JavaScript
338  abuse. Let's look at its jobs one after the other:</P
339 ><P
340 > <TABLE
341 BORDER="0"
342 BGCOLOR="#E0E0E0"
343 WIDTH="100%"
344 ><TR
345 ><TD
346 ><PRE
347 CLASS="SCREEN"
348 >FILTER: js-annoyances Get rid of particularly annoying JavaScript abuse
349
350 # Get rid of JavaScript referrer tracking. Test page: http://www.randomoddness.com/untitled.htm
351 #
352 s|(&#60;script.*)document\.referrer(.*&#60;/script&#62;)|$1"Not Your Business!"$2|Usg</PRE
353 ></TD
354 ></TR
355 ></TABLE
356 ></P
357 ><P
358 > Following the header line and a comment, you see the job. Note that it uses
359  <TT
360 CLASS="LITERAL"
361 >|</TT
362 > as the delimiter instead of <TT
363 CLASS="LITERAL"
364 >/</TT
365 >, because
366  the pattern contains a forward slash, which would otherwise have to be escaped
367  by a backslash (<TT
368 CLASS="LITERAL"
369 >\</TT
370 >).</P
371 ><P
372 > Now, let's examine the pattern: it starts with the text <TT
373 CLASS="LITERAL"
374 >&#60;script.*</TT
375 >
376  enclosed in parentheses. Since the dot matches any character, and <TT
377 CLASS="LITERAL"
378 >*</TT
379 >
380  means: <SPAN
381 CLASS="QUOTE"
382 >"Match an arbitrary number of the element left of myself"</SPAN
383 >, this
384  matches <SPAN
385 CLASS="QUOTE"
386 >"&#60;script"</SPAN
387 >, followed by <I
388 CLASS="EMPHASIS"
389 >any</I
390 > text, i.e.
391  it matches the whole page, from the start of the first &#60;script&#62; tag.</P
392 ><P
393 > That's more than we want, but the pattern continues: <TT
394 CLASS="LITERAL"
395 >document\.referrer</TT
396 >
397  matches only the exact string <SPAN
398 CLASS="QUOTE"
399 >"document.referrer"</SPAN
400 >. The dot needed to
401  be <I
402 CLASS="EMPHASIS"
403 >escaped</I
404 >, i.e. preceded by a backslash, to take away its
405  special meaning as a joker, and make it just a regular dot. So far, the meaning is:
406  Match from the start of the first &#60;script&#62; tag in a the page, up to, and including,
407  the text <SPAN
408 CLASS="QUOTE"
409 >"document.referrer"</SPAN
410 >, if <I
411 CLASS="EMPHASIS"
412 >both</I
413 > are present
414  in the page (and appear in that order).</P
415 ><P
416 > But there's still more pattern to go. The next element, again enclosed in parentheses,
417  is <TT
418 CLASS="LITERAL"
419 >.*&#60;/script&#62;</TT
420 >. You already know what <TT
421 CLASS="LITERAL"
422 >.*</TT
423 >
424  means, so the whole pattern translates to: Match from the start of the first  &#60;script&#62;
425  tag in a page to the end of the last &#60;script&#62; tag, provided that the text
426  <SPAN
427 CLASS="QUOTE"
428 >"document.referrer"</SPAN
429 > appears somewhere in between.</P
430 ><P
431 > This is still not the whole story, since we have ignored the options and the parentheses:
432  The portions of the page matched by sub-patterns that are enclosed in parentheses, will be
433  remembered and be available through the variables <TT
434 CLASS="LITERAL"
435 >$1, $2, ...</TT
436 > in
437  the substitute. The <TT
438 CLASS="LITERAL"
439 >U</TT
440 > option switches to ungreedy matching, which means
441  that the first <TT
442 CLASS="LITERAL"
443 >.*</TT
444 > in the pattern will only <SPAN
445 CLASS="QUOTE"
446 >"eat up"</SPAN
447 > all
448  text in between <SPAN
449 CLASS="QUOTE"
450 >"&#60;script"</SPAN
451 > and the <I
452 CLASS="EMPHASIS"
453 >first</I
454 > occurrence
455  of <SPAN
456 CLASS="QUOTE"
457 >"document.referrer"</SPAN
458 >, and that the second <TT
459 CLASS="LITERAL"
460 >.*</TT
461 > will
462  only span the text up to the <I
463 CLASS="EMPHASIS"
464 >first</I
465 > <SPAN
466 CLASS="QUOTE"
467 >"&#60;/script&#62;"</SPAN
468 >
469  tag. Furthermore, the <TT
470 CLASS="LITERAL"
471 >s</TT
472 > option says that the match may span
473  multiple lines in the page, and the <TT
474 CLASS="LITERAL"
475 >g</TT
476 > option again means that the
477  substitution is global.</P
478 ><P
479 > So, to summarize, the pattern means: Match all scripts that contain the text
480  <SPAN
481 CLASS="QUOTE"
482 >"document.referrer"</SPAN
483 >. Remember the parts of the script from
484  (and including) the start tag up to (and excluding) the string
485  <SPAN
486 CLASS="QUOTE"
487 >"document.referrer"</SPAN
488 > as <TT
489 CLASS="LITERAL"
490 >$1</TT
491 >, and the part following
492  that string, up to and including the closing tag, as <TT
493 CLASS="LITERAL"
494 >$2</TT
495 >.</P
496 ><P
497 > Now the pattern is deciphered, but wasn't this about substituting things? So
498  lets look at the substitute: <TT
499 CLASS="LITERAL"
500 >$1"Not Your Business!"$2</TT
501 > is
502  easy to read: The text remembered as <TT
503 CLASS="LITERAL"
504 >$1</TT
505 >, followed by 
506  <TT
507 CLASS="LITERAL"
508 >"Not Your Business!"</TT
509 > (<I
510 CLASS="EMPHASIS"
511 >including</I
512 >
513  the quotation marks!), followed by the text remembered as <TT
514 CLASS="LITERAL"
515 >$2</TT
516 >.
517  This produces an exact copy of the original string, with the middle part
518  (the <SPAN
519 CLASS="QUOTE"
520 >"document.referrer"</SPAN
521 >) replaced by <TT
522 CLASS="LITERAL"
523 >"Not Your
524  Business!"</TT
525 >.</P
526 ><P
527 > The whole job now reads: Replace <SPAN
528 CLASS="QUOTE"
529 >"document.referrer"</SPAN
530 > by
531  <TT
532 CLASS="LITERAL"
533 >"Not Your Business!"</TT
534 > wherever it appears inside a
535  &#60;script&#62; tag. Note that this job won't break JavaScript syntax,
536  since both the original and the replacement are syntactically valid
537  string objects. The script just won't have access to the referrer
538  information anymore.</P
539 ><P
540 > We'll show you two other jobs from the JavaScript taming department, but
541  this time only point out the constructs of special interest:</P
542 ><P
543 > <TABLE
544 BORDER="0"
545 BGCOLOR="#E0E0E0"
546 WIDTH="100%"
547 ><TR
548 ><TD
549 ><PRE
550 CLASS="SCREEN"
551 ># The status bar is for displaying link targets, not pointless blahblah
552 #
553 s/window\.status\s*=\s*['"].*?['"]/dUmMy=1/ig</PRE
554 ></TD
555 ></TR
556 ></TABLE
557 ></P
558 ><P
559 > <TT
560 CLASS="LITERAL"
561 >\s</TT
562 > stands for whitespace characters (space, tab, newline,
563  carriage return, form feed), so that <TT
564 CLASS="LITERAL"
565 >\s*</TT
566 > means: <SPAN
567 CLASS="QUOTE"
568 >"zero
569  or more whitespace"</SPAN
570 >. The <TT
571 CLASS="LITERAL"
572 >?</TT
573 > in <TT
574 CLASS="LITERAL"
575 >.*?</TT
576 >
577  makes this matching of arbitrary text ungreedy. (Note that the <TT
578 CLASS="LITERAL"
579 >U</TT
580 >
581  option is not set). The <TT
582 CLASS="LITERAL"
583 >['"]</TT
584 > construct means: <SPAN
585 CLASS="QUOTE"
586 >"a single
587  <I
588 CLASS="EMPHASIS"
589 >or</I
590 > a double quote"</SPAN
591 >.</P
592 ><P
593 > So what does this job do? It replaces assignments of single- or double-quoted
594  strings to the <SPAN
595 CLASS="QUOTE"
596 >"window.status"</SPAN
597 > object with a dummy assignment
598  (using a variable name that is hopefully odd enough not to conflict with
599  real variables in scripts). Thus, it catches many cases where e.g. pointless
600  descriptions are displayed in the status bar instead of the link target when
601  you move your mouse over links.</P
602 ><P
603 > <TABLE
604 BORDER="0"
605 BGCOLOR="#E0E0E0"
606 WIDTH="100%"
607 ><TR
608 ><TD
609 ><PRE
610 CLASS="SCREEN"
611 ># Kill OnUnload popups. Yummy. Test: http://www.zdnet.com/zdsubs/yahoo/tree/yfs.html
612 #
613 s/(&#60;body .*)onunload(.*&#62;)/$1never$2/iU</PRE
614 ></TD
615 ></TR
616 ></TABLE
617 ></P
618 ><P
619 > Including the
620  <A
621 HREF="http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-eventgroupings-htmlevents"
622 TARGET="_top"
623 >OnUnload
624  event binding</A
625 > in the HTML DOM was a <I
626 CLASS="EMPHASIS"
627 >CRIME</I
628 >.
629  When I close a browser window, I want it to close and die. Basta.
630  This job replaces the <SPAN
631 CLASS="QUOTE"
632 >"onunload"</SPAN
633 > attribute in
634  <SPAN
635 CLASS="QUOTE"
636 >"&#60;body&#62;"</SPAN
637 > tags with the dummy word <TT
638 CLASS="LITERAL"
639 >never</TT
640 >.
641  Note that the <TT
642 CLASS="LITERAL"
643 >i</TT
644 > option makes the pattern matching
645  case-insensitive.</P
646 ><P
647 > The last example is from the fun department:</P
648 ><P
649 > <TABLE
650 BORDER="0"
651 BGCOLOR="#E0E0E0"
652 WIDTH="100%"
653 ><TR
654 ><TD
655 ><PRE
656 CLASS="SCREEN"
657 >FILTER: fun Fun text replacements
658
659 # Spice the daily news:
660 #
661 s/microsoft(?!\.com)/MicroSuck/ig</PRE
662 ></TD
663 ></TR
664 ></TABLE
665 ></P
666 ><P
667 > Note the <TT
668 CLASS="LITERAL"
669 >(?!\.com)</TT
670 > part (a so-called negative lookahead)
671  in the job's pattern, which means: Don't match, if the string 
672  <SPAN
673 CLASS="QUOTE"
674 >".com"</SPAN
675 > appears directly following <SPAN
676 CLASS="QUOTE"
677 >"microsoft"</SPAN
678 >
679  in the page. This prevents links to microsoft.com from being messed, while
680  still replacing the word everywhere else.</P
681 ><P
682 > <TABLE
683 BORDER="0"
684 BGCOLOR="#E0E0E0"
685 WIDTH="100%"
686 ><TR
687 ><TD
688 ><PRE
689 CLASS="SCREEN"
690 ># Buzzword Bingo (example for extended regex syntax)
691 #
692 s* industry[ -]leading \
693 |  cutting[ -]edge \
694 |  award[ -]winning # Comments are OK, too! \
695 |  high[ -]performance \
696 |  solutions[ -]based \
697 |  unmatched \
698 |  unparalleled \
699 |  unrivalled \
700 *&#60;font color="red"&#62;&#60;b&#62;BINGO!&#60;/b&#62;&#60;/font&#62; \
701 *igx</PRE
702 ></TD
703 ></TR
704 ></TABLE
705 ></P
706 ><P
707 > The <TT
708 CLASS="LITERAL"
709 >x</TT
710 > option in this job turns on extended syntax, and allows for
711  e.g. the liberal use of (non-interpreted!) whitespace for nicer formatting.</P
712 ><P
713 > You get the idea?</P
714 ></DIV
715 ></DIV
716 ><DIV
717 CLASS="NAVFOOTER"
718 ><HR
719 ALIGN="LEFT"
720 WIDTH="100%"><TABLE
721 WIDTH="100%"
722 BORDER="0"
723 CELLPADDING="0"
724 CELLSPACING="0"
725 ><TR
726 ><TD
727 WIDTH="33%"
728 ALIGN="left"
729 VALIGN="top"
730 ><A
731 HREF="actions-file.html"
732 >Prev</A
733 ></TD
734 ><TD
735 WIDTH="34%"
736 ALIGN="center"
737 VALIGN="top"
738 ><A
739 HREF="index.html"
740 >Home</A
741 ></TD
742 ><TD
743 WIDTH="33%"
744 ALIGN="right"
745 VALIGN="top"
746 ><A
747 HREF="templates.html"
748 >Next</A
749 ></TD
750 ></TR
751 ><TR
752 ><TD
753 WIDTH="33%"
754 ALIGN="left"
755 VALIGN="top"
756 >Actions Files</TD
757 ><TD
758 WIDTH="34%"
759 ALIGN="center"
760 VALIGN="top"
761 >&nbsp;</TD
762 ><TD
763 WIDTH="33%"
764 ALIGN="right"
765 VALIGN="top"
766 >Templates</TD
767 ></TR
768 ></TABLE
769 ></DIV
770 ></BODY
771 ></HTML
772 >