Extended Matching Commands |

Besides the normal meta-characters, Proxomitron also features special matching commands. Looking a bit like function calls, they work to extend the normal matching rules and add all sorts of useful abilities that would be hard or impossible to do with meta-characters alone. The basic format looks a bit like so...

$COMMAND(Parameter1, Parameter2, ...)

Although the commands begin with a "$", this character alone does not have special meaning. Normally you can use it in a match without having to escape it. The only exception would be if you were matching text that actually looked like an existing command.

One last note: not all commands can be used in all places. Some function only in the match, others only in the replace (and a few in both). Likewise some commands work only in header filters while others are designed to be used in web filters. Any such restrictions will be mentioned in the command descriptions below.

Matching Command Reference

Now without further ado (Ok, just one more ado - Ado! There - got that out of my system now) Here's what you've all been waiting for - A (hopefully) complete listing of all matching commands, their parameters (if any), and their basic use.

Quick Jump: click a link to jump to the command you're looking for or browse below:

$ADDLST $ADDLSTBOX $ALERT $ASK $AV $AVQ $CON $CONFIRM $DTM $ESC $FILE $FILTER $IHDR $INEST $JUMP $KEYCHK $LOCK $LOG $LST $NEST $OHDR $RDIR $RESP $SET $SETPROXY $STOP $TYPE $UESC $UNLOCK $URL $USEPROXY $WESC

$ALERT(message text)

Restrictions: Match or replace
Filter Types: All

$ALERT works much like the JavaScript alert() function. It will display a dialog box with message of your choosing. It doesn't do much of anything but can be useful for debugging or notifying the user something has happened. The message isn't fixed and any of the replacement commands (like \1 and \h) can be used to add captured text, hostnames, etc.

$CONFIRM(message text)

Restrictions: Match or replace
Filter Types: All

Like $ALERT, $CONFIRM will display a dialog box with message of your choosing. However it also includes "Yes" and "No" buttons. This can be used as a test in a match where "Yes" is considered a match and "No" will fail to match. With this, you can have filters do different things depending on how the user responds.

Also like $ALERT, the message will have any replacement commands expanded before the message is displayed.

$ADDLST(ListName, text to add)

Restrictions: Match or replace
Filter Types: All

$ADDLST can be used to add a new line to any currently loaded blocklist. Just give it the name of the list to add the item to and the text of what you want to add and it'll will be appended to the file. Any replacement commands in the text will expanded before the item is added which makes it easy to add captured URLs, hostnames, or other items matched by a filter. One word of caution: it's best not to trust stuff captured from a page - it's a good idea to use the $WESC(...) command to neutralize any potentially harmful matching commands first. For example...

$URL(http://\1)
$ADDLST(MyList, $WESC(\1))

Will make sure that everything captured in the \1 variable will have any wildcards safely escaped into regular characters.

$ADDLSTBOX(ListName, [dialog title,] text to add)

Restrictions: Match or replace
Filter Types: All

$ADDLSTBOX can also be used to add a new line to any currently loaded blocklist. However this does so by calling Proxomitron's "Add to blockfile" dialog box. This gives the user a chance to edit the entry or even cancel the addition altogether. When called in a match, the $ADDLSTBOX will match as "true" if the user decides to add the item and "false" otherwise. The dialog title is optional, but if included will be show in the dialog box's title bar.

$ASK(AllowList, DenyList, Prompt, item to add [, alt match])

Restrictions: Match only
Filter Types: All

$ASK() automates the process of asking the user if a particular item should be filtered at a given site. You first must have both an "Allow" list and a "Deny" list that will be used to store the user's choice (lists could be shared by multiple filters though). "Prompt" is any text you wish to include with the YES/NO choice the user will be given. Any replacement commands will be expanded before display. "item to add" is the item to add to either list (based on the user's choice). It will be matched against the sites URL (by default). $ASK must be used in the matching section of a filter and should normally be the last item checked. Here's an example....

      Name="A foo filter"
      Active=TRUE
      URL="^$LST(AllowFoos)"
      Match="<foo\s*>&"
            "$ASK(AllowFoos, DenyFoos, You you want to Foo at...\n\h?, \h)"
      Replace="<NoFoosAllowed>"

