Link to home
Start Free TrialLog in
Avatar of idadan
idadan

asked on

simple prob. for an expert...

I get a server error when i run this and sometimes nothing at all. It get sent 3 variables
                     -probnum -lastprob and -question It's sent with method="post" and action="algebra.cgi?new" I
                     think that's ok but i don't have access to server error logs or command line. If anyone has
                     access to command line they could just use perl's -d command ... anyway any help would be
                     greatly appreciated. Or if you think of a better way to do what i'm doing i'll boost the points to
                     400. Thanks. Any question just post. here's the url to the 1st page the place where you ask the
                     question http://www.tiac.net/users/rkeir/EAT/addnew.html Oh, also everything is chmod to
                     755.

                     #!/usr/bin/perl

                     #########################################################
                     # #
                     #########################################################

                     #global variables
                     $frontreal = "/xlv0/web/rkeir/EAT/algfake.html";
                     $front = "/EAT/algfake.html";


                     if($ENV{'QUERY_STRING'} eq "new"){
                     &parse_form;
                     &get_variables;
                     &add_part;
                     &show_new;
                     }

                     ############
                     #Parse Form#
                     ############
                     sub parse_form {

                        # Get the input
                         read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

                        # Split the name-value pairs
                        @pairs = split(/&/, $buffer);

                        foreach $pair (@pairs) {
                         ($name, $value) = split(/=/, $pair);

                         # Un-Webify plus signs and %-encoding
                         $value =~ tr/+/ /;
                         $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
                         $value =~ s/<!--(.|\n)*-->//g;

                         $value =~ s/<([^>]|\n)*>//g;
                         $FORM{$name} = $value;
                         }
                     }

                     ###############
                     #Get variables#
                     ###############

                     sub get_variables {

                      if ($FORM{'probnum'}) {
                         $probnum = $FORM{'probnum'};
                         }
                      if ($FORM{'lastprob'}) {
                         $lastprob = $FORM{'lastprob'};
                         }
                      if ($FORM{'qustion'}) {
                         $question = $FORM{'question'};
                         }
                     }


                     ##########
                     #Add part#
                     ##########
                     sub add_part {
                     open (FILE,"$frontreal") || die "Can't Open $frontreal: $!\n";
                     @LINES=<FILE>;
                     close(FILE);
                     $SIZE=@LINES;
                     open (STORY,">$frontreal") || die "Can't Open $frontreal: $!\n";
                     for ($i=0;$i<=$SIZE;$i++) {
                        $_=$LINES[$i];
                        if (/<!--$lastprob-->/) {
                         
                         print STORY "$question\n";
                         print STORY "<!--$probnum-->\n";
                         }
                     }
                         print STORY $_;
                     close (STORY);

                     print "Location: ",$front,"\n\n";
                     1;
                     }



  2.Question history:

          Comment from
          ozo...
                      calling it with lastprob="**)((" can cause a server error
                      if /xlv0/web/rkeir/EAT/algfake.html is unreadable by the server, that could cause an error
                      if you call it twice at the same time, you might destroy /xlv0/web/rkeir/EAT/algfake.html
          Comment from
          idadan...
                      Well it's a little different than that... Let me explain it a tad more. These are the variables i'm giving it from the html page- probnum is "problem2"
                      lastnum is "problem1" and question is just text. What i'm (trying to do) above is have it look for a hidden comment <!--$lastprob--> (which is
                      problem1) and after that put $question (just some text). It closes by writing <!--$probnum--> so next time i go to do this same process it's the same
                      with different numbers. Here's the script i'm basing it off of. The rest of this script is just non-relavant sub routines.

                      #!/usr/bin/perl

                      # Jackanory V1.0
                      # Created by Steve Coulson http://www.netlink.co.uk/users/avid-eye 
                      # Created on 7th June 1996
                      #
                      # Script based on Guestbook for the World Wide Web
                      # Created by Matt Wright Version 2.3.1
                      # Created on: 4/21/95 Last Modified: 10/29/95
                      #
                      # THIS FILE MUST BE CHMOD 775

                      #############################################################################
                      # Set Variables

                      $storybookurl = "http://www.tiac.net/users/rkeir/EAT/story.html";
                      $storybookreal = "/xlv0/web//rkeir/EAT/story.html";
                      $cgiurl = "http://www.tiac.net/users/rkeir/EAT/jackanory.cgi";
                      $recipient = 'idadan@tiac.net';
                      $incremfile = "/xlv0/web//rkeir/EAT/increm.txt";
                      $storyname = 'My school';
                      $storydesc = 'Can it get any worse?';
                      $mailprog = '/usr/sbin/sendmail';
                      $date_command = "/usr/bin/date";

                      # Set Your Options:

                      $mail = 0; # 1 = Yes; 0 = No - Mails you a copy of story additions
                      $remote_mail = 0; # 1 = Yes; 0 = No - Mails a thankyou to the submitter



                      # Done
                      #############################################################################


                      # Get the Date for Entry
                      $date = `$date_command +"%A, %B %d, %Y"`; chop($date);

                      # Get the input
                      read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

                      # Split the name-value pairs
                      @pairs = split(/&/, $buffer);

                      foreach $pair (@pairs) {
                         ($name, $value) = split(/=/, $pair);

                         # Un-Webify plus signs and %-encoding
                         $value =~ tr/+/ /;
                         $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
                         $value =~ s/<!--(.|\n)*-->//g;
                         $value =~ s/<([^>]|\n)*>//g;

                         $FORM{$name} = $value;
                      }


                      # allow special characters and paragraphs

                         if ($FORM{'comments'}) {
                          $body = "$FORM{'comments'}";
                          $body =~ s/\cM//g;
                          $body =~ s/\n\n/<p>/g;
                          $body =~ s/\n/<p>/g;

                          $body =~ s/&lt;/</g;
                          $body =~ s/&gt;/>/g;
                          $body =~ s/&quot;/"/g;
                         }
                         else {
                          &no_comments;
                         }

                      # Print the Blank Response Subroutines if no name entered

                      &no_name unless $FORM{'realname'};

                      # get author number

                         open(INCREM,"$incremfile") || die $!;
                         $increm = <INCREM>;
                         $increm++;
                         close(INCREM);
                         

                      # Begin the Editing of the Story
                      open (FILE,"$storybookreal") || die "Can't Open $storybookreal: $!\n";
                      @LINES=<FILE>;
                      close(FILE);
                      $SIZE=@LINES;


                      # Open Link File to Output
                      open (STORY,">$storybookreal") || die "Can't Open $storybookreal: $!\n";


                      for ($i=0;$i<=$SIZE;$i++) {
                         $_=$LINES[$i];
                         if (/<!--addstory-->/) {
                         
                         
                          print STORY "$body <a href=\"#$increm\"><font size=-1>$increm<\/font><\/a>\n";
                          print STORY "<!--addstory-->\n";
                          }

                         else {
                          if (/<!--addauthor-->/) {
                          print STORY "<a name=\"$increm\">$increm. <\/a>$FORM{'realname'}";
                          if ($FORM{'username'}) {
                          print STORY " <a href=\"mailto:$FORM{'username'}\">($FORM{'username'}<\/a>) from IP $ENV{'REMOTE_HOST'} on $date.<br>\n";
                          print STORY "<!--addauthor-->\n";
                          }
                          else {
                          print STORY " from IP $ENV{'REMOTE_HOST'} on $date.<br>\n";
                          print STORY "<!--addauthor-->\n";
                          }
                          }
                          else {
                          print STORY $_;
                          }
                         }
                      }


                         open(INCREM,">$incremfile") || die $!;
                         print INCREM "$increm";
                         close(INCREM);

                      close (STORY);
