2012年9月26日 星期三

Perl 教學 -- 表單處理

Perl 教學 -- 表單處理

This tutorial is copyrighted and provided as is. You are welcomed to use it for non-commercial purpose.
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu

請勿轉貼
看其他教材

本範例參考並修改了 CGI 一日通: 使用 Perl 5 這本書中的一個範例。 在這個範例,我們設計了兩個表單元件的表單,並整合了之前所學的概念 (含 GET/POST 資料、字串處理),讓程式可以分別取得單一表單元件的資料。 讓我們以範例進行說明:
  1. 表單:
    E-mail:
    您的意見:
    表單的原始碼如下:

    <form method="POST" action="comments.pl">
    <strong>E-mail:</strong>
    <input type="text" name="address" size="30" maxlength="50">
    <br>您的意見:<br>
    <textarea name="comments" rows="8" cols="50">
    </textarea>
    <p><input type="submit" value="Sent Comments">
    </form>
    
    在表單中,總共有兩個分別名為 addresscomments 的資料會傳送給 comments.pl,其格式為 address=email@address 以及 comments=使用者輸入的意見
  2. 為了處理瀏覽器傳過來的 addresscomments 資料, comments.pl 利用了一些可以重複使用的方法,而這些方法定義在 forms-lib.pl,其原始碼如下:
    #!/usr/local/bin/perl
    # forms-lib.pl
    # Decodes URLs and unpacks from input.
    # Read the form contents into $input, decodes it, unpacks it,
    # and returns it as an associative array.
    sub GetFormInput
    {
      my(%input);
      $input = &ReadInput();
      %input = &ParseInput($input) if $input;
      return(%input);
    }
    
    sub ReadInput
    {
      my($method, $input, $length);
      $method = $ENV{'REQUEST_METHOD'};
      if($method eq 'GET')
      {
        $input = $ENV{'QUERY_STRING'};
      }
      elsif ($method eq 'POST')
      {
        $length = $ENV{'CONTENT_LENGTH'};
        read(STDIN, $input, $length);
      }
    
      return($input);
    }
    
    sub ParseInput
    {
      my($input) = @_;
      my(@pairs);
      my(%input);
      @pairs = split('&',$input);
      foreach $pair (@pairs)
      {
        # convert all plus signs to spaces.
        $pair =~ s/\+/ /g;
    
        # split into a key and a value.
        ($key, $value) = split('=', $pair, 2);
    
        # Convert hex numbers to alphanumeric.
        $key =~ s/%(..)/pack("c", hex($1))/ge;
        #$value =~ s/%(..)/pack("c", hex($1))/ge;
        $value =~ s/%([\da-fA-F][\da-fA-F])/pack("c", hex($1))/ge;
    
        # handle multiple values, separated by newlines.
        $input{$key} .= "\n" if defined($input{$key});
    
        # associate keys and values
        $input{$key} = $value;
      }
      return (%input);
    }
    
    return true;
    

    • comments.pl 首先呼叫 GetFormInput 來取得表單 資料;而其取得資料的方式,分成兩個步驟:第一個是呼叫 ReadInput, 第二個是呼叫 ParseInput
    • ReadInput 是一個可以處理 GET 以及 POST 的方法;它利用 環境變數 REQUEST_METHOD 來確認 GET 或者 POST,然後分別利用 相對應的方式(讀取環境變數 QUERY_STRING 或者標準輸入 STDIN)來取得 輸入的資料;請注意: 目前取得的資料其格式為 address=email@address&comments=使用者輸入的意見 的一個字串。
    • 因此,我們需要利用 ParseInput 將字串轉換成如下的格式:
      address    email@address
      comments   使用者輸入的意見
      
      這種資料結構稱之為 hash,而 hash 中的第一個欄位一般稱之為 key,第二個欄位稱之為 value。Perl 用來代表具有 hash 結構的變數,會在變數名稱之前加上 %;例如,在 ParseInput 內 第三行,就宣告了一個名為 %input 的 hash 區域變數。從程式中, 我們也可以觀察到 %input$input 被視為兩個不同的 變數。
      在 ParseInput 中,它首先利用 splitaddress=email@address&comments=使用者輸入的意見 分成一個具有兩個 元素的陣列 @pair;兩個元素分別是 address=email@addresscomments=使用者輸入的意見;然後,再利用 splitaddress 指定為 key,而 email@address 指定為 value; 同樣的方式也套用在 @pair 陣列中其他的元素。至於,將 + 和 url-encoded characters 轉換成適當的字元也在 ParseInput 內完成。最後,把 hash 的結果回傳給 GetFormInput,而 GetFormInput 再把 hash 的結果回傳給 comments.pl

  3. comments.pl 的原始碼如下:
    #!/usr/local/bin/perl
    require 'forms-lib.pl';
    
    print "content-type: text/html\n\n";
    %input = &GetFormInput();
    $recipient = $input{'address'} || "jllu\@nchu.edu.tw";
    $message = $input{'comments'};
    $sender = $ENV{'HTTP_FROM'} || "jllu\@nchu.edu.tw";
    print <<EndofMessage;
    <html>
    <head><title>Comment Tests<title><head>
    <body>
    <h3>Your Comment is to be sent<h3>
    <pre>
    To: $recipient
    From: $sender
    Subject: Comments on your web page
    $message
    </pre>
    </body>
    </html>
    EndofMessage
    
    在取得 hash 結構 %input 之後,分別取得 address 和 comments 的 值的方式分別為 $input{'address'} 以及 $input{'comments'}。 最後,程式中還有一個值得說明的部分是 print <<EndofMessage 指的是 出現在這一行之後,一直到出現 EndofMessage 之間的字串都會被輸出(print)。








Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu

沒有留言:

張貼留言