0

I have written this code in cgi file for html but it's showing internal server error in xampp server. When I compiled it in command line it's just displaying 'no debug' as result. What is it that i am doing wrong? The code is working fine without css part being included but as soon as I add the link part it stops working.

 #!"c:\xampp\perl\bin\perl.exe"
use strict;
use warnings;
use CGI qw(:all); 
use CGI::Carp qw(fatalsToBrowser);
#use CGI ('div');
use CGI qw/Link/;

my $q = new CGI;

print $q->header,

$q->start_html
({
  -title=>'Input Request',
  -head=>Link({-rel => 'stylesheet', 
                        -media  => 'print',
                        -type   => 'text/css',
                        -href   => 'style.css'}), 

}),

print $q->div(
              {-id=>"divtop"},
              $q->p("Here's a paragraph")
             );
$q->start_form
(
    -method=>'post',
    ), "\n",

    "Operating System",

    $q->radio_group
    (
    -name=>'ostype',
    -values=>['Windows','Linux'],
    ),
    $q->br, "\n",
$q->end_html;
  • Check your web server's error log. – simbabque Feb 07 '18 at 16:07
  • 2
    **Warning**: [Read the documentation for the CGI module](https://metacpan.org/pod/distribution/CGI/lib/CGI.pod#HTML-Generation-functions-should-no-longer-be-used): * All HTML generation functions within CGI.pm are no longer being maintained. Any issues, bugs, or patches will be rejected unless they relate to fundamentally broken page rendering.* (Keep reading for further explanation and alternatives). – Quentin Feb 07 '18 at 16:10
  • 2
    **Warning**: [Read other bits of the documentation for the CGI module](https://metacpan.org/pod/distribution/CGI/lib/CGI.pod#CGI.pm-HAS-BEEN-REMOVED-FROM-THE-PERL-CORE): *CGI.pm is no longer considered good practice for developing web applications, including quick prototyping and small web scripts. There are far better, cleaner, quicker, easier, safer, more scalable, more extensible, more modern alternatives available at this point in time. These will be documented with [CGI::Alternatives](https://metacpan.org/pod/CGI::Alternatives).* – Quentin Feb 07 '18 at 16:10
  • @simbabque Failed to load resource: the server responded with a status of 500 (Internal Server Error) – Rishab Kamboj Feb 07 '18 at 16:28
  • Why do you have `use CGI...` twice? – Chris Turner Feb 07 '18 at 16:54
  • @ChrisTurner even if i use it once.. doesn't make any difference – Rishab Kamboj Feb 07 '18 at 17:03
  • *it's showing internal server error* -- Did you give execute privileges to your perl script file? – 7stud Feb 07 '18 at 17:23
  • @7stud the file is running without the head part... – Rishab Kamboj Feb 07 '18 at 17:52
  • @RishabKamboj, Yes, I figured that out. – 7stud Feb 07 '18 at 19:20

3 Answers3

3

Having ran your code the problem is quite obvious. This is the first line it outputs...

<div id="divtop"><p>Here's a paragraph</p></div>Content-Type: text/html; charset=ISO-8859-1

The "Content-Type:" header should be the absolutely first thing that comes out of your CGI script. Anything else and your webserver won't know what to do with the output.

It looks like you've got confused between semicolons and commas in your code

print $q->header,

$q->start_html
({
  -title=>'Input Request',
  -head=>Link({-rel => 'stylesheet', 
                        -media  => 'print',
                        -type   => 'text/css',
                        -href   => 'style.css'}), 

}),

print $q->div(
              {-id=>"divtop"},
              $q->p("Here's a paragraph")
             );

Linking those 3 statements with commas means that the code printing the <div> happens and the return value is added to the list of things being printed by the first print.

Tidying things up, your code should look like this. The header line comes first and is just a single statement by itself.

print $q->header;

I don't really have any idea what that mess of CGI HTML code is meant to look like, so I'm not going to attempt to try and fix it, although I think it should be just one long comma separated statement. You should really look at something better like the Template Toolkit. Even just printing out raw HTML would be easier to read IMO in comparison.

Also, just to cover all the bases the first line of your script appears to have a space at the front - that will also cause problems if it actually exists and isn't just a copy'n'paste error.

 #!"c:\xampp\perl\bin\perl.exe"
Chris Turner
  • 8,082
  • 1
  • 14
  • 18
1

You should understand how print (or any other function works):

1) Here's an example:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;
use DBI;

sub do_stuff {
    print "xxx\n";
}

print "goodbye\n", do_stuff, "\n";

What do you think perl will output first? The string "goodbye\n" or the string "xxx"? In other words, is that print statement equivalent to:

print "goodbye\n";
print dostuff;
print "\n";

???

2) Here's another example:

print "hello", die("Too tired too print anything else...");

What do you think the output will be? die() causes your program to terminate immediately and output the specified message before quitting.

The rule is: a function's arguments must be fully determined before the function itself will execute. Therefore, in your perl script when you wrote:

print $q->header,

...that was correct because you have to output the response header first. But then there's that trailing comma. You continued your print statement with:

