views:

268

answers:

6

Hi, what i am trying to do is get the contents of a file from another server. Since im not in tune with perl, nor know its mods and functions iv'e gone about it this way:

 my $fileContents;
 if( $md5Con =~ m/\.php$/g ) {
     my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $@";
     $ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
     $ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
     open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
     $fileContents = <FILE>;
     close(FILE);
     unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
     $ftp->quit;
 }

What i thought id do is get the file from the server, put on my local machine, edit the content, upload to where ever an then delete the temp file.

But I cannot seem to figure out how to get the contents of the file;

open FILE, ">>c:/perlscripts/" . md5_hex($md5Con) . "-code.php" or die $!;
$fileContents = <FILE>;
close(FILE);

keep getting error;

Use of uninitialized value $fileContents

Which im guessing means it isn't returning a value.

Any help much appreciated.

>>>>>>>>>> EDIT <<<<<<<<<<

my $fileContents;
if( $md5Con =~ m/\.php$/g ) {
    my $ftp = Net::FTP->new($DB_ftpserver, Debug => 0) or die "Cannot connect to some.host.name: $@";
    $ftp->login($DB_ftpuser, $DB_ftppass) or die "Cannot login ", $ftp->message;
    $ftp->get("/" . $root . $webpage, "c:/perlscripts/" . md5_hex($md5Con) . "-code.php") or die $ftp->message;
    my $file = "c:/perlscripts/" . md5_hex($md5Con) . "-code.php";
    {
        local( $/ ); # undefine the record seperator
        open FILE, "<", $file or die "Cannot open:$!\n";
        my $fileContents = <FILE>;
        #print $fileContents;
        my $bodyContents;
        my $headContents;

        if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
            print $0 . $1 . "\n";
            $bodyContents = $dbh->quote($1);    
        }
        if( $fileContents =~ m/^.*<\/head>/gi ) {
            print $0 . $1 . "\n";
            $headContents = $dbh->quote($1);    
        }

        $bodyTable = $dbh->quote($bodyTable);
        $headerTable = $dbh->quote($headerTable);
        $dbh->do($createBodyTable) or die " error: Couldn't create body table: " . DBI->errstr;
        $dbh->do($createHeadTable) or die " error: Couldn't create header table: " . DBI->errstr;
        $dbh->do("INSERT INTO $headerTable ( headData, headDataOutput ) VALUES ( $headContents, $headContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
        $dbh->do("INSERT INTO $bodyTable ( bodyData, bodyDataOutput ) VALUES ( $bodyContents, $bodyContents )") or die " error: Couldn't connect to database: " . DBI->errstr;
        $dbh->do("INSERT INTO page_names (linkFromRoot, linkTrue, page_name, table_name, navigation, location) VALUES ( $linkFromRoot, $linkTrue, $page_name, $table_name, $navigation, $location )") or die " error: Couldn't connect to database: " . DBI->errstr;

        unlink("c:/perlscripts/" . md5_hex($md5Con) . "-code.php");
    }
    $ftp->quit;
}

the above using print WILL print the whole file. BUT, for some reason the two regular expresions are returning false. Any idea why?

if( $fileContents =~ m/<\s*body[^>]*>.*$/gi ) {
            print $0 . $1 . "\n";
            $bodyContents = $dbh->quote($1);    
        }
        if( $fileContents =~ m/^.*<\/head>/gi ) {
            print $0 . $1 . "\n";
            $headContents = $dbh->quote($1);    
        }
+3  A: 
open FILE, "c:/perlscripts" . md5_hex($md5Con) . "-code.php" or die $!;
while (<FILE>) {
    # each line is in $_
}
close(FILE);

will open the file and allow you to process it line-by-line (if that's what you want - otherwise investigate binmode). I think the problem is in your prepending the filename to open with >>. See this tutorial for more info.

I note you're also using regular expressions to parse HTML. Generally I would recommend using a parser to do this (e.g. see HTML::Parser). Regular expressions aren't suited to HTML due to HTML's lack of regularity, and won't work reliably in general cases.

Brian Agnew
im not wanting line by line just whole content.. will have a play
Phil Jackson
your above code seems to return the first line.
Phil Jackson
Your record separator may not match the file contents
Brian Agnew
have to use regular expression as im not just after HTML. PHP, HTML, JAVASCRIPT, JQUERY AND ASP. I try to split into head and body to analyse and then try to extract the serverside code, add placeholder and then see what content is able to be edited.
Phil Jackson
+2  A: 
sateesh
im really only after the content to upload to db. I will take a look.
Phil Jackson
I will generally turn that into a function vs inline code. But this is the approach I tend to use to slurp files
telesphore4
A: 

if you want to get the content of the file,

 @lines = <FILE>;
Dyno Fu
if you vote down, please leave a comment...
Dyno Fu
why people love verbose so much...
Dyno Fu
+1. The above is correct
Brian Agnew
+1 TIMTOWTDI shortly
YordanGeorgiev
Usually given as TMTOWTDI ("There's", not "There is"). But TMTOWTDI.
ysth
I would suspect people are voting down because the goal in this particular case is to have the whole file in one scalar, not separate lines in an array.
ysth
i just want to provide an alternative to solve the problem. (personally, if the answer is not totally irrelevant, or emotional, should not vote down. anyway people are free to vote what they think is wrong).
Dyno Fu
+8  A: 

Use File::Slurp if you want to read all file contents in one go.

However, more importantly, use an HTML parser to parse HTML.

Sinan Ünür
+8  A: 

This is covered in section 5 of the Perl FAQ included with the standard distribution.

How can I read in an entire file all at once?

You can use the File::Slurp module to do it in one step.

use File::Slurp;
$all_of_it = read_file($filename); # entire file in scalar
@all_lines = read_file($filename); # one line per element

The customary Perl approach for processing all the lines in a file is to do so one line at a time:

open (INPUT, $file) || die "can't open $file: $!";
while (<INPUT>) {
    chomp;
    # do something with $_
}
close(INPUT)        || die "can't close $file: $!";

This is tremendously more efficient than reading the entire file into memory as an array of lines and then processing it one element at a time, which is often—if not almost always—the wrong approach. Whenever you see someone do this:

@lines = <INPUT>;

you should think long and hard about why you need everything loaded at once. It's just not a scalable solution. You might also find it more fun to use the standard Tie::File module, or the DB_File module's $DB_RECNO bindings, which allow you to tie an array to a file so that accessing an element the array actually accesses the corresponding line in the file.

You can read the entire filehandle contents into a scalar.

{
local(*INPUT, $/);
open (INPUT, $file) || die "can't open $file: $!";
$var = <INPUT>;
}

That temporarily undefs your record separator, and will automatically close the file at block exit. If the file is already open, just use this:

$var = do { local $/; <INPUT> };

For ordinary files you can also use the read function.

read( INPUT, $var, -s INPUT );

The third argument tests the byte size of the data on the INPUT filehandle and reads that many bytes into the buffer $var.

Greg Bacon
+1  A: 

BUT, for some reason the two regular expresions are returning false. Any idea why?

. in a regular expression by default matches any character except newline. Presumably you have newlines before the </head> tag and after the <body> tag. To make . match any character including newlines, use the //s flag.

I'm not sure what your print $0 . $1 ... code is about; you aren't capturing anything in your matches to be stored in $1, and $0 isn't a variable used for regular expression captures, it's something very different.

ysth