Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

How to convert an @ARGV to form based input?

by taint (Chaplain)
on Aug 21, 2012 at 06:03 UTC ( #988585=perlquestion: print w/ replies, xml ) Need Help??
taint has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, Well, I spent last weekend creating an all encompassing DNS query perl script. Creation & testing was done from the CLI. Everything worked as intended. So today I set out to convert it to a web based form. But apparently my train of thought decoupled a few cars somewhere along the line. Because no matter how hard I tried, I couldn't generate a form that either 1) posted the input variable, or 2) didn't make perl squeal bloody murder. WHat I had hoped to accomplish today, was to incorporate a form field inline (within the script itself), using the POST method (to help thwart users embedding a query string from within their own pages, against mine). The script is quite large, but here's a snippet, that should reveal my intent:
#!/usr/bin/perl -w use strict; use Net::DNS; my $dns = new Net::DNS::Resolver; for my $domain( @ARGV ) { my $mx = $dns->query( $domain, 'MX' ); print "content-type:text/html; charset=utf-8\n\n"; print "$domain:\n\n"; foreach my $rr ($mx->answer) { print "<br />", $rr->exchange, ' [<b>', $rr->preference, "</b> +]\n"; } }
using the above in a web page as:
http://mydomain.tld/dnsdig.cgi?google.com
produces the intended output. But, any incarnation of:
# replace for my $domain( @ARGV ) { # with if($domain ne "") { print "<form action=\"dnsdig.cgi\" method=\"post\"> <input name=\"domain\" type=\"text\" value=\"\" /> <input type=\"submit\" value=\"Get MX\" /> </form>"; } else { my $mx = $dns->query( $domain, 'MX' ); print "content-type:text/html; charset=utf-8\n\n"; print "$domain:\n\n"; foreach my $rr ($mx->answer) { print "<br />", $rr->exchange, ' [<b>', $rr->preference, "</b> +]\n"; } }
fails! :(
YES. I know $domain is replaced with (@ARGV), and this is truly trivial, but for the life of me, I'm stuck. Please help.
Thank you for all of your time and consideration.
--Chris
#!/usr/bin/perl -Tw
use perl::always;
my $perl_version = "5.12.4";
print $perl_version;

Comment on How to convert an @ARGV to form based input?
Select or Download Code
Re: How to convert an @ARGV to form based input?
by CountZero (Bishop) on Aug 21, 2012 at 06:10 UTC
    any incarnation of: (...) fails!
    "Fails" in which way? Any errors on screen or in the webserver's logs? Do you use CGI (or similar) to parse the inputs?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      Greetings @CountZero, and thank you for your prompt reply! Yes, there are errors. In the case above, perl complains about:
      Global symbol "$domain" requires explicit package name at dnsdig.cgi line 8.
      Mind you, I've tried MANY different incarnations today. But I think that was the output perl emitted in the web log, when I used the example above.
      Thanks again for taking the time to respond.
      --Chris
      #!/usr/bin/perl -Tw
      use perl::always;
      my $perl_version = "5.12.4";
      print $perl_version;
        Mmmm, obviously you have not shown us the whole of your program and that makes it difficult to help you. It seems the code to stuff the content of the form fields into $domain is entirely missing.

        I suggest you make a small and simple cgi-script using CGI::Simple or such and see you can get some data in and out of it. Don't yet bother yourself with coupling the cgi-script with your DNS-routines. You can add those later.

        Or even better, start using some web-frameworks (Dancer springs to mind) to make life more easy for you.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        My blog: Imperial Deltronics
        That's obviously because in for my $domain(...) loop you defined $domain but when you replaced this line with if($domain ne "") this variable was not defined anymore. Put my $domain; before if and it will work.
Re: How to convert an @ARGV to form based input?
by ig (Vicar) on Aug 21, 2012 at 08:22 UTC

    You have explained a bit about what you don't want but you haven't said much about what you do want, so I can only guess. Anyway, you seem to be having a problem accessing CGI parameters from your script. Here is one simple way to access a CGI parameter:

    use strict; use warnings; use Net::DNS; use CGI; use CGI::Carp qw{fatalsToBrowser}; my $q = CGI->new(); my $dns = new Net::DNS::Resolver; if(my $domain = $q->param('domain')) { my $mx = $dns->query( $domain, 'MX' ); print "content-type:text/html; charset=utf-8\n\n"; print "$domain:\n\n"; foreach my $rr ($mx->answer) { print "<br />", $rr->exchange, ' [<b>', $rr->preference, "</b> +]\n"; } } else { die "missing required parameter: domain"; }

    If you query this CGI script with a URL like:

    http://mydomain.tld/dnsdig.cgi?domain=google.com

    You should get something.

    It is unusual, in my experience, to use unnamed parameters with HTTP requests. Whether using GET or POST, I always name my parameters. Note that this CGI script will work with both GET requests, with parameters in the URL or POST requests with parameters in the body, as commony submitted from HTML forms.

    Hopefully, this will get you past your block, to see how query parameters can be accessed from within a CGI script.

    Do read up on CGI and CGI::Carp

      Or even
      use CGI; my $query = $ENV{QUERY_STRING} || $ENV{REDIRECT_QUERY_STRING} || '%68% +69.example.com'; my $domain = CGI->unescape( $query ); print CGI->header; print "$domain\n"; __END__ Content-Type: text/html hi.example.com
      Good advice @ig, and thank you very much for the reply.
      What I actually have, is a very large script that provides every option DNS queries permit. I built, and tested it as CLI (at the console/term). Now that it all works at the term, I want to incorporate a form field where the (@ARGV) is. Since the whole thing is so large, I simply posted one of the queries as an example. I have already finished all of the web based stuff, providing each query option as a
      <select> <option> </option> </select>

      Then providing additional options as checkboxes, or radio.
      so: the example I posted here appears as:
      <select> <option>MX</option> </select>

      the additional options are A, AAA, HINFO, IP6, TXT, etc...
      What I do want to do, is provide an empty form input field that allows the entry of a domain name to query those options for. meaning; replace the (@ARGV) I have now, with a form input field. As it sits now (without form fielsd(s), I can query the form via:
      http://mydomain.tld/dnsdig.cgi?somedomain.tld
      and it returns the MX records (using the example above with the (@ARGV). But I don't want the web clients location: to see, or be able to manipulate the query string -- hence the desire to put the form fields within the script itself, and my choice of using the POST method.
      I hope that helps clear things up a bit, and thanks again for your thoughtful reply.
      --Chris
      #!/usr/bin/perl -Tw
      use perl::always;
      my $perl_version = "5.12.4";
      print $perl_version;

        But I don't want the web clients location: to see, or be able to manipulate the query string -- hence the desire to put the form fields within the script itself, and my choice of using the POST method.

        Yeah, POST doesn't hide anything from the client

        From CGI:

        It is possible for a script to receive CGI parameters in the URL as well as in the fill-out form by creating a form that POSTs to a URL containing a query string (a "?" mark followed by arguments). The param() method will always return the contents of the POSTed fill-out form, ignoring the URL's query string. To retrieve URL parameters, call the url_param() method. Use it in the same way as param(). The main difference is that it allows you to read the parameters, but not set them.

        So, you can easily ignore parameters from the URL when using CGI. If you are parsing the CGI inputs otherwise, you will have to look to the tools you are using to find out what your options are. When you are delivering the blank form, you can ignore parameters entirely, if that suits you.

        For an empty form input field, I would use something like:

        <form method="POST" action="http://mydomain.tld/dnsdig.cgi"> <input type="text" name="domain"> <input type="submit" value="Submit"> </form>

        If the user enters a URL that refers to your CGI script and includes a query string in the URL, you could detect this and issue a redirect to a URL without a query string.

Re: How to convert an @ARGV to form based input?
by CountZero (Bishop) on Aug 21, 2012 at 13:29 UTC
    Your problem seems to be that you do not know how to get the data from your form field into your script.

    The old but venerable Ovid's CGI course (sadly now only found on the way-back engine) will explain it to you. Lessons 4 and 5 are particularly to the point.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      Greetings @CountZero, and thank you for your continued efforts.
      Well, I see what the problem has been. Using the advice listed within this thread -- including my own thoughts, have all returned the POSTed data as $domain=blah..., instead of turning $domain into blah... -- which was what the title suggested ;).
      So. I think the best idea will be to abandon the use of NET::DNS::*, and simply slurp the form input data, and pass it to my system via a:
      read(STDIN,$temp,$ENV{'CONTENT_LENGTH'});.
      This worked quite well for my whois script, and I was able to easily sanitize the input by filtering $temp before handing it off to the system itself.
      Thanks again, to you, and everyone else who attempted to help me solve this problem.
      Perhaps this dialog will help others who fall into this dilemna. :)
      --Chris
      #!/usr/bin/perl -Tw
      use perl::always;
      my $perl_version = "5.12.4";
      print $perl_version;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://988585]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2014-10-22 12:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (117 votes), past polls