How to Join Member's Area Private Library Search Today's Topics p Login
Main Forums Discussion Tech Talk Mature Content Archives
   Nav Win
 Tech Talk
 Beyond the Basics
 Grrr - Perl
 1 2 3 4 5 6 7 8 9
Follow us on Facebook

 Moderated by: Ron   (Admins )

 
User Options
Format for Better Printing EMail to a Friend Not Available
Admin Print Send ECard
Passions in Poetry

Grrr - Perl (Replace variables in Template)

 Post A Reply Post New Topic   Go to the Next Oldest/Previous Topic Return to Topic Page Go to the Next Newest Topic 
Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


0 posted 04-18-2002 12:18 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher


What am i doing wrong here? I basically modified this off one of my older scripts that i had working... and i can't for the life of me figure out why this isn't working??? I have all the permissions set properly... i can't find any missing semi-colons... all my braces match... *sigh*

Help! I thought i had a good handle on this... i know it's probably somethign really simple too. heh.

Chris
form: http://www.countlesshorizons.com/processforms/form.htm

perl:

#!/usr/local/bin/perl

$title = $input{'title'}; #title of poem
$author = $input{'author'}; #author's name
$lname = $input{'lname'}; #letter of alphabet to assign author (am or nz)
$submission = $input{'submission'}; #body of submission
$fileNumber = $input{'filenumber'}; #name of file
$prevNum = $fileNumber - 1; #insert file name to assign values
$nextNum = $fileNumber + 1; #insert file name to assign values
$authEmail = $input{'authemail'}; #author's email address


#Subroutines
&inputIn;
&header;
&writePage;

#subroutine to read and parse input and place into array
sub inputIn {
    if ($ENV{'REQUEST_METHOD'} eq 'GET')
    {$formInfo = $ENV{'QUERY_STRING'};}
    else
    {read(STDIN, $formInfo, $ENV{'CONTENT_LENGTH'});}
    @inputPairs = split (/[&;]/, $formInfo);
    %input = ();
    foreach $pair (@inputPairs) {
        $pair =~ s/\+/ /g;
        ($name, $value) = split (/=/, $pair);
        $name =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
        $value =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
        $input{$name} = $value;
        }
}

#Subroutine to write CGI Header for HTML page
sub header {
    print qq~Content-type: text/html\n\n~;
}

#imports template page and replaces variables
sub writePage {
open(TEMPLATE, 'templatepoems.htm');
@Page = <TEMPLATE>;
close(TEMPLATE);
    foreach $line(@Page) {
      $line =~ s/\*\*title\*\*/$title/;
      $line =~ s/\*\*author\*\*/$author/;
      $line =~ s/\*\*lname\*\*/$lname/;
      $line =~ s/\*\*submission\*\*/$submission/;
      $line =~ s/\*\*filenumber\*\*/$fileNumber/;
      $line =~ s/\*\*prevnum\*\*/$prevNum/;
      $line =~ s/\*\*nextnum\*\*/$nextNum/;
      $line =~ s/\*\*authemail\*\*/$authEmail/;
      print $line;
    }
}


template:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
**title**<br>
**author**<br>
**lname**<br>
**submission**<br>
**filenumber**<br>
**prevnum**<br>
**nextnum**<br>
**authemail**<br>
</body>
</html>
Ron
Administrator
Member Rara Avis
since 05-19-99
Posts 9708
Michigan, US


1 posted 04-18-2002 05:37 PM       View Profile for Ron   Email Ron   Edit/Delete Message      Find Poems   Click to visit Ron's Home Page   View IP for Ron

I haven't had the chance to look at the link to see what it's doing, and you didn't give any indication of what it's not doing, but I'm going to take a quick guess. If this doesn't help, I'll try to find time to look more deeply later.

My first glace suggests you're trying to use variable before they've been filled? The very first line of the script is assigning $title from the %input hash, but there's absolutely no way that hash can have anything in it yet. Put your call to the inputln routine above the assignments instead of below.

Better yet - don't fill two variable for the same job. Change your regular expressions to use the hash. For example

$line =~ s/\*\*title\*\*/$input{'title'}/;