Avatar of idadan
idadan

ASKER

sorry for the messed up appearance up top its actually ozo comment too and my response after the first question.
ASKER CERTIFIED SOLUTION
Avatar of icd
icd

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Checking further, I found no sign of the file algfake.html which I expected to find at URL.

http://www.tiac.net/users/rkeir/EAT/algfake.html

I could not verify your path to the file

$frontreal = "/xlv0/web/rkeir/EAT/algfake.html";

You might do better with a relative path, such as:-

$frontreal = "../docs/algfake.html";

(Or something like it, depending upon the directory layout of your server root directories).


Avatar of idadan

ASKER

Thanks for help so far.  Couple things have turned up.  First when i run the script before i changed the part you told me it wouldn't come back with response but would edit the file BUT all that was left on algfake was <!--problem3--> at the top.  Here are the urls of the parts.
ALGEBRA.CGI- http://www.tiac.net/users/rkeir/EAT/algebra.txt
ALGFAKE.HTML- http://www.tiac.net/users/rkeir/EAT/algfake.html

This is the current versions of both and your welcome to try on your machine changing paths to your machine!  All files are under this directory.  All the paths are correct to my knowlage and both were chmod correct.  Any other questions please post.
You have several problems here.

First the script does not output any data so that when it runs you (probably) get an error message 'document contains no data'.
To fix this I have changed some of your code like so:-

