⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch06_04.htm

📁 用perl编写CGI的好书。本书从解释CGI和底层HTTP协议如何工作开始
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<p><a href="ch06_04.htm#ch06-83567">Example 6-14</a> contains the<tt class="function">get_story</tt> function from the News module.</p><a name="ch06-83567" /><div class="example"><h4 class="objtitle">Example 6-14. News.pm (part 2 of 3) </h4><blockquote><pre class="code">sub get_story {    my( $filename ) = shift(  ) =~ /^(\d+)$/;    my( $headline, $article );        unless ( defined( $filename ) and -T "$NEWS_DIR/$filename" ) {        return "Story Not Found", &lt;&lt;END_NOT_FOUND, get_time( time );&lt;P&gt;Oops, the story you requested was not found.&lt;/P&gt;&lt;P&gt;If a link on our What's New page brought you here, pleasenotify the &lt;A HREF="mailto:$ENV{SERVER_ADMIN}"&gt;webmaster&lt;/A&gt;.&lt;/P&gt;END_NOT_FOUND    }        open STORY, "$NEWS_DIR/$filename" or      die "Cannot open $NEWS_DIR/$filename: $!";    flock STORY, LOCK_SH;    $headline = &lt;STORY&gt;;    chomp $headline;    local $/ = undef;    $article = &lt;STORY&gt;;        return $headline, $article, get_date( $filename );}</pre></blockquote></div><p>This function takes the story number as a parameter, and the firstthing this function does is verify that it is the expected format.The <a name="INDEX-1478" />regular expression assignmentfollowed by the <tt class="function">defined</tt> test may seem like aroundabout way to test this, but we do this in order to untaint the<a name="INDEX-1479" />filename;we explain tainting and why it's important in <a href="ch08_04.htm#ch08-28640">Section 8.4, "Perl's Taint Mode"</a>. Finally we make sure that this story existsand is a text file.</p><p>If any of our checks fail, we return an error to the user formattedlike a standard story. Otherwise, we open the file read the headlineand contents, get its date, and return this to the page.</p><p>Now let's look at the administrative pages. The administrativepages should be placed in a subdirectory beneath the other files. Forexample, the files could be installed in the following locations:</p><blockquote><pre class="code">.../news/news.epl.../news/article.epl.../news/admin/edit_news.epl.../news/admin/edit_article.epl</pre></blockquote><p>This enables us to configure the web server to restrict access to the<em class="emphasis">admin</em> subdirectory. <a href="ch06_04.htm#ch06-70774">Example 6-15</a>shows the main administrative page,<em class="filename">admin_news.epl</em>.</p><a name="ch06-70774" /><div class="example"><h4 class="objtitle">Example 6-15. admin_news.epl </h4><blockquote><pre class="code">&lt;HTML&gt;[!    use lib "/usr/local/apache/lib-perl";    use News;!][-      if ( my( $input ) = keys %fdat ) {        my( $command, $story ) = split ":", $input;                $command eq "new" and do {            $http_headers_out{Location} = "edit_article.epl";            exit;        };        $command eq "edit" and do {            $http_headers_out{Location} = "edit_article.epl?story=$story";            exit;        };        $command eq "delete" and            News::delete_story( $story );    }        @stories = News::get_stories(  )-]&lt;HEAD&gt;  &lt;TITLE&gt;What's New Administration&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY BGCOLOR="white"&gt;  &lt;FORM METHOD="POST"&gt;    &lt;H2&gt;What's New Administration&lt;/H2&gt;        &lt;P&gt;Here you can edit and delete existing stories as well as create      new stories. Clicking on a headline will take you to that article      in the public area; you will need to use your browser's Back button      to return.&lt;/P&gt;    &lt;HR&gt;        &lt;TABLE BORDER=1&gt;    &lt;TR&gt;      [- ( $story, $headline, $date ) = @{ $stories[$row] } if $stories[$row] -]      &lt;TD&gt;        &lt;INPUT TYPE="submit" NAME="edit:[+ $story +]" VALUE="Edit"&gt;        &lt;INPUT TYPE="submit" NAME="delete:[+ $story +]" VALUE="Delete"          onClick="return confirm('Are you sure you want to delete this?')"&gt;      &lt;/TD&gt;      &lt;TD&gt;        &lt;A HREF="../article.epl?story=[+ $story +]"&gt;[+ $headline +]&lt;/A&gt;        &lt;I&gt;[+ $date +]&lt;/I&gt;      &lt;/TD&gt;    &lt;/TR&gt;    &lt;/TABLE&gt;        &lt;INPUT TYPE="submit" NAME="new" VALUE="Create New Story"&gt;    &lt;/FORM&gt;  &lt;HR&gt;  &lt;P&gt;Go to &lt;A HREF="../news.epl"&gt;What's New&lt;/A&gt;.&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</pre></blockquote></div><p>The result looks like <a href="ch06_04.htm#ch06-53377">Figure 6-5</a>.</p><a name="ch06-53377" /><div class="figure"><img width="478" src="figs/cgi2.0605.gif" height="288" alt="Figure 6-5" /></div><h4 class="objtitle">Figure 6-5. Main administrative page for "What's New"</h4><p>This page must handle a few different requests. If it receives aparameter, it uses a series of conditions to determine how to handlethe request. Let's return to these statements after looking atthe rest of the file because when the administrator first visits thispage, there are no parameters.</p><p>Like <em class="filename">news.epl</em>, we fetch an array of stories from<tt class="function">get_stories</tt>, but instead of creating an orderedlist and looping over list items, we output a table and loop overrows in this table. For each story, we output a corresponding Editand Delete button as well as a link to the story. Note that the nameof the Edit and Delete buttons contain the command as well as thenumber of the story separated by a colon. This allows us to pass bothpieces of information when the administrator clicks on a button,without restricting us from changing the label of the button.Finally, we add a submit button to the bottom of the page to allowthe administrator to add a new story.</p><p>All the form elements on these page are submit buttons, and they willonly send a name-value pair if they are clicked. Thus, if theadministrator clicks a button, the browser will request the same pageagain, passing a parameter for the selected button. Returning to theconditions at the top of the file, if there is a parameter passed tothis file, it is split by colon into <tt class="literal">$command</tt> and<tt class="literal">$story</tt>.</p><p>You may have noticed that if the administrator selects the button tocreate a new story, then the supplied parameter will not include acolon. That's okay because in this case,<tt class="function">split</tt> will set <tt class="literal">$command</tt> to"new" and <tt class="literal">$story</tt> to<tt class="literal">undef</tt>. If <tt class="literal">$command</tt> is set to"new", we forward the user to the<em class="filename">edit_article.epl</em> file. To do this, we assignEmbperl's special <tt class="literal">%http_headers_out</tt>variable. Setting the "Location" key to a value outputs a<em class="emphasis">Location</em> HTTP header; we can then exit thispage.</p><p>If the administrator edits an existing story, we also forward to the<em class="filename">edit_article.epl</em> file and exit, but in this casewe pass the story number as part of the query string. If theadministrator deletes a story, we invoke the<tt class="function">delete_story</tt> function from our News module andcontinue processing. Because we gather the list of stories after thisdeletion, this page will display the updated list of headers.</p><p>We also add a JavaScript handler to the delete button to preventstray mouse clicks from deleting the wrong file. Even if you havedecided not to use JavaScript on your public site, it can be veryuseful for administrative pages with limited access such as this,where you typically can be more restrictive about the browserssupported.</p><p>Finally, <a href="ch06_04.htm#ch06-90891">Example 6-16</a> presents<em class="firstterm">edit_article.epl</em>, the page that allows theadministrator to create or edit articles.</p><a name="ch06-90891" /><div class="example"><h4 class="objtitle">Example 6-16. edit_article.ep </h4><blockquote><pre class="code">&lt;HTML&gt;[!    use lib "/usr/local/apache/lib-perl";    use News;!][-    if ( $fdat{story} ) {        ( $fdat{headline}, $fdat{article} ) =            News::get_story( $fdat{story} );    }    elsif ( $fdat{save} ) {        News::save_story( $fdat{story}, $fdat{headline}, $fdat{article} );        $http_headers_out{Location} = "edit_news.epl";        exit;    }-]&lt;HEAD&gt;  &lt;TITLE&gt;Edit Article&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY BGCOLOR="white"&gt;  &lt;H2&gt;Edit Article&lt;/H2&gt;    &lt;HR&gt;  &lt;FORM METHOD="POST"&gt;    &lt;P&gt;&lt;B&gt;Headline: &lt;/B&gt;&lt;INPUT TYPE="text" NAME="headline" SIZE="50"&gt;&lt;/P&gt;        &lt;P&gt;&lt;B&gt;Article:&lt;/B&gt; (HTML formatted)&lt;BR&gt;      &lt;TEXTAREA NAME="article" COLS=60 ROWS=20&gt;&lt;/TEXTAREA&gt;&lt;/P&gt;        &lt;INPUT TYPE="reset" VALUE="Reset Form"&gt;    &lt;INPUT TYPE="submit" NAME="save" VALUE="Save Article"&gt;    [$ hidden $]  &lt;/FORM&gt;  &lt;HR&gt;  &lt;P&gt;Return to &lt;A HREF="edit_news.epl"&gt;What's New Administration&lt;/A&gt;.    &lt;I&gt;Warning, you will lose your changes!&lt;/I&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</pre></blockquote></div><p>The result looks like <a href="ch06_04.htm#ch06-86259">Figure 6-6</a>.</p><a name="ch06-86259" /><div class="figure"><img width="473" src="figs/cgi2.0606.gif" height="375" alt="Figure 6-6" /></div><h4 class="objtitle">Figure 6-6. Article editing page</h4><p>If the administrator is editing a page, then the story number will besupplied in the query string. We get this from<tt class="literal">%fdat</tt> and fetch the headline and article contentsusing <tt class="function">get_story</tt>. We then set these fields in<tt class="literal">%fdat</tt> so that when Embperl encounters the<em class="emphasis">headline</em> and <em class="emphasis">article</em> formelements later in this file, it will pre-fill these defaults valuesfor us automatically. The hidden command in the form below will bereplaced with the story number if it was supplied. This is all weneed to do in order to have the form handle new stories as well asedits.</p><p>When the administrator submits these changes, the story number (whichwill be present for edits and undefined for additions), the headlinetext, and the article text are supplied to the<tt class="function">save_story</tt> function and the administrator isredirected back to the main administrative page.</p><p>The administrative functions from <a name="INDEX-1480" /><a name="INDEX-1481" />News are shown in <a href="ch06_04.htm#ch06-74481">Example 6-17</a>.</p><a name="ch06-74481" /><div class="example"><h4 class="objtitle">Example 6-17. News.pm (part 3 of 3) </h4><blockquote><pre class="code">sub save_story {    my( $story, $headline, $article ) = @_;    local *STORY;        $story ||= time;                        # name new files based on time in secs    $article =~ s/\015\012|\015|\012/\n/g;  # make line endings consistent    $headline =~ tr/\015\012//d;            # delete any line endings just in case        my( $file ) = $story =~ /^(\d+)$/ or die "Illegal filename: '$story'";        open STORY, "&gt; $NEWS_DIR/$file";    flock STORY, LOCK_EX;    seek STORY, 0, 0;    print STORY $headline, "\n", $article;    close STORY;}sub delete_story {    my $story = shift;        my( $file ) = $story =~ /^(\d+)$/ or die "Illegal filename: '$story'";    unlink "$NEWS_DIR/$file" or die "Cannot remove story $NEWS_DIR/$file: $!";}</pre></blockquote></div><p>The <tt class="function">save_story</tt> function takes an optional storyfile number, a headline, and article contents. If a number is notprovided for the story, <tt class="function">save_story</tt> assumes thatthis is a new story and generates a new number from<tt class="function">date</tt>. We convert line endings from browsers onother platforms to the standard line ending for our web server andtrim any line-ending characters from the headline because these wouldcorrupt our data.</p><p>Again, we test the story number to make sure it is valid and thenopen this file and write to it, replacing any previous version ifthis is an update. We get an exclusive lock while we are writing sosomeone else does not try to read it before we finish (and get apartial news story). The <tt class="function">delete_story</tt> functionsimply tests that the filename is <a name="INDEX-1482" /> <a name="INDEX-1,483" />valid and removes it.</p></div></div><a name="ch06-22-fm2xml" /><div class="sect2"><h3 class="sect2">6.4.6. Summary</h3><p>As we have seen, Embperl presents a very different approach togenerating dynamic output with Perl. We've covered what youneed to know in order to develop most Embperl pages, but Embperl hasmany features and options that we simply do not have room to present.Fortunately, Embperl has extensive documentation, so if you want tolearn more about HTML::Embperl, you can download it from CPAN<a name="INDEX-1484" /><a name="INDEX-1485" /><a name="INDEX-1486" />and visitthe <a name="INDEX-1487" /><a name="INDEX-1488" />Embperlwebsite at <a href="http://perl.apache.org/embperl/">http://perl.apache.org/embperl/</a>.</p></div><hr align="left" width="515" /><div class="navbar"><table border="0" width="515"><tr><td width="172" valign="top" align="left"><a href="ch06_03.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0" /></a></td><td width="171" valign="top" align="center"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0" /></a></td><td width="172" valign="top" align="right"><a href="ch06_05.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0" /></a></td></tr><tr><td width="172" valign="top" align="left">6.3. HTML::Template</td><td width="171" valign="top" align="center"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0" /></a></td><td width="172" valign="top" align="right">6.5. Mason</td></tr></table></div><hr align="left" width="515" /><img src="../gifs/navbar.gif" alt="Library Navigation Links" usemap="#library-map" border="0" /><p><font size="-1"><a href="copyrght.htm">Copyright &copy; 2001</a> O'Reilly &amp; Associates. All rights reserved.</font></p><map name="library-map"><area href="../index.htm" coords="1,1,83,102" shape="rect" /><area href="../lnut/index.htm" coords="81,0,152,95" shape="rect" /><area href="../run/index.htm" coords="172,2,252,105" shape="rect" /><area href="../apache/index.htm" coords="238,2,334,95" shape="rect" /><area href="../sql/index.htm" coords="336,0,412,104" shape="rect" /><area href="../dbi/index.htm" coords="415,0,507,101" shape="rect" /><area href="../cgi/index.htm" coords="511,0,601,99" shape="rect" /></map></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -