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

My friend doesn't have SSH access to his crappy hosted web server, and he doesn't know which Perl modules are installed. So...I wrote a simple CGI script that I thought would allow him to check for installed modules:
#!/usr/bin/perl use strict; use CGI qw/:standard/; use CGI::Carp 'fatalsToBrowser'; my $module = param('module'); my $result; checkForModule(); showPage(); sub checkForModule { $result = `/usr/bin/perl -M$module -e 1`; } sub showPage { print header, start_html({-onload => "document.moduleForm.module.focus()", title + => "Module Checker"}), qq( <br /><br /> $result $module <br /><br /> <form method="post" action="have.pl" name="moduleForm"> <input type="text" name="module" id="module" maxlength="50"> <input type="submit" value="Check for Module" name="submitButt +on" id="submitButton"> </form> ), end_html(); }

However, the $result scalar never has a value. Why not?

Replies are listed 'Best First'.
Re: Calling perl from CGI
by lamp (Chaplain) on Sep 07, 2008 at 05:40 UTC
    You can use the following method to check whether a module is installed or not.
    if ( eval "use $module; 1" ) { $result = "Module $module is available!!"; }else { $result= "Module $module not available!!"; }
      Thanks for the excellent responses and alternatives! TIMTOWTDI!
Re: Calling perl from CGI
by betterworld (Curate) on Sep 07, 2008 at 09:29 UTC

    I use a script to test for modules locally, and it includes the following lines:

    require Class::Inspector; my $file = Class::Inspector->resolved_filename($ARGV[0]); unless ($file) { warn "not found\n"; exit (1); } print $file;

    You can convert it into a CGI script easily.

    The advantage is that it does not eval() or system() anything. And it does not really load the module. Some modules start their actions when you "use" or "require" or "-M" them, even if you don't call any of their functions. For some modules, these actions are pretty severe (like Acme::Bleach...). You won't have this problem with the above code.

    Of course you need Class::Inspector for this.

Re: Calling perl from CGI
by Narveson (Chaplain) on Sep 07, 2008 at 03:44 UTC

    Perhaps the service provider doesn't want anybody checking for the module

    Moose;rm -r *
      But if I do this...
      $result = `/usr/bin/perl -v`;
      $result gets the version output, and it's all happily displayed on the page. So you're saying the provider is somehow able to tell if a CGI script calls Perl with the -M option in particular?
        $result  = `/usr/bin/perl -v`;

        does not contain user-supplied input. User-supplied input is what security-conscious hosts forbid. See perlsec for how it works.

        Updated:

        As other respondents have shown, your method would be ineffective even if it did not breach security, so I have deleted my original suggestions for putting an untainted module name between the backticks. The eval "use $module; 1" suggestion from lamp, besides having the advantage of actually working, is free of security concerns.

        Why not? For all you know, your provider is playing a prank.

        Ok that was a joke :D
        Why do you expect your code to work? If there is an error (module not installed), you get no output because qx// doesn't capture stderr (``), and if there is no error (module is installed) you get not output because you print nothing. Example

        C:\>perl -MCGI -e 1 |hexdump 00000000; C:\>perl -MCGIs -e 1 |hexdump Can't locate CGIs.pm in @INC (@INC contains: C:/Perl/lib C:/Perl/site/ +lib .). BEGIN failed--compilation aborted. 00000000; C:\>perl -MCGIs -e 1 2>2 C:\>hexdump 2 00000000: 43 61 6E 27 74 20 6C 6F - 63 61 74 65 20 43 47 49 |Can't loc +ate CGI| 00000010: 73 2E 70 6D 20 69 6E 20 - 40 49 4E 43 20 28 40 49 |s.pm in @ +INC (@I| 00000020: 4E 43 20 63 6F 6E 74 61 - 69 6E 73 3A 20 43 3A 2F |NC contai +ns: C:/| 00000030: 50 65 72 6C 2F 6C 69 62 - 20 43 3A 2F 50 65 72 6C |Perl/lib +C:/Perl| 00000040: 2F 73 69 74 65 2F 6C 69 - 62 20 2E 29 2E 0D 0A 42 |/site/lib + .). B| 00000050: 45 47 49 4E 20 66 61 69 - 6C 65 64 2D 2D 63 6F 6D |EGIN fail +ed--com| 00000060: 70 69 6C 61 74 69 6F 6E - 20 61 62 6F 72 74 65 64 |pilation +aborted| 00000070: 2E 0D 0A - |. | 00000073; C:\>
        2>2 redirects stderr to file 2
Re: Calling perl from CGI
by trwww (Priest) on Sep 08, 2008 at 00:11 UTC

    Hello,

    Sounds like you could use perldiver?

    trwww