Notice here all we do is insert the hostname of the site into either list using "\h". There's no need to call $LOCK() or any similar commands - $ASK will do that for us to make sure it won't prompt the user twice for the same item. Also notice we've added a "not" test of the allow list to the filter's URL match. It would work without this, but it's always a good idea since, if the item's already allowed, we don't need to use the filter at all on this site.

Normally $ASK will use the site's URL to match against (similar to the filter's own URL match), but it's also possible to match against other items. $ASK can be given an optional "alternate match" that, when expanded, will be matched against the "allow" and "deny" lists instead. Here's an example...

      Name="Filter applets by class"
      Active=TRUE
      Bounds="<applet\s*</applet>"
      Match="<applet*code=$AV(\1)*&"
            "$ASK(AllowApplet, DenyApplet,"
            "Do you you want to allow Java Applet\n[\1]?, \1, \1)"
      Replace="<AppletKilled>"

This first matches the applet's "code" attribute and sticks the value in variable \1. Next when $ASK is called, instead of the page's URL, \1's value is checked against both.

One thing that may seem odd at first is $ASK returns as a "true" when the user selects "No" and "false" when they select "Yes". It may seem backwards, but it makes things simpler since "Yes" normally means we don't want to filter this item.

$AV(match)

Restrictions: Match only
Filter Types: IN Headers, OUT Headers, or Match

This is used to match any attribute's value. It first parses and isolates the value - automatically taking things like quotes vs. no quotes into account. The match within the command is then limited to just the attribute value. Note: Any quotes surrounding the value will not be part of the match.

For example, to match any image with the word "Gargalishous!" in the alt tag, you could use...

<img * alt=$AV(*gargalishous!*) *>

which would work for any of the following...

<img src="foo" alt="My is this trout ever Gargalishous!">
<img src="foo" alt='Gee your hair is Gargalishous! Is that bison flavor?'>
<img src="foo" alt=JustRawGargalishous! >

Even though the match doesn't include the quotes, they'll still be consumed by the command. This means if you want to capture the entire value including quotes you could use a match like...

<img * alt=($AV(\1))\2 *>

Here \2 will contain the full tag with its original quotes, while \1 will just contain the raw value itself. For example given...

<img src="foo" alt="Move all Zig!">
\1 = Move all Zig!
\2 = "Move all Zig!"

But there's also another way to do this - just use $AVQ()

$AVQ(match)

Restrictions: Match only
Filter Types: All

This is exactly like $AV(...) except it also includes any quotes in the match. Useful when you just want to capture an attribute's value like so...

<img * alt=$AVQ(\1) * >

which would capture any alt value into \1.

$DTM(format)

Restrictions: Replace only
Filter Types: All

$DTM can be use to insert date, time and connection information into any replacement text. It uses a simple (case sensitive) format string to control the display...

M = Month
D = Day
Y = Year
h = (12 hour)
H = (24 hour)
m = Minute
s = Second
t = thousandths of a second (milliseconds)
a = (am/pm)
I = Internet formatted UTC
c = Current connection #

There's also some shortcuts

T = H:m:s (24 Hour:Minute:second)
U = M/D/Y (U.S. style date)
E = D/M/Y (European style date)
d = Y-M-D (database style date)

For example, to print out a date "year/month/day" you can use...

$DTM(Y/M/D)

To print out the time in a 12 hour format, you could use...

$DTM(h:m:s a)

To print both use...

$DTM(Y/M/D h:m:s a)

This can be useful for adding dates to a page, or including information for use with $LOG or other similar commands.

$KEYCHK(keycode list)

Restrictions: Match only
Filter Types: All

The KEYCHK command can be used to test for user keypress combinations during a filter test (for example, to have a filter bypass itself or act differently if the user is pressing a specific key). It works like any matching test and can be used in a filter's match or a URL match. When the match is done KEYCHK will return as "matched" if the keys being tested for are currently pressed. Most keys can be tested by using their *unshifted* values. However, there's several special key tests which begin with a carat "^" symbol....

