SlideShare uma empresa Scribd logo
1 de 106
Source Filters
   in perl
 Belgian perl workshop 2010
   hendrik van belleghem
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
Eh?
Eh?


• What are Source Filters?
Eh?


• What are Source Filters?
• Writing Source Filters
Eh?


• What are Source Filters?
• Writing Source Filters
• Magic revealed!
What are source filters?
What are source filters?


• Manipulate code during compile time
What are source filters?


• Manipulate code during compile time
• Modules loaded during compile time
What are source filters?


• Manipulate code during compile time
• Modules loaded during compile time
• Only works on main::
What are source filters?


• Manipulate code during compile time
• Modules loaded during compile time
• Only works on main::
• Only parses $0
Example
Acme::bleach
Example
Acme::bleach
  before       after




For *really* clean programs
Example
         Acme::bleach


Before
Example
           Acme::bleach


Before
#!/usr/bin/perl
use Acme::Bleach;
print “Hello World”;
Example
        Acme::bleach


After
Example
           Acme::bleach


After
#!/usr/bin/perl
use Acme::Bleach;
Example
           Acme::bleach


After
#!/usr/bin/perl
use Acme::Bleach;
Example
          Acme::bleach


• Live demo?
Writing source filters
Writing source filters

• Approaches:
Writing source filters

• Approaches:
   • Filter::Util::Call
Writing source filters

• Approaches:
   • Filter::Util::Call
   • Filter::Simple
Writing source filters

• Approaches:
   • Filter::Util::Call
   • Filter::Simple
   • From scratch
Writing source filters

• Approaches:
   • Filter::Util::Call
   • Filter::Simple
   • From scratch
• Our example: Line numbers
Writing source filters
Writing source filters

• Problem: Filter the code first
Writing source filters

• Problem: Filter the code first
   • Adding line numbers
Writing source filters

• Problem: Filter the code first
   • Adding line numbers
   • Bleaching (Acme::Bleach)
Writing source filters

• Problem: Filter the code first
   • Adding line numbers
   • Bleaching (Acme::Bleach)
   • Buffy’ing (Acme::Buffy)
Writing source filters

• Problem: Filter the code first
   • Adding line numbers
   • Bleaching (Acme::Bleach)
   • Buffy’ing (Acme::Buffy)
   • Encrypting (Filter::CBC)
Writing source filters

• Problem: Filter the code first
   • Adding line numbers
   • Bleaching (Acme::Bleach)
   • Buffy’ing (Acme::Buffy)
   • Encrypting (Filter::CBC)
• Problem: Don’t filter filtered code again
Filter::Util::Call
Filter::Util::Call


• Module by Paul Marquess
Filter::Util::Call


• Module by Paul Marquess
• Part of Perl core
Filter::Util::Call


• Module by Paul Marquess
• Part of Perl core
• Could be easier
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;
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;
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
Filter::NumberLines
package Filter::NumberLines;
use Filter::Util::Call;

sub import
{ my ($type, @arguments) = @_ ;
  filter_add([ ]) ;
}

sub filter
{ my ($self) = @_ ;
  my ($status) ;
  $status = filter_read();
  if ($status) { $_ =~ s/^d+:t//gm; }
  return $status;
}
1;
Filter::NumberLines
Filter::NumberLines


• One Problem..
Filter::NumberLines


• One Problem..
• We have to add the line numbers manually
Filter::NumberLines


• One Problem..
• We have to add the line numbers manually
• Introducing auto-filtering code...
Filter::NumberLines



Add this at the bottom..
Filter::NumberLines
open(INFILE,"<$0") || die $!;
open(OUTFILE,">$0.bak") || die $!;
my $line = 0; my $no_go = 0; my $past_use = 0; $|++;
while(<INFILE>)
{ $line++;
   if ($past_use && /^d+:t/) { $no_go++; last; }
  if ($past_use) { $_ =sprintf("%03d",$line).":t".$_; }
  if (/use Filter::NumberLines;/) { $past_use++; }
  print OUTFILE $_;
}
close(OUTFILE);
close (INFILE);
if (!$no_go)
{ unlink($0) || die $!; rename ("$0.bak",$0);
  exit;
}
else { unlink("$0.bak") || die $!; }
Filter::NumberLines



• Live demo?
Filter::Simple
Filter::Simple


• Module by Damian Conway
Filter::Simple


• Module by Damian Conway
• Part of Perl core
Filter::Simple


• Module by Damian Conway
• Part of Perl core
• Much easier than Filter::Util::Call
Filter::Simple


    package MyFilter;
use Filter::Simple;

FILTER { do_some_magic(); };

1;
Filter::NumberLines


package Filter::NumberLines::Simple;
use Filter::Simple;

FILTER { s/^d+:t//gm; }

1;
Filter::NumberLines
Filter::NumberLines


• One Problem..
Filter::NumberLines


• One Problem..
• We have to add the line numbers again
Filter::NumberLines


• One Problem..
• We have to add the line numbers again
• Introducing auto-filtering code...
Filter::NumberLines



Add this at the bottom..
Filter::NumberLines
open(INFILE,"<$0") || die $!;
open(OUTFILE,">$0.bak") || die $!;
my $line = 0; my $no_go = 0; my $past_use = 0; $|++;
while(<INFILE>)
{ $line++;
   if ($past_use && /^d+:t/) { $no_go++; last; }
  if ($past_use) { $_ =sprintf("%03d",$line).":t".$_; }
  if (/use Filter::NumberLines::Simple;/) { $past_use++; }
  print OUTFILE $_;
}
close(OUTFILE);
close (INFILE);
if (!$no_go)
{ unlink($0) || die $!; rename ("$0.bak",$0);
  exit;
}
else { unlink("$0.bak") || die $!; }
Filter::NumberLines



• Live demo?
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;
From Scratch



• Live demo?
From Scratch
From Scratch
          Easy
                 Bree
                     zy!
From Scratch
                      Easy
                             Bree
                                 zy!

• Filter code..
From Scratch
                      Easy
                             Bree
                                 zy!

• Filter code..
• and eval’uate it.
Magic Revealed
Acme::Bleach
Acme::Bleach
• Bleaches code
Acme::Bleach
• Bleaches code
   • Step 1: Convert code to bit stream
Acme::Bleach
• Bleaches code
   • Step 1: Convert code to bit stream
   • Step 2: Convert bits into tabs (1) and spaces (0)
Acme::Bleach
• Bleaches code
   • Step 1: Convert code to bit stream
   • Step 2: Convert bits into tabs (1) and spaces (0)
• Reverse to unbleach
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
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
Acme::Bleach
Acme::Bleach
   package Acme::Bleach;

my $tie = " t"x8;

sub whiten { local $_ = unpack "b*", pop; tr/01/ t/; s/(.{9})/$1n/g; $tie.$_ }
sub brighten { local $_ = pop; s/^$tie|[^ t]//g; tr/ t/01/; pack "b*", $_ }
sub dirty { $_[0] =~ /S/ }
sub dress { $_[0] =~ /^$tie/ }
open 0 or print "Can't rebleach '$0'n" and exit;
(my $shirt = join "", <0>) =~ s/.*^s*uses+Acme::Bleachs*;n//sm;
local $SIG{__WARN__} = &dirty;
do { eval brighten $shirt; exit } unless dirty $shirt && not dress $shirt;
open 0, ">$0" or print "Cannot bleach '$0'n" and exit;
print {0} "use Acme::Bleach;n", whiten $shirt and exit;
Acme::Bleach



• Live demo?
Acme::Buffy
Acme::Buffy

• Buffies code
Acme::Buffy

• Buffies code
   • Step 1: Convert code to bit stream
Acme::Buffy

• Buffies code
   • Step 1: Convert code to bit stream
   • Step 2: Convert bits into uppercase and
     lowercase letters from the word Buffy
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
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
Acme::Buffy
Acme::Buffy
    my $horns = “BUffY bUFFY” x 2;
my $i = 0;

sub _slay {
   my $willow = unpack "b*", pop;
   my @buffy = ( 'b', 'u', 'f', 'f', 'y', ' ' );
   my @BUFFY = ( 'B', 'U', 'F', 'F', 'Y', "t" );
   my $demons = $horns;
   foreach ( split //, $willow ) {
      $demons .= $_ ? $BUFFY[$i] : $buffy[$i];
      $i++;
      $i = 0 if $i > 5;
   }
   return $demons;
}
sub _unslay {
   my $demons = pop;
   $demons =~ s/^$horns//g;
   my @willow;
   foreach ( split //, $demons ) {
      push @willow, /[buffy ]/ ? 0 : 1;
   }
   return pack "b*", join '', @willow;
}
Acme::Buffy
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";
Acme::Buffy



• Live demo?
Filter::CBC
Filter::CBC
• Encrypts code using Crypt::CBC
Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
Filter::CBC
• Encrypts code using Crypt::CBC
• Can use any algorithm that uses CBC cipher
 • Hardcoded or external algorithm & key phrase
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
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
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
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";
Filter::CBC
Filter::CBC
   my $blank = “This space is left blank intentionally”;

sub import
{ my ($type) = shift @_;
 my $algorithm = shift || "Rijndael";
 $algorithm = $Ciphers{uc $algorithm} || $algorithm;
 my $key = shift || $blank; my ($ref) = [ ];
 $cipher = Crypt::CBC->new(-key => $key,-cipher => $algorithm);
 if (defined $algorithm && defined $key)
 { open(F,"<$0") || die $!; flock(F,2); seek(F,0,0);
    my @CODE = (); my $past_use;
    while(<F>)
    { if (/^# $blank/ && !$past_use) { close(F); last; }
      if (/use Filter::CBC/) { push(@CODE,$_); $past_use++; next; }
      if (!$past_use) { push(@CODE,$_); }
   else
Filter::CBC
Filter::CBC
          { my $code = $_; local $/ = undef; $code .= <F>;
           splice(@CODE,-2,0,"# $blank");
           $code = $cipher->encrypt($code);
           open(OUTFILE,">$0.bak") || die $!;
           binmode(OUTFILE);
           print OUTFILE @CODE,$code;
           close(OUTFILE); close(F);
           unlink("$0") || die $!;
           rename ("$0.bak",$0) || die $!;
           exit;
         }
     }
    }
    filter_add(bless $ref) ;
}

sub filter
{ my ($self) = @_ ; my ($status); local $/ = undef;
  if (($status = filter_read()) > 0) { $_ = $cipher->decrypt($_); }
  return $status ;
}
1;
Questions?



• Time for bonus slides?
Switch
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"; }
}
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
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”; }
Acme::Pony

Mais conteúdo relacionado

Mais procurados

Mais procurados (20)

Working with Cocoa and Objective-C
Working with Cocoa and Objective-CWorking with Cocoa and Objective-C
Working with Cocoa and Objective-C
 
Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)
Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)
Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)
 