will save a completely useless assignment. Make sense?

If that doesn't help, I'll be back after dinner.
Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


2 posted 04-18-2002 06:13 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher

actually that DOES make complete sense (both, cutting down the work, but especially the point at which the variables are being called)

what it's NOT doing, is not filling in the text as it should... not being defined would fit exactly what it's doing....

heh

i will try this when i get home tonight ron - thank you, as always, for your help... and... uhmm... if you DO get some free time (hahahah) or at least the inclination, would you mind a quick run through on how i might be able to have the output of this file saved to my server?

peace

Chris
Ron
Administrator
Member Rara Avis
since 05-19-99
Posts 9708
Michigan, US


3 posted 04-18-2002 10:11 PM       View Profile for Ron   Email Ron   Edit/Delete Message      Find Poems   Click to visit Ron's Home Page   View IP for Ron

Well, on one hand, saving the information to disk is simple. Concatenate the variables together, open a file for appending, write one line to the file, close the file.

Using the tilde char as your field delimiter, it might look like this:

$dataline = "$title~$author~$lname~$submission";
open(LOGS,">>path/file.log "); # append operation
print LOGS "$dataline\n";
close(LOGS)

Piece of cake. Unfortunately, there's always that other hand waiting around to spoil the simplicity.  

In a multi-user environment, you need to make sure two visitors aren't hitting the disk file at the same exact moment, so you need a file locking mechanism. You also need to make sure your delimiter (the tilde in this case) isn't included as text in any of your variables, or you'll have the wrong number of "fields" in that line. And because you're writing the data as a single line (record) in the text file, you'll need to make sure there's no line breaks in the data, too.

The last two are simple substitutions, but the locking mechanism takes a bit more. I use a couple of subroutines to do it.

# lock and unlock routines rely on SYMLINK and therefore a
# non-existant file can not be locked
sub GetLock {
  my $file_name = $_;
  my ($i);

  ## try several times, waiting a second in between
  for ($i = 1; $i <= 10; ++$i) {
    ## true if the lock file was created
    if ( symlink ($file_name, "$file_name.lock") ) {
      return 1;        # success!
    }
    sleep 1;
  }
  &FATAL("Could not get lock on $file_name<br>$file_name.lock");
  return 0;                # failure :-(
}

sub DropLock {
  my ($file_name) = $_;
  unlink ("$file_name.lock");
}

I make the necessary subsitutions in my input routine, what you're calling inputln. That's because there are a LOT of other substitutions you should make in order to protect the security of your system. A very common hacking trick is to type a OS command as data in a form and then hope the script passes it to the system. To protect ourselves, we need to test for that before doing anything else with the form data. Inside the foreach loop, just before you assign $value to the hash, I would do something like this:

