📄 ch05_02.htm
字号:
<a name="INDEX-986" />HTTPS_ environmentvariable. These variables are set by your web server only if you arereceiving a secure request via SSL. When <tt class="function">https</tt>is called without arguments, it returns the value of the HTTPSenvironment variable, which indicates whether the connection issecure (its values are server-dependent).</p></div><a name="ch05-6-fm2xml" /><div class="sect3"><h3 class="sect3">5.2.1.4. query_string</h3><p>The <tt class="function">query_string</tt><a name="INDEX-987" /> method does not do what you mightthink since it does not correspond one-to-one with<tt class="literal">$ENV{QUERY_STRING}</tt>.<tt class="literal">$ENV{QUERY_STRING}</tt> holds the query portion of theURL that called your CGI script. <tt class="function">query_string</tt>,on the other hand, is dynamic, so if you modify any of the queryparameters in your script (see <a href="ch05_02.htm#ch05-43788">Section 5.2.2.1, "Modifying parameters"</a>later in this chapter), then the value returned by<tt class="function">query_string</tt> will include these new values. Ifyou want to know what the original query string was, then you shouldrefer to <tt class="literal">$ENV{QUERY_STRING}</tt> instead.</p><p>Also, if the request method is<a name="INDEX-988" /> POST, then<tt class="function">query_string</tt> returns the POST parameters thatwere submitted in the content of the request, and ignores anyparameters passed to the CGI script via the query string. This meansthat if you create a form that submits its values via POST to a URLthat also contains a query string, you will not be able to access theparameters on the query string via CGI.pm unless you make a slightmodification to CGI.pm to tell it to include parameters from theoriginal query string with POST requests. We'll see how to dothis in <a href="ch05_02.htm#ch05-40519">Section 5.2.2.2, "POST and the query string"</a> later in this chapter.</p></div><a name="ch05-7-fm2xml" /><div class="sect3"><a name="INDEX-989" /><h3 class="sect3">5.2.1.5. self_url</h3><p>This method does not correspond to a standard CGI<a name="INDEX-990" />environment variable, although you couldmanually construct it from other environment variables. It providesyou with a <a name="INDEX-991" />URL that can call your CGI with the sameparameters. The path information is maintained and the query stringis set to the value of the <tt class="function">query_string</tt> method.</p><p>Note that this URL is not necessarily the same URL that was used tocall your CGI script. Your CGI script may have been called because ofan internal redirection by the web server. Also, because all of theparameters are moved to the query string, this new URL is built to beused with a GET request, even if the current request was a POSTrequest.</p></div><a name="ch05-8-fm2xml" /><div class="sect3"><h3 class="sect3">5.2.1.6. url</h3><p>The <tt class="function">url </tt><a name="INDEX-992" />method functions similarly to the<tt class="function">self_url</tt> method, except that it returns a URL tothe current CGI script without any parameters, i.e., no pathinformation and an empty query string.</p></div><a name="ch05-9-fm2xml" /><div class="sect3"><h3 class="sect3">5.2.1.7. virtual_host</h3><p>The <tt class="function">virtual_host</tt><a name="INDEX-993" /> <a name="INDEX-994" /><a name="INDEX-995" /> method is handy because it returns thevalue of the HTTP_HOST environment variable, if set, and SERVER_NAMEotherwise. Remember that HTTP_HOST is the name of the web server asthe browser referred to it, which may differ if multiple domainsshare the same IP address. HTTP_HOST is available only if the browsersupplied the Host HTTP header, added for HTTP 1.1.</p></div></div><a name="ch05-10-fm2xml" /><div class="sect2"><h3 class="sect2">5.2.2. Accessing Parameters</h3><p><tt class="function">param</tt><a name="INDEX-996" /> is probably the most useful methodCGI.pm provides. It allows you to access the parameters submitted toyour <a name="INDEX-997" />CGIscript, whether these parameters come to you via a GET request or aPOST request. If you call <tt class="function">param</tt> withoutarguments, it will return a list of all of the parameter names yourscript received. If you provide a single argument to it, it willreturn the value for the parameter with that name. If no parameterwith that name was submitted to your script, it returns<tt class="literal">undef</tt>.</p><p>It is possible for your CGI script to receive multiple values for aparameter with the same name. This happens when you create two formelements with the same name or you have a select box that allowsmultiple selections. In this case, <tt class="function">param</tt> returnsa list of all of the values if it is called in a list context andjust the first value if it is called in a scalar context. This maysound a little complicated, but in practice it works such that youshould end up with what you expect. If you ask<tt class="function">param</tt> for one value, you will get one value(even if other values were also submitted), and if you ask it for alist, you will always get a list (even if the list contains only oneelement).</p><p><a href="ch05_02.htm#ch05-79926">Example 5-1</a> is a simple example that displays allthe parameters your script receives.</p><a name="ch05-79926" /><div class="example"><h4 class="objtitle">Example 5-1. param_list.cgi </h4><blockquote><pre class="code">#!/usr/bin/perl -wTuse strict;use CGI;my $q = new CGI;print $q->header( "text/plain" );print "These are the parameters I received:\n\n";my( $name, $value );foreach $name ( $q->param ) { print "$name:\n"; foreach $value ( $q->param( $name ) ) { print " $value\n"; }}</pre></blockquote></div><p>If you call this CGI script with multiple parameters, like this:</p><blockquote><pre class="code">http://localhost/cgi/param_list.cgi?color=red&color=blue&shade=dark</pre></blockquote><p>you will get the following output:</p><blockquote><pre class="code">These are the parameters I received:color: red blueshade: dark</pre></blockquote><a name="ch05-43788" /><div class="sect3"><h3 class="sect3">5.2.2.1. Modifying parameters</h3><p>CGI.pm also lets you add, modify, or delete the value of<a name="INDEX-998" /> <a name="INDEX-999" />parameters within your script. To add ormodify a parameter, just pass <tt class="function">param</tt> more thanone argument. Using Perl's <tt class="literal">=></tt> operatorinstead of a comma makes the code easier to read and allows you toomit the quotes around the parameter name, so long as it's aword (i.e., only contains includes letters, numbers, and underscores)that does not conflict with a built-in function or keyword:</p><blockquote><pre class="code">$q->param( title => "Web Developer" );</pre></blockquote><p>You can create a parameter with multiple values by passing additionalarguments:</p><blockquote><pre class="code">$q->param( hobbies => "Biking", "Windsurfing", "Music" );</pre></blockquote><p>To <a name="INDEX-1000" />delete a parameter, use the<tt class="function">delete</tt> method and provide the name of theparameter:</p><blockquote><pre class="code">$q->delete( "age" );</pre></blockquote><p>You can clear all of the parameters with<tt class="function">delete_all</tt><a name="INDEX-1001" />:</p><blockquote><pre class="code">$q->delete_all;</pre></blockquote><p>It may seem odd that you would ever want to modify parametersyourself, since these will typically be coming from the user. Settingparameters is useful for many reasons, but especially when assigningdefault values to fields in forms. We will see how to do this laterin this chapter.</p></div><a name="ch05-40519" /><div class="sect3"><h3 class="sect3">5.2.2.2. POST and the query string</h3><p><tt class="function">param</tt> automatically determines if the requestmethod is <a name="INDEX-1002" /> <a name="INDEX-1,003" /><a name="INDEX-1004" />POST or GET. If it is POST, it reads anyparameters submitted to it from STDIN. If it is GET, it reads themfrom the query string. It is possible to POST information to a URLthat already has a query string. In this case, you have two souces ofinput data, and because CGI.pm determines what to do by checking therequest method, it will ignore the data in the query string.</p><p>You can change this behavior if you are willing to edit CGI.pm. Infact, CGI.pm includes comments to help you do this. You can find thisblock of code in the<tt class="function">init</tt><a name="INDEX-1005" /> subroutine (the line number willvary depending on the version of CGI.pm you have):</p><blockquote><pre class="code">if ($meth eq 'POST') { $self->read_from_client(\*STDIN,\$query_string,$content_length,0) if $content_length > 0; # Some people want to have their cake and eat it too! # Uncomment this line to have the contents of the query string # APPENDED to the POST data. # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'}; last METHOD;}</pre></blockquote><p>By removing the pound sign from the beginning of the line indicated,you will be able to use POST and query string data together. Notethat the line you would need to uncomment is too long to display onone line in this text, so it has been wrapped to the next line, butit is just one line in CGI.pm.</p></div><a name="ch05-11-fm2xml" /><div class="sect3"><h3 class="sect3">5.2.2.3. Index queries</h3><p>You may receive a query string that contains words that do notcomprise name-value pairs. The <a name="INDEX-1006" /> <a name="INDEX-1,007" /> <a name="INDEX-1,008" /><ISINDEX> HTML tag, which is notused much anymore, creates a single text field along with a prompt toenter search keywords. When a user enters words into this field andpresses Enter, it makes a new request for the same URL, adding thetext the user entered as the query string with keywords separated bya <a name="INDEX-1009" /> <a name="INDEX-1,010" />plus sign (<tt class="literal">+</tt>), suchas this:</p><blockquote><pre class="code">http://www.localhost.com/cgi/lookup.cgi?cgi+perl</pre></blockquote><p>You can retrieve the list of keywords that the user entered bycalling <tt class="function">param</tt><a name="INDEX-1011" /> with "keywords" as thename of the parameter or by calling the separate keywords method:</p><blockquote><pre class="code">my @words = $q->keywords; # these lines do the same thingmy @words = $q->param( "keywords" );</pre></blockquote><p>These methods return index keywords only if CGI.pm finds noname-value pair parameters, so you don't have to worry aboutusing "keywords" as the name of an element in your HTMLforms; it will work correctly. On the other hand, if you want to<a name="INDEX-1012" />POST form data to a URLwith a keyword, CGI.pm cannot return that keyword to you. You mustuse <tt class="literal">$ENV{QUERY_STRING}</tt><a name="INDEX-1013" /> to get it.</p></div><a name="ch05-12-fm2xml" /><div class="sect3"><h3 class="sect3">5.2.2.4. Supporting image buttons as submit buttons</h3><p>Whether <a name="INDEX-1014" /> <a name="INDEX-1,015" />you use <INPUT TYPE="IMAGE" > or<INPUT TYPE="SUBMIT">, the form is still sent to the CGIscript. However, with the image button, the name is not transmittedby itself. Instead, the web browser splits an image button name intotwo separate variables:<em class="emphasis">name.x</em><a name="INDEX-1016" />and <em class="emphasis">name.y</em>.</p><p>If you want your program to support image and regular submit buttonsinterchangeably, it is useful to translate the image button names tonormal submit button names. Thus, the main program code can use logicbased upon which submit button was clicked even if image buttonslater replace them.</p><p>To accomplish this, we can use the following code that will set aform variable without the coordinates in the name for each variablethat ends in ".x":</p><blockquote><pre class="code">foreach ( $q->param ) { $q->param( $1, 1 ) if /(.*)\.x/;}</pre></blockquote></div></div><a name="ch05-13-fm2xml" /><div class="sect2"><h3 class="sect2">5.2.3. Exporting Parameters to a Namespace</h3><p>One of the problems with using a method to retrieve the value of a<a name="INDEX-1017" /><a name="INDEX-1018" />parameter is that it is more workto embed the value in a string. If you wish to print the value ofsomeone's input, you can use an intermediate variable:</p><blockquote><pre class="code">my $name = $q->param( 'user' );print "Hi, $user!";</pre></blockquote><p>Another way to do this is via an odd Perl construct that forces thesubroutine to be evaluated as part of an anonymous list:</p><blockquote><pre class="code">print "Hi, @{[ $q->param( 'user' ) ]}!";</pre></blockquote><p>The first solution is more work and the second can be hard to read.Fortunately, there is a better way. If you know that you are going toneed to refer to many output values in a string, you can import allthe parameters as variables to a specified namespace:</p><blockquote><pre class="code">$q->import_names( "Q" );print "Hi, $Q::user!";</pre></blockquote><p>Parameters with multiple values become arrays in the new namespace,and any<a name="INDEX-1019" /><a name="INDEX-1020" />characters in a parameter nameother than a letter or number become underscores. You must provide anamespace and cannot pass "main", the default namespace,because that might create security risks.</p><p>The price you pay for this convenience is increased memory usagebecause Perl must create an alias for each parameter.</p></div><a name="ch05-67561" /><div class="sect2"><h3 class="sect2">5.2.4. File Uploads with CGI.pm</h3><p>As we mentioned in the last <a name="INDEX-1021" /> <a name="INDEX-1,022" />chapter, it is possible to create aform with a<em class="emphasis">multipart/form-data</em><a name="INDEX-1023" />media type that permits users to upload files via<a name="INDEX-1024" />HTTP. We avoided discussing how to handlethis type of input then because handling file uploads properly can bequite complex. Fortunately, there's no need for us to do thisbecause, like other form input, CGI.pm provides a very simple
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -