| Acme-Stegano documentation | Contained in the Acme-Stegano distribution. |
Acme::Stegano - Put some text inside another
use Acme::Stegano;
# Create a stegano object passing a file you wish to inject
my $st = Stegano->new("my-file.txt");
$st->insert("This is a sample text");
# nearby in some other part of code, someone could
my $st = Stegano->new("my-file.txt");
print $st->extract
You can put some text inside another and it seems to remain the same. Then you could extract the text doing the inverse operation. The idea was from Damian Cownay in his Acme::Bleach.
Well, this is based in the idea of Damian Conway used in Acme::Bleach, so thank it to him.
Anarion: anarion@7a69ezine.org
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Acme-Stegano documentation | Contained in the Acme-Stegano distribution. |
# Anarion anarion@7a69ezine.org package Acme::Stegano; use strict; use warnings; use Tie::File; use Carp; use vars q/$VERSION/; $VERSION = '0.02';
sub new { my ($class,$filename) = @_; my @file; tie @file, 'Tie::File', $filename or croak "Cant tie filename $filename: $!"; bless \@file, $class } sub insert { my ($self,$text) = @_; my ($max_str,$max_cont,@map_letters) = (0,0); my $binstr = unpack "b*", " $text"; # It must begin with 0 $_ > $max_str and $max_str = $_ for map { length } @$self; while ($binstr =~ /((.)\2*)/g) { my $len = length($1); $max_cont = $len if $len > $max_cont; push(@map_letters,$len); } my @map_file = map { $max_str - length($_) > $max_cont } @$self; for (my $i=0;$i<@$self;$i++) { $self->[$i] .= " " x shift(@map_letters) if $map_file[$i] and @map_letters; } carp "Text is not enougth large to insert all chars" if @map_letters; return ! @map_letters; } sub extract { my $self = shift; my ($binstr,$i); for my $line (@$self) { $binstr .= ++$i % 2 ? 0 x length($1) : 1 x length($1) if $line =~ s/( +)$// } return substr(pack("b*", $binstr),1) # Delete our mark } 1;