print $q->header, $q->start_html(), print $q->div() 

That statement is equivalent to:

print(
    $q->header,
    $q->start_html(),
    print($q->div)
)

Okay, applying the rule: the outer print() won't execute until each of the three arguments are determined. Therefore, perl executes $q->header, which returns a string. And rule #2 is: all function calls in your code are replaced by the function's return value. That gives you:

print(
    "some http response info,
    $q->start_html()
    print($q->div)
)

Next, perl executes $q->html, which also returns a string, giving you:

print(
    "some http response info",
    "<html> blah blah",
    print($q->div)
)

Finally, the third argument is evaluated, print($q->div). The third argument is equivalent to print("<div>..."), giving you:

print(
    "some html response stuff",
    "<html> blah blah",
    print("<div...")
)

As my first two examples at the beginning of my answer demonstrate, the inner print() will execute before the outer print is able to print the first two arguments. Therefore, you end up NOT outputting the header first, hence your error. print("<div...") actually returns 1 after outputting the string, so you end up with:

print(
    "some html response stuff",
    "<html> blah blah",
    1
)

And now the outer print can finally execute.

I'm using Apache for my server, and your perl script is located here:

apache2/cgi-bin/perl2.pl 

A url to retrieve the output of the script:

http://localhost:8080/cgi-bin/perl2.pl

I put a css file here:

apache2/cgi-bin/htdocs/css/my.css

Normally, I can retrieve html pages in htdocs without specifying the htdocs directory, so:

http://localhost:8080/page.html

As a result, the path from the cgi-bin directory to a file in the htdocs directory is simpy:

../css/my.css  (rather than ../htdocs/css/my.css)

Here's your code with all the changes needed to access the css file:

use strict;
use warnings;
use CGI qw(:all); 
use CGI::Carp qw(fatalsToBrowser);

my $q = new CGI;

print(

    $q->header,

    $q->start_html(
        -title => 'Input Request',
        -style=>{-src=>"../css/my.css"}    #<==THIS CREATES A LINK TAG           
    ),

    $q->div(
        {-id=>"divtop"},
        $q->p("Here's a paragraph")
    ),

    $q->start_form(
        -method=>'post'
    ),

    $q->div("OperatingSystem"),
    $q->div(
        $q->radio_group(
            -name=>'ostype',
            -values=>['Windows','Linux']
        )
    ),

    $q->end_form,
    $q->end_html
);

Here's the html that the perl script creates(spacing adjusted by me):

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">

<head>
  <title>Input Request</title>
  <link rel="stylesheet" type="text/css" href="../css/my.css" />
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>

<div id="divtop"><p>Here's a paragraph</p></div>

<form method="post" action="/cgi-bin/perl2.pl" enctype="multipart/form-data">
  <div>OperatingSystem</div>
  <div>
    <label><input type="radio" name="ostype" value="Windows" checked="checked" />Windows</label> 
    <label><input type="radio" name="ostype" value="Linux" />Linux</label>
  </div>

<div><input type="hidden" name=".cgifields" value="ostype"  /></div>
</form>

</body>
</html>

Note that you get the head tag for free. I assume that's because the title and link tags are supposed to be inside a head tag in well formatted html.

And, here it is using Link():

print(

    $q->header,

    $q->start_html(
        -title => 'Input Request',
        -head  => Link({
                   -rel    => 'stylesheet',
                   -type   => 'text/css',
                   -href   => '../css/my.css'
                  })    
    ),

    $q->div(
        {-id=>"divtop"},
        $q->p("Here's a paragraph")
    ),

    $q->start_form(
        -method=>'post'
    ),

    $q->div("OperatingSystem"),
    $q->div(
        $q->radio_group(
            -name=>'ostype',
            -values=>['Windows','Linux']
        )
    ),

    $q->end_form(),

    $q->br(),
    $q->end_html()

);

If I add media => 'print to the Link() hash, which adds the attribute media="print" to the link tag, the css is disabled in my browser. On the other hand, when I do a Print Preview of the page in my browser, I do see the css styling. I think that's the expected behavior. Here's the html:

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">

<head>
<title>Input Request</title>
<link type="text/css" rel="stylesheet" href="../css/my.css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>
<div id="divtop"><p>Here's a paragraph</p></div><form method="post" action="/cgi-bin/perl2.pl" enctype="multipart/form-data"><div>OperatingSystem</div><div><label><input type="radio" name="ostype" value="Windows" checked="checked" />Windows</label> <label><input type="radio" name="ostype" value="Linux" />Linux</label></div><div><input type="hidden" name=".cgifields" value="ostype"  /></div></form><br />
</body>
</html>
7stud
  • 46,922
  • 14
  • 101
  • 127
0

CGI programs are typically placed in a cgi-bin directory which is configured so the web server treats everything in it as a CGI compliant executable. Your CSS file is not an executable CGI program!

Move your static files outside cgi-bin and change the URLs you use to reference them to point to their new URLs.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • my cgi file is in cgi-bin and i moved my css file outside and gave full correct path for css file.... still the same error is there. – Rishab Kamboj Feb 07 '18 at 16:21