Learn JavaScript by modeling Rubik Cube
Learn JavaScript by modeling Rubik CubeLearn JavaScript by modeling Rubik Cube
Learn JavaScript by modeling Rubik Cube
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Drupal 8: A story of growing up and getting off the island
Drupal 8: A story of growing up and getting off the islandDrupal 8: A story of growing up and getting off the island
Drupal 8: A story of growing up and getting off the island
 
"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo"Managing API Complexity". Matthew Flaming, Temboo
"Managing API Complexity". Matthew Flaming, Temboo
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Defensive Coding Crash Course Tutorial
Defensive Coding Crash Course TutorialDefensive Coding Crash Course Tutorial
Defensive Coding Crash Course Tutorial
 
Xtext Webinar
Xtext WebinarXtext Webinar
Xtext Webinar
 
Starting Out With PHP
Starting Out With PHPStarting Out With PHP
Starting Out With PHP
 
Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)Diving into HHVM Extensions (php[tek] 2016)
Diving into HHVM Extensions (php[tek] 2016)
 
Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Sca...
Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Sca...Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Sca...
Scala in-practice-3-years by Patric Fornasier, Springr, presented at Pune Sca...
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
Php training100%placement-in-mumbai
Php training100%placement-in-mumbaiPhp training100%placement-in-mumbai
Php training100%placement-in-mumbai
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Intro to PHP for Beginners
Intro to PHP for BeginnersIntro to PHP for Beginners
Intro to PHP for Beginners
 
