A retake of a 2002 presentation I did at YAPC::EU 2002 (I feel old now) about Source Filters in Perl. It attempts to shed some more light on code alterations and reveals some of the magic behind Acme::Bleach and Acme::Buffy
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Source Filters in Perl 2010
1. Source Filters
in perl
Belgian perl workshop 2010
hendrik van belleghem
2. Source Filters
in perl
Belgian perl workshop 2010
hendrik van belleghem
Spoiler warning: This talk might ruin the magic behind Acme::bleach and acme::buffy
37. Filter::Util::Call
package MyFilter;
use Filter::Util::Call;
sub import
{ my ($type, @arguments) = @_ ;
filter_add([ ]) ;
}
sub filter
{ my ($self) = @_ ;
my ($status) ;
$status = filter_read();
#Do magic with $_ if $status > 0
return $status;
}
1;
38. Filter::Util::Call
package MyFilter;
use Filter::Util::Call;
import is called when module is “used”
sub import
{ my ($type, @arguments) = @_ ;
filter_add([ ]) ;
}
sub filter
{ my ($self) = @_ ;
my ($status) ;
$status = filter_read();
#Do magic with $_ if $status > 0
return $status;
}
1;
39. Filter::Util::Call
package MyFilter;
use Filter::Util::Call;
sub import
{ my ($type, @arguments) = @_ ;
filter_add([ ]) ;
}
sub filter
{ my ($self) = @_ ;
my ($status) ;
$status = filter_read();
if ($status) { $_ =~ s/World/Belgian Perl Workshop/g; }
return $status;
}
1; # Hello World -> Hello Belgian Perl Workshop
61. From Scratch
package Filter::NumberLines::Scratch;
sub scratch { local $_ = pop; s/^d+:t//gm; return $_; }
sub import
{ open 0 or print "Can't number '$0'n" and exit;
my $line = 0; my $no_go = 0; my $past_use = 0; my $file;
while(<0>)
{ $line++;
if ($past_use && /^d+:t/) { $no_go++; $file = join "",$_,<0>; last; }
if ($past_use) { $_ =sprintf("%03d",$line).":t".$_; }
if (/use Filter::NumberLines::Scratch;/) { { $past_use++; }
$file .= $_;
}
if ($no_go)
{ do { eval scratch $file; exit; } }
else { open 0, ">$0" or print "Cannot number '$0'n" and exit;
print {0} $file and exit;
}
}
1;
71. Acme::Bleach
• Bleaches code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into tabs (1) and spaces (0)
72. Acme::Bleach
• Bleaches code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into tabs (1) and spaces (0)
• Reverse to unbleach
73. Acme::Bleach
• Bleaches code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into tabs (1) and spaces (0)
• Reverse to unbleach
• Written by Damian Conway
74. Acme::Bleach
• Bleaches code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into tabs (1) and spaces (0)
• Reverse to unbleach
• Written by Damian Conway
• from scratch
81. Acme::Buffy
• Buffies code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into uppercase and
lowercase letters from the word Buffy
82. Acme::Buffy
• Buffies code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into uppercase and
lowercase letters from the word Buffy
• Written by Leon Brocard
83. Acme::Buffy
• Buffies code
• Step 1: Convert code to bit stream
• Step 2: Convert bits into uppercase and
lowercase letters from the word Buffy
• Written by Leon Brocard
• Written from scratch
87. Acme::Buffy
sub _evil {
return $_[0] =~ /S/;
}
sub _punch {
return $_[0] =~ /^$horns/;
}
sub import {
open 0 or print "Can't rebuffy '$0'n" and exit;
( my $demon = join "", <0> ) =~ s/.*^s*uses+Acme::Buffys*;n//sm;
local $SIG{__WARN__} = &evil;
do { eval _unslay $demon; exit }
unless _evil $demon and not _punch $demon;
open my $fh, ">$0" or print "Cannot buffy '$0'n" and exit;
print $fh "use Acme::Buffy;n", _slay $demon and exit;
print "use Acme::Buffy;n", _slay $demon and exit;
return;
}
"Grrr, arrrgh";
92. Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
• Hardcoded or external algorithm & key phrase
93. Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
• Hardcoded or external algorithm & key phrase
• Pass parameters in use statement
94. Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
• Hardcoded or external algorithm & key phrase
• Pass parameters in use statement
• Based on Filter::Util::Call
95. Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
• Hardcoded or external algorithm & key phrase
• Pass parameters in use statement
• Based on Filter::Util::Call
• Written by uhm me
96. Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
• Hardcoded or external algorithm & key phrase
• Pass parameters in use statement
• Based on Filter::Util::Call
• Written by uhm me
use Filter::CBC "Rijndael","my secret key";
103. Switch
use Switch;
switch ($val) {
case 1 { print "number 1"; }
case "a" { print "string a"; }
case [1..10,42] { print "number in list"; }
case /w+/ { print "pattern"; }
else { print "previous case not true"; }
}
104. Switch
use Switch;
switch ($val) {
case 1 { print "number 1"; }
case "a" { print "string a"; }
case [1..10,42] { print "number in list"; }
case /w+/ { print "pattern"; }
else { print "previous case not true"; }
}
is turned into
105. Switch
use Switch;
switch ($val) {
case 1 { print "number 1"; }
case "a" { print "string a"; }
case [1..10,42] { print "number in list"; }
case /w+/ { print "pattern"; }
else { print "previous case not true"; }
}
is turned into
if ($var == 1) { print “number 1”; }
elsif ($var eq “a”) { print “string a”; }
elsif (grep /$var [1..10,42]) { print "number in list" }
elsif ($var=~ /w+/) { print “pattern”; }
else { print “previous case not true”; }