Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

evaling code stored in database

by mhearse (Chaplain)
on Jan 11, 2011 at 04:26 UTC ( [id://881587]=perlquestion: print w/replies, xml ) Need Help??

mhearse has asked for the wisdom of the Perl Monks concerning the following question:

I'm having trouble eval ing stored code. I don't think I'm storing/escaping it correctly. Can someone offer help?
#!/usr/bin/perl # A true Ruth Goldberg contraption. use strict; use DBI; use File::Path qw(mkpath); use Digest::MD5 qw(md5_hex); ### Connect to sqlite database. Sqlite handles ### locking for us. my $dbh = DBI->connect( "dbi:SQLite:/home/bittorrent/bittorrent.db", "","", { RaiseError => 0, AutoCommit => 1 } ); my %queries; my @tables; $queries{bittorrent} = <<EOQ; create table bittorrent ( id integer primary key asc, mainSite varchar(50) not null, torrentSite varchar(50) not null, torrentFile varchar(50) not null, torrentPattern varchar(50) not null, code varchar(500), unique( mainSite ) ) EOQ push @tables, "bittorrent"; $queries{bittorrentCheckSums} = <<EOQ; create table bittorrentCheckSums ( id integer primary key asc, checkSum varchar(100) not null, unique( checkSum ) ) EOQ push @tables, "bittorrentCheckSums"; $queries{checkTableExistence} = $dbh->prepare(<<EOQ); select name from sqlite_master where name = ? EOQ { for my $table (@tables) { my $q = $queries{checkTableExistence}; $q->execute($table); my $rec = $q->fetchrow_hashref(); if (! $rec->{name}) { $dbh->do($queries{$table}); } } } $queries{insertBittorrent} = $dbh->prepare(<<EOQ); insert into bittorrent ( mainSite, torrentSite, torrentFile, torrentPattern, code ) values (?, ?, ?, ?, ?) EOQ $queries{insertBittorrentCheckSum} = $dbh->prepare(<<EOQ); insert into bittorrentCheckSums( checkSum ) values ( ? ) EOQ $queries{selectBittorrent} = $dbh->prepare(<<EOQ); select * from bittorrent EOQ $queries{selectBittorrentCheckSum} = $dbh->prepare(<<EOQ); select 1 as bool from bittorrentCheckSums where checkSum = ? EOQ { my $q = $queries{insertBittorrent}; $q->execute( 'http://www.slackware.com', 'getslack/torrents.php', 'torrents.php', 'install-dvd',' if (\\$line =~ /href="(.*)"/) { print "Fetching torrent file: \\$mainSite/\\$1.\\n"; system qq{wget "\\$mainSite/\\$1"}; } ' ); $q->execute( 'http://www.debian.org', 'CD/torrent-cd', 'index.html', 'bt-dvd',' my \$subSite; my \@releases = split /\]/, \$line; for my \$release (\@releases) { if (\$release =~ /(i386|amd64)/) { if (\$release =~ /href="(.*)"/) { \$subSite = \$1; system qq{wget "\$1"}; open FILE, "index.html.1"; while (my \$line1 = <FILE>) { chomp \$line1; if (\$line1 =~ /torrent/) { if (\$line1 =~ /href="(.*)"/) { system qq{wget "\$subSite/\$1"}; } } } } } } ' ); } my $q = $queries{selectBittorrent}; $q->execute(); while (my $rec = $q->fetchrow_hashref() ) { my $mainSite = $rec->{mainSite}; my $torrentSite = $rec->{torrentSite}; my $torrentFile = $rec->{torrentFile}; my $torrentPattern = $rec->{torrentPattern}; my $code = $rec->{code}; my $homeDir = "/home/bittorrent"; my $tmpDir = "tmp.$$"; if (! -d $homeDir ) { print "Making $homeDir.\n"; mkpath($homeDir, 0, 0077); } print "Entering $homeDir.\n"; chdir $homeDir; if (! -d $tmpDir ) { print "Making $tmpDir.\n"; mkpath($tmpDir, 0, 0077); } print "Entering $tmpDir.\n"; chdir $tmpDir; print "Fetching $mainSite torrent page.\n"; system qq{wget "$mainSite/$torrentSite"}; open FILE, $torrentFile; while (my $line = <FILE>) { chomp $line; if ($line =~ /$torrentPattern/) { eval $code or die $!; } } my @torrentFiles; open CMD, "ls *torrent |"; while (my $line = <CMD>) { chomp $line; push @torrentFiles, $line; } close CMD; MSTR_LOOP: for my $torrent (@torrentFiles) { print "Checking to see if we already have this release: $torre +nt\n"; my $digest = md5_hex($torrent); my $q = $queries{selectBittorrentCheckSum}; $q->execute($digest); my ($bool) = $q->fetchrow_array(); if ($bool) { print "\nLooks like we already have this release, skipping +: $torrent\n"; next MSTR_LOOP; } print "Looks like we don't have this release, downloading it: +$torrent\n"; system qq{transmissioncli -ep --download-dir $homeDir/$tmpDir + --uplimit number 0 --config-dir $homeDir/$tmpDir $torrent &}; while (1) { sleep 15; my $cntr = 1; my @results; open CMD, "transmission-remote --list |"; while (my $line = <CMD>) { chomp $line; next if ($cntr++ != 2); @results = split /\s+/, $line; } close CMD; if ($results[5] eq "Done") { print "\n\nStopping transmissioncli.\n"; system "transmission-remote -t 1 -S &"; my $q = $queries{insertBittorrentCheckSum}; $q->execute($digest); next MSTR_LOOP; } } } }

Replies are listed 'Best First'.
Re: evaling code stored in database
by ELISHEVA (Prior) on Jan 11, 2011 at 05:37 UTC

    What are you doing to eval the code? I don't see the word eval anywhere in the posted script. Is this the code you are trying to eval? Or are you refering to your attempt to insert code into the database in what looks like code samples at the end of each of your "execute" calls?

    If the entire script is what you are eval'ing, as a first step make sure the script works without escaping or quoting when placed in a file and run as a normal script. I suspect it doesn't even compile. One you get it to compile, if you still have trouble, come back. However, post the code you use to eval the script, not the script itself. Without knowing what you are doing to "eval", we can't even begin to troubleshoot with you.

    If, what you mean by "eval" is that you are having trouble passing in the code samples as the final line of each call to execute, I don't see any starting or ending quotes around those code samples. Perl is reading that as part of your script and not as a string of code to pass to bit-torrent. You need to consruct a string containing the code and then pass the the string to your execute call, e.g.

    #This string is single quoted with q{...} so you don't # need to "escape" parenthesis or dollar signs # Also you can nest q{...}, but not '....'. so it is more # reliable my $sCode=q{ if ($line =~ /href=\"(.*)\"/) { print "Fetching torrent file: $mainSite/$1.\n"; system qq{wget "$mainSite/$1"}; } }; # alternatively, you can use a here doc with the end tag # in single quotes. Putting '...' around the end tag tells # perl to treat all of the text within verbatim so there is # no need to escape individual characters $sCode=<<'EOF'; if ($line =~ /href="(.*)") { print "Fetching torrent file: $mainSite/$1.\n"; system qq{wget "$mainSite/$1"}; } EOF # run command with _string_ variable containing code my $q = $queries{insertBittorrent}; $q->execute( 'http://www.slackware.com', 'getslack/torrents.php', 'torrents.php', 'install-dvd',' $sCode);
Re: evaling code stored in database
by jwkrahn (Abbot) on Jan 11, 2011 at 07:41 UTC
    mkpath($homeDir, 0, 0077); chdir $homeDir; mkpath($tmpDir, 0, 0077); chdir $tmpDir; system qq{wget "$mainSite/$torrentSite"}; open FILE, $torrentFile; open CMD, "ls *torrent |"; close CMD; system qq{transmissioncli -ep --download-dir $homeDir/$tmpDir + --uplimit number 0 --config-dir $homeDir/$tmpDir $torrent &}; open CMD, "transmission-remote --list |"; close CMD; system "transmission-remote -t 1 -S &";

    You should ALWAYS verify that these system calls performed correctly before trying to use code that relies on their results.



    if (! -d $homeDir ) { print "Making $homeDir.\n"; mkpath($homeDir, 0, 0077); } print "Entering $homeDir.\n"; chdir $homeDir; if (! -d $tmpDir ) { print "Making $tmpDir.\n"; mkpath($tmpDir, 0, 0077); } print "Entering $tmpDir.\n"; chdir $tmpDir;

    Why not just use one step:

    unless ( -d "$homeDir/$tmpDir" ) { print "Making $homeDir/$tmpDir.\n"; my $err; eval { mkpath "$homeDir/$tmpDir", { verbose => 0, mode => 0077, e +rror => \$err }; }; if ( $@ or @$err ) { die "mkpath failed because: ", $@ || @$err; } } print "Entering $homeDir/$tmpDir.\n"; chdir "$homeDir/$tmpDir" or die "Cannot chdir to '$homeDir/$tmpDir +' because: $!";


    eval $code or die $!;

    The $! variable will not have any useful information from eval.    You need to use the $@ variable instead.



    my @torrentFiles; open CMD, "ls *torrent |"; while (my $line = <CMD>) { chomp $line; push @torrentFiles, $line; } close CMD;

    Or just:

    my @torrentFiles = glob '*torrent';

Re: evaling code stored in database
by Corion (Patriarch) on Jan 11, 2011 at 07:47 UTC
Re: evaling code stored in database
by ikegami (Patriarch) on Jan 11, 2011 at 05:48 UTC
    It would be simpler to place the code snippets into subs and place the name of the subs in the database.
Re: evaling code stored in database
by educated_foo (Vicar) on Jan 11, 2011 at 05:28 UTC
    If you want help, you should probably not just post a hundred-line script. If you want someone to do your work for you, you should ask on Rentacoder.
Re: evaling code stored in database
by scorpio17 (Canon) on Jan 11, 2011 at 15:08 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://881587]
Approved by planetscape
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2024-04-25 20:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found