^C = CONTROL
^A = ALT
^S = SHIFT
^T = TAB
^F1 = Function key #1
^F2 = Function key #2
^32 = Virtual keycode 32 (spacebar)
^65 = Virtual keycode 65 ("A")

Characters are not case sensitive so either "^c" or "^C" may be used. Multiple keys can be included to test for combinations. For example...

$KEYCHK(^A^S) = ALT+SHIFT
$KEYCHK(^C^F6) = CONTROL+F6
$KEYCHK(^AG) = ALT+G
$KEYCHK(^C^A^S) = CONTROL+ALT+SHIFT

This will work for any combination the keyboard allows. Other special keys can also be tested if you know the Windows virtual keycode - this is a number between 0-255. For instance ^2 tests for the right mouse button.

$FILE(filename)

Restrictions: Replacement only
Filter Types: All

The $FILE command can be used to insert the contents of any file into the replacement text of a filter. For example...

    Match="(^(^<BODY))"
    Replace="<script>$FILE(c:\mystuff\myscript.js)</script>"
            "$STOP()"

Could be used to insert a custom JavaScript directly before the body tag of a webpage.

It's actually using a bit of a trick to do it too - take a close look at the (^(^...)) in the match section. a single "(^...)" is used to negate a match so what's a "double negative" like "(^(^...))" do? It re-reverses things to make it once again act pretty much like a normal match with one important exception - it consumes no characters! What this means is you can use it to test for something (like a <body> tag) without actually "using it up". That way you don't have to re-include it in the replacement, and other filters can still match on it even without using multi-match!

The trick has one other important feature - if we used multi-match on this filter, anything we inserted via $FILE would be stuck back in the input buffer and also subject to filtering. Using the negative, negative trick take's the cake but let's us have it too (or something like that), but be careful to use something like $STOP() in your filter to prevent matching the same tag over and over!

$LOCK()

Restrictions: None
Filter Types: All

