[LON-CAPA-cvs] cvs: loncom /interface lonpdfupload.pm

onken onken@source.lon-capa.org
Fri, 03 Apr 2009 15:40:17 -0000


onken		Fri Apr  3 15:40:17 2009 EDT

  Modified files:              
    /loncom/interface	lonpdfupload.pm 
  Log:
  Upgrade for PDF-Forms. 
  
  Now only perl is used to read out PDF-Formdata. Before you copy lonpdfupload.pm in to your Apache-folder check the needed Steps below.
  
  ----------
  
  Enable PDF-Forms in LON-CAPA
  
  First you need to install the AcroTeX-education bundle from ctan.
  
  Get the package and unzip it:
  
      [root@loncapa ]# wget http://tug.ctan.org/get/macros/latex/contrib/acrotex.zip
      [root@loncapa ]# unzip acrotex.zip
  
  go into the acrotex-folder and install
  
      [root@loncapa ]# cd acrotex
      [root@loncapa acrotex]# latex acrotex.ins
  
  Now move the folder acrotex file into the latex path. You can easy find it by searching for "cite.sty" or some other tex-packages.
  
      [root@loncapa /]# locate cite.sty
      /usr/share/texmf/tex/latex/cite/cite.sty
      /usr/share/texmf/tex/latex/cite/drftcite.sty
      /usr/share/texmf/tex/latex/cite/overcite.sty
      On CentOS the latex path is: /usr/share/texmf/tex/latex/ (perhaps there is different to 
  
      [root@loncapa acrotex]# cd ..
      [root@loncapa ]# mv acrotex /usr/share/texmf/tex/latex/
  
  Remove the acrotex.zip
  
      [root@loncapa]# rm acrotex.zip
  
  After that you must rehash tex:
  
      [root@loncapa ]# texhash
  
  Now you are able to print PDF with Forms (Radiobutton-, Comboboxes-, Textfield based problems).
  
  The second thing to do is to enable the Upload-script lonpdfupload.pm. Before you can use it you have to install CAM::PDF for perl. It is available on CPAN so you can use the perl –MCPAN -eshell.
  
      [root@loncapa ~]# perl -MCPAN -eshell
  
      cpan shell -- CPAN exploration and modules installation (v1.7602)
      ReadLine support enabled
  
      cpan>install CAM::PDF 
      (…follow installation and also install the dependencies)
      cpan>exit
  
  Next you need to copy the upload-script from CVS to the LON-CAPA Apache folder.
  
      [root@loncapa ~]# cp [your-cvs-folder]/loncom/interface/lonpdfupload.pm /home/httpd/lib/perl/Apache/
      
  Now restart httpd:
      [root@loncapa ~]# /etc/init.d/httpd restart
  
  
  
  
Index: loncom/interface/lonpdfupload.pm
diff -u loncom/interface/lonpdfupload.pm:1.1 loncom/interface/lonpdfupload.pm:1.2
--- loncom/interface/lonpdfupload.pm:1.1	Tue Sep  9 13:56:44 2008
+++ loncom/interface/lonpdfupload.pm	Fri Apr  3 15:40:17 2009
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Publication Handler
 #
-# $Id: lonpdfupload.pm,v 1.1 2008/09/09 13:56:44 onken Exp $
+# $Id: lonpdfupload.pm,v 1.2 2009/04/03 15:40:17 onken Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -46,45 +46,48 @@
 use Apache::lonhomework;
 use LONCAPA::Enrollment;
 use LONCAPA::Configuration;
+use CAM::PDF;
 
 use strict;
 
 sub handler() {
-  my $r = shift;
+    my $r = shift;
 
-  #Testen ob der Benutzer ein gültiges Cookie besitzt
-  if(!&checkpermission($r)) {
-    return OK;
-  }
+    # check user permissions 
+    if(!&checkpermission($r)) {
+        # stop processing 
+        return OK;
+    }
 
-  $Apache::lonxml::request=$r;
-  $Apache::lonxml::debug=$env{'user.debug'};
-  $env{'request.uri'}=$r->uri;
- 
-  $r->content_type('text/html');
-  $r->send_http_header();
-  $r->print(&Apache::loncommon::start_page('Upload-PDF-Form'));
-
-  #lade die per POST gesendenten daten in env
-  &Apache::lonacc::get_posted_cgi($r);
-
-  if($env{'form.Uploaded'} && $env{'form.file'}) { 
-    #Upload-Formular wurde gesendet
-    $r->print(&processPDF);
-
-  } else { 
-    #erster Aufruf Upload-Formular wird ausgeben   
-    $r->print(&get_javascripts);
-    $r->print(&get_uploadform);
-
-  }
-
-  #&dumpenv($r); #debug -> prints the environment
-  $r->print("<br /><a href='/adm/navmaps'>".&mt("Navigate Contents")."</a><br />");
-  $r->print("  </body>\n</html>\n");
-  return OK;
+    $Apache::lonxml::request=$r;
+    $Apache::lonxml::debug=$env{'user.debug'};
+
+    $env{'request.uri'}=$r->uri;
+    $r->content_type('text/html');
+    $r->send_http_header();
+    $r->print(&Apache::loncommon::start_page('Upload-PDF-Form'));
+
+    #load post data into environment
+    &Apache::lonacc::get_posted_cgi($r);
+
+    # if a file was upload
+    if($env{'form.Uploaded'} && $env{'form.file'}) {
+        $r->print(&processPDF);
+    } else { 
+        # print upload form
+        $r->print(&get_javascripts);
+        $r->print(&get_uploadform);
+    }
+
+    #link to course-content
+    $r->print("    <br />\n    <a href='/adm/navmaps'>\n      ".&mt("Navigate Contents")."\n    </a>\n    <br />");
+
+    #&dumpenv($r); #debug -> prints the environment
+    $r->print("  </body> \n</html>\n");
+    return OK;
 }
 
+
 sub checkpermission() {
     my $r = shift;
     if (! &LONCAPA::loncgi::check_cookie_and_load_env()) {
@@ -92,10 +95,14 @@
 Content-type: text/html
 
 <html>
-<head><title>Bad Cookie</title></head>
-<body>
-Your cookie information is incorrect.
-</body>
+  <head>
+    <title>
+      Bad Cookie
+    </title>
+  </head>
+  <body>
+    Your cookie information is incorrect.
+  </body>
 </html>
 END
 ;
@@ -108,25 +115,29 @@
 
 
 sub get_javascripts() {
-    my $result = '  <script type="text/javascript">';
+    
+    my $message = &mt('Please choose a PDF-File');
 
-    # JavaScript prüft die Datei Endung der hochzuladenden Datei
-    $result .= <<END
+    # simple test if the upload ends with ".pdf"
+    # it's only for giving a message to the user
+    my $result .= <<END
+  <script type="text/javascript">
     function checkFilename(form) {
         var fileExt = form.file.value;
         fileExt = fileExt.match(/[.]pdf\$/g);
         if(fileExt) {
             return true;
         }
-        alert("Bitte geben Sie nur ein PDF an.")
+        alert("$message");
         return false;
     }
+  </script>
 END
 ;
-    $result .= "  </script>";
     return $result; 
 }
 
+
 sub get_uploadform() {
     my $result = <<END
     <p height='25'> 
@@ -168,53 +179,35 @@
 }
 
 sub processPDF {
-    my $result = ();
-    my @pdfdata = ();
+    my $result = ();  # message for Browser
+    my @pdfdata = (); # answers from PDF-Forms
     
-    @pdfdata = &get_pdf_data;
+    @pdfdata = &get_pdf_data(); # get answers from PDF-Form
     
     if (scalar @pdfdata) {    
-        $result .= &grade_pdf(@pdfdata);
+        &grade_pdf(@pdfdata);
     } else {
-        $result .= "<h2>".&mt("reading PDF-formfields: failed")."</h2>";
+        $result .= "<h2>".&mt("Can't find any valid PDF-formfields")."</h2>";
     }
 }
 
 sub get_pdf_data() {
     my @data = ();
-    my $file_path = "/home/httpd/pdfspool/".time."_".
-                    int(rand(100000)).".pdf";
-    my $file_data = $file_path;
-       $file_data =~ s/(.*)\..*/$1.data/;
-
-    # zwischenspeichern der hochgeladenen PDF
-    my $temp_file = Apache::File->new('>'.$file_path);
-    binmode($temp_file);
-    print $temp_file $env{'form.file'};
-    $temp_file->close;
-      
-    #Java PDF-Auslese-Programm starten
-    my @command = ("java", "-jar", 
-                   "/home/httpd/pdfspool/dumpPDF.jar", 
-                   $file_path, $file_data);
-    system(@command);
-    
+    my $pdf = CAM::PDF->new($env{'form.file'});
 
-    #Einlesen der extrahierten Daten
-    $temp_file = new IO::File->new('<'.$file_data);
-    while (defined (my $line = $temp_file->getline())) {
-        push(@data, $line);
-    }
-    $temp_file->close;
-    undef($temp_file);
+    my @formFields = $pdf->getFormFieldList(); #get names of formfields
+    
+    foreach my $field (@formFields) {
+	my $dict = $pdf->getFormFieldDict($pdf->getFormField($field)); # get formfield dictonary
 
-    #zwischengespeicherte Dateien loeschen
-    if( -e $file_path) {
-#        unlink($file_path);
-    }
-    if( -e $file_data) {
-#        unlink($file_data); 
-    }
+        #
+        # this is nessesary 'cause CAM::PDF has a problem with formfieldnames which include a
+        # dot in fieldnames. So a fieldname like "i.am.aFormfield" will offer three fieldnames "i", "i.am" 
+        # and "i.am.aFormfield". The fragmentary names keep no values and will be ignored.
+        if($dict->{'V'}) {
+            push(@data, $field."?". $dict->{'V'}{'value'}); #binding fieldname with value
+        }
+    } 
     return @data;
 }
 
@@ -232,10 +225,10 @@
     $result .= "<table width='80%'>\n";
     foreach my $entry (sort(@pdfdata)) {
         if ($entry =~ /^meta.*/) {
-            $debug .= 'found: metadata -> '.$entry;
-            my ($label, $value) = split('\?', $entry);
+            $debug .= 'found: metadata -> '.$entry . "<br />";
+            my ($label, $value) = ($entry =~ /^([^?]*)\?(.*)/);
             my ($domain, $user) = split('&', $value);
-            $user =~ s/(.*)\n/$1/;
+            $user =~ s/(.*)\n/$1/; #TODO find an other way
             
             if($user ne $env{'user.name'} or  $domain ne $env{'user.domain'}) {
                 return "<pre>".&mt('Wrong username in PDF-File').": $user $domain -> $env{'user.domain'} $env{'user.name'} </pre>";    
@@ -243,7 +236,7 @@
 
         } elsif($entry =~ /^upload.*/)  {
             $debug .= 'found: a problem -> '.$entry;
-            my ($label, $value) = split('\?', $entry);
+            my ($label, $value) = ($entry =~ /^([^?]*)\?(.*)/);
             my ($symb, $part, $type, $HWVAL) = split('&', $label);
             my ($map,$id,$resource)=&Apache::lonnet::decode_symb($symb);  
             $value =~ s/(.*)\n/$1/; 
@@ -268,8 +261,8 @@
             $debug .= 'found: -> '.$entry;
             next;
         }
-        #$result = $debug;
     }
+    $result .= $debug;
 
     foreach my $key (sort (keys %problems)) {
         my %problem = %{$problems{$key}};