# remove potentially dangerous commands that should never
# be passed to any Unix process (like sendmail)
$value =~ s/\0//g;
$value =~ s/system\(.+//g;
$value =~ s/grep//g;
$value =~ s/\srm\s//g;
$value =~ s/\srf\s//g;
$value =~ s/\.\.([\/\:]|$)//g;
$value =~ s/< *((SCRIPT)|(APPLET)|(EMBED))[^>]+>//ig;
# disable all HTML commands (I'm including spaces so it'll show here)
$value =~ s/</& lt;/g;
$value =~ s/>/& gt;/g;
$value =~ s/~/& #0124;/sg; # protect our delimiter
$value =~ s/\n/< br>/g; # convert line breaks

So now, our "simple" write to disk should look something like this:

$dataline = "$title~$author~$lname~$submission";
&GetLock("path/file.log");
open(LOGS,">>path/file.log "); # append operation
print LOGS "$dataline\n";
close(LOGS)
&DropLock("path/file.log");

Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


4 posted 04-18-2002 10:28 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher

worked perfectly fine - thank you so much for your patience Ron.

NOW -

if you have time, or inclination, i have a few other questions. i'll be trying to find the answers to these as well in my books, but thought i'd pose them in case you had any input:

1. re: above - saving file to server (a raw guess is something to do with STDOUT...)

2. i want to eliminate a space between the characters in a string... oh... i think i may have got it. maybe using something along the lines of: $variable =~ s/\%%20(i don't know what character to use here to represent the space)//g;

3. format a number properly - ie: in above examples, $filenumber comes out as a 6-digit number, but $prevNum and $nextNum comes out as a two or three digit number, skipping all the leading zeros.

okies... that should do for now, thoguh of course there's lots more later. heh.

thanks again Ron

Chris
Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


5 posted 04-18-2002 10:32 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher

heh


of course it's not simple!!!

you replied in the (long) time it took me to write my last reply (bouncing back and forth between book and screen... can't seem to find what represents the space character)

looks good, and i was just reading about the security issues today - thank you for that snippet.

does writing a new "htm" file work along the same lines? i would imagine it does... looks like i'm in for some testing!

will come back to this after playing a little bit - this is still so fun!

Chris
Ron
Administrator
Member Rara Avis
since 05-19-99
Posts 9708
Michigan, US


6 posted 04-19-2002 01:05 AM       View Profile for Ron   Email Ron   Edit/Delete Message      Find Poems   Click to visit Ron's Home Page   View IP for Ron

1. Writing files - yea, writing an HTML files is basically the same. Except you rarely have to lock them, and you do NOT want to append as I indicated for the data files (change the >> to a single > to create or re-create a file).

To write any file, remember that you have to have permission to do so. That usually means setting up a directory with write permissions before running the script.

2. Eliminating spaces - you have the right idea, but you don't have to "represent" a space with any special code. $variable =~ s/ //; will work fine.

3. Formatting fixed width numbers - this one requires a bit of a kludge. The function sprintf exists so we can print columns of numbers and make sure they line up correctly. It does its job by adding spaces to the beginning of numbers, but we can easily use a regexp to change those leading spaces into leading zeroes.

$number = 17;
$number = sprintf("%5d", $number);
$number =~tr/ /0/;

The result would be 00017
Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


7 posted 04-20-2002 05:38 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher

OK - all that is good! i even figured out a few things on my own (like how to turn all the letters in a string to lower case and how to retrieve just the first letter!!!)

HOWEVER - I am having problem with file permissions... how do i tell the program that i want to do this: ../../processforms/$filename   ? I tried it using escape characters (see following, but it's not working???)

hmm... will keep working at it. Thanks again Ron

Have:

open(FILE,">$dir..\/..\/\/processforms\/$fileNumber.htm") ||
die "Can't create index file $fileNumber: $!\n\n";

Get:

Can't create index file 00021: No such file or directory
Christopher
Moderator
Member Rara Avis
since 08-02-99
Posts 9130
Purgatorial Incarceration


8 posted 04-20-2002 05:39 PM       View Profile for Christopher   Email Christopher   Edit/Delete Message      Find Poems  View IP for Christopher

and i DO have all my permissions set to read write and execute (just in case at this point)
Ron
Administrator
Member Rara Avis
since 05-19-99
Posts 9708
Michigan, US


9 posted 04-20-2002 06:16 PM       View Profile for Ron   Email Ron   Edit/Delete Message      Find Poems   Click to visit Ron's Home Page   View IP for Ron

Hard to say for sure what's happening, Chris, but the path in your open statement looks, uh, a little strange. How can you have a variable ($dir) in front of the parent dir symbols (double dots)?

The best thing is usually to assign your entire open parameter to a variable, and then print that in your die clause.

my $openPath = "$dir..\/..\/\/processforms\/$fileNumber.htm";
open(FILE,">$openPath ") || die "Can't create index file $openPath: $!\n\n";
 
 Post A Reply Post New Topic   Go to the Next Oldest/Previous Topic Return to Topic Page Go to the Next Newest Topic 
All times are ET (US) Top
  User Options
>> Tech Talk >> Beyond the Basics >> Grrr - Perl Format for Better Printing EMail to a Friend Not Available
Print Send ECard

 

pipTalk Home Page | Main Poetry Forums

How to Join | Member's Area / Help | Private Library | Search | Contact Us | Today's Topics | Login
Discussion | Tech Talk | Archives | Sanctuary



© Passions in Poetry and netpoets.com 1998-2013
All Poetry and Prose is copyrighted by the individual authors