The $LOCK command can be used to make sure a group of items in a filter all happen together as a unit. Only one filter can be "locked" at any given time. Any other filters that then call $LOCK - even on other pages loading at the same time - will have to wait until the first filter has completed or calls $UNLOCK. Most often this can be useful for filters that involve some kind of user interaction, like choosing to add a site to an "allow" or "deny" list. Here's an example...

    (some filter matching code)
    & $LOCK()
    (
      $URL(http://$LST(DenyList))|
      (^$URL(http://$LST(AllowList)))
      (^$CONFIRM(Allow Flash at:\n\h)
        $ADDLST(AllowList,\h)
        $STOP()
      )
      $ADDLST(DenyList,\h)
    )

first the filter is LOCKed so any other filters attempting the same thing will wait until we're finished. Next we check to see if the site's already in the "deny" list. If so, we have a match and don't need to do anything else, but if it's not denied, we then check to make sure it's not in the "allow" list. If it's not allowed either, we finally prompt the user for a choice. Depending on the user's choice we either add the hostname to the "allow" or "deny" lists so they won't need to be asked again next time.

As you can see quite a bit has to happen here, and while it's happening it's important no other page try to do the same check until we're finished. $LOCK insures the whole deal happens as a single unit. Keep in mind this slows things down, so you should never call LOCK before you really need to. In the example above, the normal filter's match would be completed first before the "locked" section.

$UNLOCK()

Restrictions: None
Filter Types: All
$UNLOCK is the reverse of the $LOCK function. It releases the lock allowing the next filter waiting for a LOCK to complete. Also, UNLOCK is automatically called after a filter completes. Usually, you only need to call it yourself if you'd like to release a lock sooner.

$LOG([RGBYVCWw]text to log)

Restrictions: None
Filter Types: All

$LOG can be used to display an entry in Proxomitron's log window (if it's open). It can be useful for debugging or adding more detailed information about a filter to the log. One thing to keep in mind is the first character is special - it's not shown in the log, but sets what color the line will be displayed as. For example...

$LOG(RThis will be red)

Here's a list of the available colors:

R=Red W=White w=Gray B=Blue G=Green Y=Yellow V=Violet C=Cyan

Keep in mind they're case sensitive.

$LST(blockfile name)

Restrictions: None
Filter Types: All

This Is used to include a blockfile in any matching expression. The contents ofthe blockfile are tested line by line against the text to be matched until a match is found. Otherwise the expression returns false.

$NEST(start match, [inner match,] end match)

Restrictions: Match only
Filter Types: All (but mainly web)

The $NEST command can be used to find the corosponding ending tag or character for a given starting tag or character even when the same tag may be nested within. To use nest you must give it a "start match" which will match the opening tag and an "end match" which will match the closing tag. For example, to match nested <TABLE> tags you might use...

$NEST(<table*>,</table>)

Given the following text, it would match the area in red...

    ...some HTML...
    <table name="outer table">
      ...
      <table name="inner table">
        ...
      </table>
      ...
    </table>
    ...some more HTML...

Notice it manages to find the correct ending tag for the outer table even though there's an innter table also using the same tags.

$NEST can also have an optional third "inner match" parameter. If present this match will be applied to the area of text withing the starting and ending tags matched. It's important to note this doesn't include the actual text in the starting or ending tag, only what's between them. Again using the example above...

$NEST(<table*>,\1,</table>)

Given the following text the "\1" would only match the area in blue...

    ...some HTML...
    <table name="outer table">
      ...
      <table name="inner table">
        ...
      </table>
      ...
    </table>
    ...some more HTML...

$INEST(start match, [inner match], end match)

Restrictions: Match only
Filter Types: All (but mainly web)

$INEST ("Inner Nest") works just like $NEST above except that the initial starting tag and ending tag are located outside the command. In other words, it assumes you've already found the tag your looking for and are only interested in discovering its end. Again the example from $NEST above might look like this...

<table name=$AV(*outer*) >$INEST(<table*>,</table>) </table>

Given the following text, it would match the area in red...

    ...some HTML...
    <table name="outer table">
      ...
      <table name="inner table">
        ...
      </table>
      ...
    </table>
    ...some more HTML...

the advantage here is it makes it easier to look for a particular starting tag (in this case a table with "outer" in the name) as opposed to just any starting tag of that type. It would be hard to do this with $NEST alone since any check in the "start match" section would have to be true not only for the outer nested table but the inner ones as well.

$SET(\# or \0-\9=Value)

Restrictions: Match only
Filter Types: All

Use to set a positional variable to a specific value. Any replacement text, including other variables, can be set entered here. The first parameter is a positional variable \0 through \9 or the replacement stack variable \# (although the "\" is optional). Next is an equal followed by the value to be set. For example...

Set \1 equal to "foobar": $SET(1=foobar)

Set variable \1 to print the contents of \2: $SET(1=Two is \2)

By placing $SET commands within a matching expression, you can set various values *only* if the matching expression reaches that point. This can be used for an if/then/else effect...

    Match: name=(one $SET(0=Naoko) | two $SET(0=Atsuko)
                  | three $SET(0=Michie) | $SET(0=Default))
    Replace: "\0 Matched"

will produce the following results...

if name=one then "Naoko Matched"
if name=two then "Atsuko Matched"
if name=three then "Michie Matched"
else "Default matched"

The set command has some limitations: The value a variable is set to isn't "expanded" until it's actually called in the replacement text. This means if \1 is "fish" and you use a SET command like $SET(\2=\1 food), the \2 will not become "fish food" but will be literally set to "\1 food". However this will be expanded to "fish food" when \2 is printed in the replacement section. Why is this important? Well, for one thing it means you can't set a variable to include part of itself as in $SET(\1=something and \1).

$CON:(x,y[,z])

Restrictions: Match only
Filter Types: All

CON will be true only if the current connection number is 'x' of 'y' (optionally for every 'z' connections). It can be used to rotate values based on connection. The following for example will rotate between three values in \0 ...

($CON(1,3) $SET(0=Value one of three)|
$CON(2,3) $SET(0=Value two of three)|
$CON(3,3) $SET(0=Value three of three))

use the 'z' option to delay the rotation to every so many connections.

$IHDR(header-name:matching)
$OHDR(header-name:matching)

Restrictions: Match only
Filter Types: All

$OHDR and $IHDR Can be use to test the value of any outgoing or incoming HTTP header respectively. First include the specific header to test (no wildcards) followed by a match for the header's value (wildcards are allowed here). The command will be true only if the named header's value matches the 'matching' section. $OHDR tests outgoing headers while $IHDR tests incoming headers. For example this will only match is the "Referer" header contains 'microsoft.com'

$OHDR(Referer:*.microsoft.com)

Using these you can have web filter only match if specific header values are also true, or to capture and use header values into a variables to use in a filter's replacement. You can use also them in HTTP header filters to check combinations of headers for a match.

$RESP(matching)

Restrictions: Match only
Filter Types: All

The $RESP command can be used to match or capture the response code returned by a web server (which you can view in the log window). Normally they'll look something like "200 OK" or "404 Not Found" etc.

The match starts directly with the returned code so does not include the "HTTP/x.x" portion of the reply line. It includes only the three digit status code and the descriptive text that usually follows it. For example, to match server redirects you could use "$RESP(302*)". It can also be useful for capturig information to include in a log file.

$URL(matching value)

Restrictions: Match only
Filter Types: All

$URL can be used to test the URL inside the matching portion of a filter. Normally you would use the filter's URL match for this, but by using this command you can check for different URL based on the text matched. It's also useful to capture portions of a URL into variables. The following would capture the URL's path...

$URL(http://www.somehost.com/\1)

Note: The URL matching now include the protocol portion of the URL in the test (i.e. the "http://"). Since Proxomitron now handles more than HTTP, that can come in useful. However it does make a change from previous versions, so you may need to adjust older filters.

$TYPE(code)

Restrictions: Match only
Filter Types: Web filters

Content Type check command. This command can be used to limit a filter to only affect certain types of pages (like JavaScript files only). The "code" must be one of the following known types...

htm | - Web pages
css | - Cascading style sheets
js | - JavaScript
vbs | - VB Script
oth | - Anything else

This is can be useful for web filters especially in their URL match. Its value is undefined in header filters (since the content-type may not be known yet). Keep in mind it's a fast and simple check. For more complex content-type checks you can also use "$IHDR(Content-Type: ... )" where "..." is any matching expression including wildcards.

$RDIR(http://some.url.com/)

Restrictions: Match or replace
Filter Types: IN or OUT header filters only

The $RDIR (redirect) command is used to transparently redirect URLs to a different location. It's also possible to redirect to a local file by using the "http://file//filename" URL command syntax. The new URL must be of a type Proxomitron understands (http, or with SSLeay, https).

Use both $RDIR and $JUMP (see below) commands in the replacement section of header filters only. It's important to note that for outgoing headers the redirect will happen before the original site is ever contacted, but when used with incoming headers, the initial site must be contacted first. These commands have no effect in web filters since by this point the original page has already begun loading into your browser. In such cases you can often use JavaScript to change to a new location as in...

<script> document.location="http://some.new.url/"; </script>

$JUMP(http://some.url.com/)

Restrictions: Match or replace
Filter Types: IN or OUT header filters only

Similar to the $RDIR command, the $JUMP command can be used to redirect a URL to a different location. However instead of transparent redirection this works by just telling your browser to go to that new location. It's more like using a refresh "meta" tag or setting document.location in a JavaScript (it actually send a 302 redirect command to the browser).

With $JUMP your browser is aware of the redirection and the URL you see will be updated to reflect the new location. It works best for redirecting an entire page, while $RDIR is better at invisibly redirecting individual page elements like images or java apps. Use $RDIR when you want the redirection to happen "behind the scenes" and use $JUMP when you want to simply go to a different site from the one requested.

$STOP()

Restrictions: Match or Replace
Filter Types: All

$STOP is a very simple command. If encountered in either the match or replace of a filter $STOP will turn that filter off for the rest of the page/connection. The current match will be allowed to complete, but once that happens, no further matching will be done on that filter.

This can be very useful for filters you only want to match once. Especially ones that insert something into a page at a given point. For example, say you wanted to insert a small script after the <BODY> tag. You could use...

Match: | <body\s \1>
Replace: | <body \1> <script>my script</script> $STOP( )

Not only does this insure the script will only be inserted once, but it also speeds things up since Proxomitron doesn't have to waste time checking for it anymore. Also note that $STOP will now do its thing even if the filter as a whole doesn't match as long as it's called at some point in the matching process.

$FILTER(True or False boolean value)

Restrictions: Match or replace
Filter Types: IN or OUT header filters only

The $FILTER command can be used to force a particular request to be filtered or not filtered regardless of it's type. Normally only specific types are filtered (like text/html, text/css, image/gif, etc). $FILTER can be used in the match or replace of any header filter and takes a "true" or "false" value. If true, the request will be run through the web filters regardless of it's type. Beware this only makes sense for content that's text based.

You can also use it to avoid "freezing" certain GIF images by using it in a header filter along with a URL match.

Take for example...

Out = "True"
Key="URL: Don't freeze this gif"
URL="www.somewhere.com/animate_me.gif"
Replace="$FILTER(False)"

$USEPROXY(True or False boolean value)

Restrictions: Match or replace
Filter Types: OUT header filters only

The $USEPROXY command also takes a "true" or "false" boolean value and can override the "Use remote proxy" check box for a given connection either turning the proxy on or off. It can be use to ensure a proxy is or isn't used for with a given site or for a particular action.

To have effect this command must be called in either the match or replace of an *outgoing* header filter. This is because the proxy setting must be established prior to connecting to the site.

$SETPROXY(remote.proxy.name[:port])

Restrictions: Match or replace
Filter Types: OUT header filters only

The $SETPROXY command will force a connection to use a particular proxy. It overrides both the "Use remote proxy" checkbox and the current proxy chosen in the proxy selector. It's useful for insuring a particular proxy is used in a given situation or with a particular URL.

The proxy to set must be one already entered into the External Proxy Selector list. This command simply looks up and sets a proxy from that list. It's usually only necessary type the first part of the proxy name - the first proxy matched in the list will be use. The partial match must be exact though (no wildcards).

Like the previous command this command must be also called in either the match or replace of an *outgoing* header filter.

$UESC(escaped text)

Restrictions: Replace only
Filter Types: All

The $UESC command is intended to be similar to the JavaScript unescape() command. It will convert most URL escaped characters back to their ASCII form. It's useful for unescaping URLs that may be embedded in other URLs (an increasingly common trick used by many sites to track the links you click). Often characters like ":" and "/" will be escaped by their hex equivilents ("%3A" and "%2F") making the real URL hard to use.

$UESC can be used in the replacement text of a filter, and can be given any valid replacement text as input (such as \1 variables). It will convert most escaped characters back to their correct form, but spaces and any non-displayable ASCII characters will remain escaped.

$ESC(any text)

Restrictions: Replace only
Filter Types: All

The $ESC command is the reverse of $UESC command. Similar in function to the JavaScript escape() command, it converts most non-alphanumeric characters into hexadecimal escape codes (of the form %xx) making them safe for inclusion as part of a URL.

$ESC can be used in the replacement text of a filter, and can be given any valid replacement text as input (such as \1 variables).

$WESC(any text)

Restrictions: Replace only
Filter Types: All

The $WESC is a bit like $ESC except it's designed to escape any wildcards or matching commands Proxomitron may use. It can be useful for inserting captured text into a blockfile when the text may contain possible wildcards characters like * or ?.

$WESC can be used in the replacement text of a filter, or even in the matching section if used within a command that does a replacement expansion on it's input (like $ADDLST and $ADDLSTBOX).

Return to main index