if($ENV{'QUERY_STRING'} eq "new"){
      print "Content-type: text/html\n\n"; # ***
      print "<HTML><HEAD></HEAD><BODY>\n"; # ***
      &parse_form;
      &get_variables;
      &add_part;
      &show_new;
      print "</BODY></HTML>\n"; # ***
}

This will output a default html document. Anything you then print in the body of your code will be displayed. For example, I changed your open statement back to:-

open (STORY,">$frontreal.tmp") || die "Can't Open $frontreal.tmp: $!\n";

because it will now print correctly (and so will all the other 'die' statements).

You had a typo on the following line:-
 if ($FORM{'question'}) {
(you had missed out the 'e'.

At the end of the subroutine 'get_variables' I put in some diagnostic code:-

print "probnum = $probnum<br>\n";
print "lastprob = $lastprob<br>\n";
print "question = $question<br>\n";

This showed me that your code:-

if (/<!--$lastprob-->/) {

should have been:-

if (/<!--problem$lastprob-->/) {

I also changed your second open statement to:-

open (STORY,">$frontreal.tmp") || die "Can't Open $frontreal.tmp: $!\n";

In general when re-writing a file I prefer to do the following:-

1. Open 'file.tmp' for output
2. Write to 'file.tmp'
3. Close 'file.tmp'
4. Rename 'file' to 'file.bak'
5. Rename 'file.tmp' to 'file'

This means the window during which the file does not exist is very small and that you always have a backup of the file prior to the change (in case things go wrong).

The reason your file was empty was that the print statement that writes to the file was outside the 'for' loop.
I changed the loop I moved it back inside like so:-

      for ($i=0;$i<=$SIZE;$i++) {
            $_=$LINES[$i];
            print STORY $_;

A more serious problem is understanding what you want your program to do.

1. Do you only want to be able to add a new problem at the end of the file? (In which case the code could be simpler, just look for a marker at the end <!-END->).

2. Do you just want to 'overwrite' existing problems.

3. Do you want to insert new problems between others, in which case you will need to renumber the existing problems.

No. 1 is the easiest. If you are writing this script as an exercise in programming then I suggest you start with this one. Your script is close to being able to do this at the moment with only slight changes.

No. 2 is slightly more difficult. You need to detect both the start of the code for the problem (with your <!-problemX-> marker) and the end. I suggest every problem section ends with another marker such as <!-endX->)

No. 3 is the most difficult, but not much more so. Having inserted a new problem at the appropriate point you need to find each <!-problemX-> marker and increment the value of X by one before re-writing that line.

Let me know what you want to do now.

If you are having problems testing scripts I suggest that (if you have a PC) you install Microsoft Personal/Peer Web Server (PWS) and perl. This will enable you to test your scripts locally with the minimum of fuss.
Avatar of idadan

ASKER

Sorry for the delay but things are definitely going better.  The script is writing to the file but in between problem number 1 and 2.  It still doesn't return anything to the browser, it just sits there acting busy but at least its writing to the file. I updated the files on my server (algebra.txt reflects algebra.cgi in txt form) url is above for that.  About changing <!--lastprob--> to <!--problem$lastprob--> I was just entering (on the html form page) where it asked for problem number "problem2" or "problem3" my bad for not telling you that.  I changed all the things you asked except that I think and about 1,2,3 method question.  All it needs to do is add at the end of the file so i guess that's easier.  Also how do you install cgi for personal web server?  If it's complicated don't bother but i was just wondering if its easy.  Thanks alot for all your help.  You can view 2 sample problems i put into algfake.html at its url.  you can add a problem if you want to try.  here are all the urls of stuff again.
Actual CGI script http://www.tiac.net/users/rkeir/EAT/algebra.cgi
Form to add- http://www.tiac.net/users/rkeir/EAT/addnew.html
Output html file http://www.tiac.net/users/rkeir/EAT/algfake.html
Txt version of CGI http://www.tiac.net/users/rkeir/EAT/algebra.txt

Thanks again.  Any question just post.
PWS automatically allows cgi, all you need to do then is to install a cgi language, such as perl, neither is difficult to install. There is one little issue with this which requires a change to the registry but if you decide to install pws and perl I will answer that issue for you for free.

Since you only ever want to insert at the end then I would do away with the request for the problem number and last number and insert a tag <!-INSERT HERE-> after the last question in algfake.html. Then you can change your main loop code to:-

for ($i=0;$i<=$SIZE;$i++) {
   $_=$LINES[$i];
   if (/<!-INSERT HERE->/) {
        print STORY "$question\n";
        }
   print STORY $_;
}
close (STORY);

Note that when the INSERT HERE tag is found the question is inserted before the tag is re-written. The tag is then in the correct position for the next question to be inserted.

Avatar of idadan

ASKER

The script is still messed in two parts.  First its still not sending any response back to the browser.  It does the work but doesn't respond.  And secondly it writes to 2 places in the file.  It writes to the begaining and the middle still.  You should view algfake.html source before trying to add a part and see that the insert here tag is in the right place.  then goto addnew.html and add some question.  Hit stop after a minute and go back to algfake.html to see.  It seems to move the tag too.  Anyway, I already have PWS installed but don't have perl installed.  If you could give me a url where i could get it and the registry change i would greatly appreciate it.  Thanks and i bumped up the points . :)
Avatar of idadan

ASKER

Oh by the way if you want to change how it writes to the file thats fine.  I know you said it was better doing it a different way.  Doesn't matter to me, but then again your're the expert.
You can get perl from the ActiveState web site. The URL is

http://www.ActiveState.com/software/default.htm

Run regedit and look for the following entry.
   MyComputer\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3Svc\Parameters\Script

    map

  you need an entry for .pl with the value
  "c\perl\bin\perl.exe %s %s" (or equivalent path)

  The main point being the two %s value (although only one can also work)

  You also need to ensure that the directory running the scripts is set up to be executable using the
  administration page of PWS
 
I have rewritten the script, but rather than try and post it here where the formatting gets screwed up I will email it to you separately (to idadan@tiac.net).

Avatar of idadan

ASKER

Thanks but there are 3 last problems.  I'll go biggest to smallest.
1.  Everytime the script runs it changes the permissions on algfake.html to 553.  This makes it so I can't change the permissions myself or upload it (I use ftp).  I talked to the webmaster at tiac and he's not sure why.  Can you change the way it writes to the way it used to be?  I have no idea how to fix that problem otherwise...
2.  I need to add some html part to it when it writes.  You'll see what I mean if you take a look at what i changed.  goto algebra.txt to see.  It prints "&html_part" on algfake.html instead of executing it.  I know thats my fault and just some perl syntax.  I'm trying to learn perl, like you couldn't tell.
3.  I need it to print the "Problem _" whatever problem number it is above it and a link to that problem number.  check out the algebra.txt to see.

Thanks alot if all these get fixed you're getting an A++!  Thanks a lot if you ever need free advertising at my site let me know, if you have a site.


1. This depends upon some default condition or other for the account used by the server. I have a similar problem on my own web site and I don't know the underlying reason for it either.

You can fix it however by using the 'chmod' function. At the end of 'add_part', after the two 'rename's you should add the line.

chmod 0777, "$frontreal";

2. The 's'ubstitute command takes a PATTERN and a REPLACEMENT string. It does not automatically evaluate to a function although it will do substitutions. Your function call therefore is being ignored. You need to make several modifications to do this.

a). Change your substitution to:-

s/<!-INSERT HERE->/&html_part/e;

This tells it to evalutate the replacement part as an expression, rather than a string.

b). Change the function 'html_part' to return a string rather than print it. (Although printing 'might' work as well).

sub html_part {
  my $retStr;

  $retStr = "<table border=\"0\" width=\"13%\" align=\"LEFT\" bgcolor=\"#66CCFF\">\n";
  $retStr .= "<tr><td><b><font face=\"Courier New, Courier, mono\">$probnum</font></b></td>\n";

  ... etc. Some code omitted here (you can see the pattern).

$retStr .= "<font face=\"Arial,Helvetica, sans-serif\"  size=\"+1\"><a href=\"http://www.tiac.net/users/rkeir/EAT/prob $litnum anw.html\">\n";
$retStr .= "Click here for the answer</a></font></p>\n";
$retStr .= "<!-INSERT HERE->";         # Don't miss this bit!
}

3. I don't quite see what you are having a problem with here. Sort out the above problems and see if it now does what you want.

Avatar of idadan

ASKER

Still having problems with permissions its late and i will try to get back to you tommorow night and update you. 1/13/98.
There is a unix command 'umask' that you can run at the start of your script that will set the default file permissions for any file that is created. This is part of the 'man' pages for umask.

     The user file-creation mode mask is set to ooo.   The  three
     octal  digits  refer  to  read/write/execute permissions for
     owner,  group,  and  other,  respectively   (see   chmod(1),
     chmod(2),  and umask(2)).  The value of each specified digit
     is subtracted from the corresponding ``digit'' specified  by
     the  system  for the creation of a file (see creat(2)).  For
     example, umask 022 removes write permission  for  group  and
     other (files normally created with mode 777 become mode 755;
     files created with mode 666 become mode 644).

I think what this means is that if you put the following line in your file it will mean that any new files created will have mode 777.

`umask 000`;

If you wanted all files to have mode 666 then you would do.

`umask 111`;

I will try this out myself today and let you know if there is any problem with this approach.

Avatar of idadan

ASKER

Sorry for the delay, midterms.  Anyways the script isn't sending any html back it just sits there after you hit submit and it now isn't editing the files.  I liked it better before we messed around making all the new files and copying them.  At least it worked then.  Oh, well.  I updated the txt version to reflect the latest version.  Thanks.
Avatar of idadan

ASKER

hello? icd...
Sorry for the delay, I have been off work for some time due to illness. Back at work now coping with the backlog :-(

You won't get very far if you can't see the output of the perl compiler, including the error
messages. This is the output from your script when I ran it.
---------------------------
Content-type: text/html

<HTML><HEAD></HEAD><BODY>
Done parsing<br>
Done getting variables<br>
<a href="../docs/algfake.html">View the new document</a><br>
Done adding part<br>
Undefined subroutine &main::show_new called at algebra.pl line 23.
---------------------------
In other words, you have not provided a subroutine called 'show_new'. If however your script failed
earlier, for example on trying to open file 'algfake.html' then the script would not even output the
'Content-type' line, in which case you would get an error 'Document contains no data'.

It is possible that your script failed because it could not open the file

/xlv0/web/rkeir/EAT/algfake.html

I prefer to use relative paths rather than full paths. If the directory changes you do not then have
to change your code. In fact the output file is actually in the *same* directory, so your code should
simply be:-

$frontreal = "algfake.html";

You need better visibility of the errors from your script. I estimate that every change to a script
(however small) produces between 5 and 10 errors. Many of these errors are obvious once you see the
error output, if you can't see the error output then you are working in the dark. I suspect that this
is your main problem.

You can get a little way by telnetting into your account (assuming your ISP allows you!) and
running the script from the command line. This is how I found out the above error.

Your ISP should improve his system and output any errors from your script so that they can be seen
in your browser.

If you can't do this then you need to access the error log. Check with your ISP if this is possible.

If you can't do *any* of the above then your ISP is an ass. Your only way forward is to check your
scripts locally as far as you can. Look back at my suggestion to use Personal Web Server on your PC.

Avatar of idadan

ASKER

Thanks for all of your help!  I can see why you're ranked first in cgi.