Intro to Perl and Bioperl
Intro to Perl and BioperlIntro to Perl and Bioperl
Intro to Perl and Bioperl
 
Scala in Practice
Scala in PracticeScala in Practice
Scala in Practice
 
Intermediate OOP in PHP
Intermediate OOP in PHPIntermediate OOP in PHP
Intermediate OOP in PHP
 
PHP 7 – What changed internally?
PHP 7 – What changed internally?PHP 7 – What changed internally?
PHP 7 – What changed internally?
 

Destaque

Destaque (8)

Cleancode
CleancodeCleancode
Cleancode
 
Json In 5 Slices.Key
Json In 5 Slices.KeyJson In 5 Slices.Key
Json In 5 Slices.Key
 
Scrabbling Code - Beatnik - YAPC::Eu::2003
Scrabbling Code - Beatnik - YAPC::Eu::2003Scrabbling Code - Beatnik - YAPC::Eu::2003
Scrabbling Code - Beatnik - YAPC::Eu::2003
 
China.z / Trojan.XorDDOS - Analysis of a hack
China.z / Trojan.XorDDOS - Analysis of a hackChina.z / Trojan.XorDDOS - Analysis of a hack
China.z / Trojan.XorDDOS - Analysis of a hack
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101
 
Learn BEM: CSS Naming Convention
Learn BEM: CSS Naming ConventionLearn BEM: CSS Naming Convention
Learn BEM: CSS Naming Convention
 
SEO: Getting Personal
SEO: Getting PersonalSEO: Getting Personal
SEO: Getting Personal
 
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job? Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
Succession “Losers”: What Happens to Executives Passed Over for the CEO Job?
 

Semelhante a Source Filters in Perl 2010

Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Jesse Vincent
 

Semelhante a Source Filters in Perl 2010 (20)

Hiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret SauceHiveminder - Everything but the Secret Sauce
Hiveminder - Everything but the Secret Sauce
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
 
Ruby 2: some new things
Ruby 2: some new thingsRuby 2: some new things
Ruby 2: some new things
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
Php Crash Course - Macq Electronique 2010
Php Crash Course - Macq Electronique 2010Php Crash Course - Macq Electronique 2010
Php Crash Course - Macq Electronique 2010
 
Write your Ruby in Style
Write your Ruby in StyleWrite your Ruby in Style
Write your Ruby in Style
 
Designing code
Designing codeDesigning code
Designing code
 
Intermediate OOP in PHP
Intermediate OOP in PHPIntermediate OOP in PHP
Intermediate OOP in PHP
 
Message passing
Message passingMessage passing
Message passing
 
Clean Manifests with Puppet::Tidy
Clean Manifests with Puppet::TidyClean Manifests with Puppet::Tidy
Clean Manifests with Puppet::Tidy
 
Rails console
Rails consoleRails console
Rails console
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Dev traning 2016 basics of PHP
Dev traning 2016   basics of PHPDev traning 2016   basics of PHP
Dev traning 2016 basics of PHP
 
Designing Auto Generated Codes
Designing Auto Generated CodesDesigning Auto Generated Codes
Designing Auto Generated Codes
 
Unleash your inner console cowboy
Unleash your inner console cowboyUnleash your inner console cowboy
Unleash your inner console cowboy
 
CPAN Exporter modules for Perl 5
CPAN Exporter modules for Perl 5CPAN Exporter modules for Perl 5
CPAN Exporter modules for Perl 5
 
Documenting with xcode
Documenting with xcodeDocumenting with xcode
Documenting with xcode
 
Intro to C++
Intro to C++Intro to C++
Intro to C++
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Último (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

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
  • 3. Eh?
  • 4. Eh? • What are Source Filters?
  • 5. Eh? • What are Source Filters? • Writing Source Filters
  • 6. Eh? • What are Source Filters? • Writing Source Filters • Magic revealed!
  • 7. What are source filters?
  • 8. What are source filters? • Manipulate code during compile time
  • 9. What are source filters? • Manipulate code during compile time • Modules loaded during compile time
  • 10. What are source filters? • Manipulate code during compile time • Modules loaded during compile time • Only works on main::
  • 11. What are source filters? • Manipulate code during compile time • Modules loaded during compile time • Only works on main:: • Only parses $0
  • 13. Example Acme::bleach before after For *really* clean programs
  • 14. Example Acme::bleach Before
  • 15. Example Acme::bleach Before #!/usr/bin/perl use Acme::Bleach; print “Hello World”;
  • 16. Example Acme::bleach After
  • 17. Example Acme::bleach After #!/usr/bin/perl use Acme::Bleach;
  • 18. Example Acme::bleach After #!/usr/bin/perl use Acme::Bleach;
  • 19. Example Acme::bleach • Live demo?
  • 22. Writing source filters • Approaches: • Filter::Util::Call
  • 23. Writing source filters • Approaches: • Filter::Util::Call • Filter::Simple
  • 24. Writing source filters • Approaches: • Filter::Util::Call • Filter::Simple • From scratch
  • 25. Writing source filters • Approaches: • Filter::Util::Call • Filter::Simple • From scratch • Our example: Line numbers
  • 27. Writing source filters • Problem: Filter the code first
  • 28. Writing source filters • Problem: Filter the code first • Adding line numbers
  • 29. Writing source filters • Problem: Filter the code first • Adding line numbers • Bleaching (Acme::Bleach)
  • 30. Writing source filters • Problem: Filter the code first • Adding line numbers • Bleaching (Acme::Bleach) • Buffy’ing (Acme::Buffy)
  • 31. Writing source filters • Problem: Filter the code first • Adding line numbers • Bleaching (Acme::Bleach) • Buffy’ing (Acme::Buffy) • Encrypting (Filter::CBC)
  • 32. Writing source filters • Problem: Filter the code first • Adding line numbers • Bleaching (Acme::Bleach) • Buffy’ing (Acme::Buffy) • Encrypting (Filter::CBC) • Problem: Don’t filter filtered code again
  • 35. Filter::Util::Call • Module by Paul Marquess • Part of Perl core
  • 36. Filter::Util::Call • Module by Paul Marquess • Part of Perl core • Could be easier
  • 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
  • 40. Filter::NumberLines package Filter::NumberLines; use Filter::Util::Call; sub import { my ($type, @arguments) = @_ ; filter_add([ ]) ; } sub filter { my ($self) = @_ ; my ($status) ; $status = filter_read(); if ($status) { $_ =~ s/^d+:t//gm; } return $status; } 1;
  • 43. Filter::NumberLines • One Problem.. • We have to add the line numbers manually
  • 44. Filter::NumberLines • One Problem.. • We have to add the line numbers manually • Introducing auto-filtering code...
  • 46. Filter::NumberLines open(INFILE,"<$0") || die $!; open(OUTFILE,">$0.bak") || die $!; my $line = 0; my $no_go = 0; my $past_use = 0; $|++; while(<INFILE>) { $line++; if ($past_use && /^d+:t/) { $no_go++; last; } if ($past_use) { $_ =sprintf("%03d",$line).":t".$_; } if (/use Filter::NumberLines;/) { $past_use++; } print OUTFILE $_; } close(OUTFILE); close (INFILE); if (!$no_go) { unlink($0) || die $!; rename ("$0.bak",$0); exit; } else { unlink("$0.bak") || die $!; }
  • 50. Filter::Simple • Module by Damian Conway • Part of Perl core
  • 51. Filter::Simple • Module by Damian Conway • Part of Perl core • Much easier than Filter::Util::Call
  • 52. Filter::Simple package MyFilter; use Filter::Simple; FILTER { do_some_magic(); }; 1;
  • 56. Filter::NumberLines • One Problem.. • We have to add the line numbers again
  • 57. Filter::NumberLines • One Problem.. • We have to add the line numbers again • Introducing auto-filtering code...
  • 59. Filter::NumberLines open(INFILE,"<$0") || die $!; open(OUTFILE,">$0.bak") || die $!; my $line = 0; my $no_go = 0; my $past_use = 0; $|++; while(<INFILE>) { $line++; if ($past_use && /^d+:t/) { $no_go++; last; } if ($past_use) { $_ =sprintf("%03d",$line).":t".$_; } if (/use Filter::NumberLines::Simple;/) { $past_use++; } print OUTFILE $_; } close(OUTFILE); close (INFILE); if (!$no_go) { unlink($0) || die $!; rename ("$0.bak",$0); exit; } else { unlink("$0.bak") || die $!; }
  • 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;
  • 64. From Scratch Easy Bree zy!
  • 65. From Scratch Easy Bree zy! • Filter code..
  • 66. From Scratch Easy Bree zy! • Filter code.. • and eval’uate it.
  • 70. Acme::Bleach • Bleaches code • Step 1: Convert code to bit stream
  • 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
  • 76. Acme::Bleach package Acme::Bleach; my $tie = " t"x8; sub whiten { local $_ = unpack "b*", pop; tr/01/ t/; s/(.{9})/$1n/g; $tie.$_ } sub brighten { local $_ = pop; s/^$tie|[^ t]//g; tr/ t/01/; pack "b*", $_ } sub dirty { $_[0] =~ /S/ } sub dress { $_[0] =~ /^$tie/ } open 0 or print "Can't rebleach '$0'n" and exit; (my $shirt = join "", <0>) =~ s/.*^s*uses+Acme::Bleachs*;n//sm; local $SIG{__WARN__} = &dirty; do { eval brighten $shirt; exit } unless dirty $shirt && not dress $shirt; open 0, ">$0" or print "Cannot bleach '$0'n" and exit; print {0} "use Acme::Bleach;n", whiten $shirt and exit;
  • 80. Acme::Buffy • Buffies code • Step 1: Convert code to bit stream
  • 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
  • 85. Acme::Buffy my $horns = “BUffY bUFFY” x 2; my $i = 0; sub _slay { my $willow = unpack "b*", pop; my @buffy = ( 'b', 'u', 'f', 'f', 'y', ' ' ); my @BUFFY = ( 'B', 'U', 'F', 'F', 'Y', "t" ); my $demons = $horns; foreach ( split //, $willow ) { $demons .= $_ ? $BUFFY[$i] : $buffy[$i]; $i++; $i = 0 if $i > 5; } return $demons; } sub _unslay { my $demons = pop; $demons =~ s/^$horns//g; my @willow; foreach ( split //, $demons ) { push @willow, /[buffy ]/ ? 0 : 1; } return pack "b*", join '', @willow; }
  • 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";
  • 90. Filter::CBC • Encrypts code using Crypt::CBC
  • 91. Filter::CBC • Encrypts code using Crypt::CBC • Can use any algorithm that uses CBC cipher
  • 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";
  • 98. Filter::CBC my $blank = “This space is left blank intentionally”; sub import { my ($type) = shift @_; my $algorithm = shift || "Rijndael"; $algorithm = $Ciphers{uc $algorithm} || $algorithm; my $key = shift || $blank; my ($ref) = [ ]; $cipher = Crypt::CBC->new(-key => $key,-cipher => $algorithm); if (defined $algorithm && defined $key) { open(F,"<$0") || die $!; flock(F,2); seek(F,0,0); my @CODE = (); my $past_use; while(<F>) { if (/^# $blank/ && !$past_use) { close(F); last; } if (/use Filter::CBC/) { push(@CODE,$_); $past_use++; next; } if (!$past_use) { push(@CODE,$_); } else
  • 100. Filter::CBC { my $code = $_; local $/ = undef; $code .= <F>; splice(@CODE,-2,0,"# $blank"); $code = $cipher->encrypt($code); open(OUTFILE,">$0.bak") || die $!; binmode(OUTFILE); print OUTFILE @CODE,$code; close(OUTFILE); close(F); unlink("$0") || die $!; rename ("$0.bak",$0) || die $!; exit; } } } filter_add(bless $ref) ; } sub filter { my ($self) = @_ ; my ($status); local $/ = undef; if (($status = filter_read()) > 0) { $_ = $cipher->decrypt($_); } return $status ; } 1;
  • 101. Questions? • Time for bonus slides?
  • 102. Switch
  • 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”; }

Notas do Editor