Code

85e23f1e4625c3e0ce3acc9c756a8540740cef2a
[gosa.git] / trunk / gosa-plugins / goto / admin / systems / ppd / class_printerPPDDialog.inc
1 <?php
3 class printerPPDDialog extends plugin
4 {
5   /* attribute list for save action */
6   var $ignore_account       = TRUE;
7   var $attributes           = array("cn");
8   var $objectclasses        = array("whatever");
10   /* PPD Handling */
11   var $selectedPPD          = false;        // e.g. /vendor/device.ppd 
12   var $ppdManager           = false;        // new ppdManager;
13   var $ppdConfig            = false;        // $this->ppdManager->loadProperties($this->selectedPPD['link']);
14   var $ppdList              = array();      // Contains all Printer models
15   var $ppdListHeader        = array();      // Contains all printer vendors
17   /* Paths */
18   var $pathToPPD            = "";           // Base path, defined in gosa.conf e.g. "/var/spool/ppd/"
19   var $pathToModified       = "modified/";  // used to store the modified ppds  
20       
21   /* Object Info */
22   var $cn                   = "" ;          // Used to tag the ppds modified by the printer object, 
24   /* If there is already a ppd file for the same type of printer, 
25    *  remember the path to ppd file and display a dialog which allows 
26    *  to overwrite the current ppd file. 
27    */
28   var $add_ppd_later            = "";
29   var $add_later_msg_dialog     = NULL;
31   function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
32   {
33     plugin::plugin ($config, $dn);
34     $this->depselect = $this->config->current['BASE'];
36     /* Get PPD path and remove double //, and add trailing /  */
37     $config = session::get('config');
38     if($config->get_cfg_value("ppdPath") != ""){
39       $this->pathToPPD = $config->get_cfg_value("ppdPath");
40       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
41       if(!preg_match("/\/$/",$this->pathToPPD)){
42         $this->pathToPPD = $this->pathToPPD."/";
43       }
44     }else{
45       $this->pathToPPD = "";
46     }
48     /* Check if ppdPath is set in gosa.conf. 
49      */
50     if(empty($this->pathToPPD)){
51       msg_dialog::display(_("Configuration error"), msgPool::invalidConfigurationAttribute("ppdPath"), ERROR_DIALOG);
52     }
54     /* It seams that we have an existing PPD path, so go on */
55     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
57       /* Load all available PPD files and sort them into an array */
58       $this->ppdManager= new ppdManager($this->pathToPPD);
59       $this->getPrinterReload ();
61       /* The user has already a valid PPD assigned
62        * Get some informations about this PPD
63        * and set it as selected. 
64        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
65        *     e.g. "/Compaq/Compaq-J1200.ppd" */
66       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
67         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
68         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
69           msg_dialog::display(_("PPD error"), sprintf(_("Cannot open PPD '%s'!"), $ppdfile), ERROR_DIALOG);
70         }else{
71           $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
72           if($ppdDesc){            
73             $selectedPPD = array(); 
74             $selectedPPD['name']   = $ppdDesc['name'];
75             $selectedPPD['link']   = $ppdfile;
76             $selectedPPD['ppd']    = $ppdDesc;
77           }    
78           $this->selectedPPD = $selectedPPD;
79         }
80       }
81     }
82   }
85   function execute()
86   {
87     /* Call parent execute */
88     plugin::execute();
90     /* Fill templating stuff */
91     $display= "";
92     $smarty= get_smarty();
93     $smarty->assign("ppdString", _("Can't get ppd informations."));
94     $smarty->assign("showOptions", "");
95     $smarty->assign("path_valid", TRUE);
97     if(empty($this->pathToPPD)){
99         /* Print out template */
100         $smarty->assign("path_valid", FALSE);
101         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
102         return($display);
103     }
105     /* Check these paths */
106     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
108     /* If one of our required paths is not available, stop here and display some info */
109     foreach($paths as $path){
110     
111       /* Check if path is write/readable*/
112       $is_r = @is_readable($path);  
113       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
114         msg_dialog::display(_("Configuration error"), sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
116         /* Print out template */
117         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
118         return($display);
119       }
120     }
122     // PPD selection / upload / dialog handling 
124     /* Is there a new PPD file uploaded ? */
125     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
126       $file = ($_FILES['NewPPDFile']);
127       if($file['size'] != 0 ){
128         if($name = $this->AddPPD($file['tmp_name'])){
129           $this->SelectPPD($name); 
130         }
131       }else{
132         msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
133       }
134     }
136     /* Overwrite existing PPD file and select it as currently used for this object */
137     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
138       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
139         $this->SelectPPD($name);
140       }
141       $this->add_ppd_later = "";
142       $this->add_later_msg_dialog = NULL;
143     } 
145     /* Open a dialog that allow us to select different PPDs */
146     if(isset($_POST['SelectPPD'])){
147       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
148     }
150     /* The selection dialog fpr PPDs is canceled */
151     if(isset($_POST['ClosePPDSelection'])){
152       unset($this->dialog);
153       $this->dialog=FALSE;
154     }
156     /* Div Selection */ 
157     if((isset($_GET['act']))&&($_GET['act']=="use")){
158       $this->SelectPPD(base64_decode($_GET['id']));
159       unset($this->dialog);
160       $this->dialog=FALSE;
162     }
164     /* if a dialog is open, print the dialog instead of this class */
165     if(is_object($this->dialog)){
166       $display = $this->dialog->execute();
167       return($display);
168     }
170     // ENDE  PPD selection / upload / dialog handling 
172     /* Give smarty the information it needs */
173     $smarty->assign("ppdString" ,$this->getPPDInformation());
174     $tmp= $this->generateProperties();
175     if ($tmp == ""){
176       $smarty->assign("showOptions", 0);
177     } else {
178       $smarty->assign("showOptions", 1);
179       $smarty->assign("properties",$this->generateProperties());
180     }
182     /* Print out template */
183     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
184     return($display);
185   }
188   /* Select PPD */
189   function SelectPPD($name)
190   {
191     /* Replace base path we don't need it here 
192        The path we need looks like this : "/Vendor/ModellName.ppd"; 
193        thats all */
194     $name = preg_replace("#".$this->pathToPPD."#","",$name);
196     /* Intialise some base vars */
197     $AbsoluteSourceName       = $this->pathToPPD.$name;   
198     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
199     $Vendor                   = ""; // Vendor 
200     $Name                     = ""; // Name 
201     $Modell                   = ""; // Modell
202     $PrinterName              = ""; // The new name of the printer 
203     $PPDName                  = "";
204  
205     /* Force reload of config dialog */ 
206     $this->ppdConfig            = false;
207     $this->selectedPPD['link']  = false;
209     /* Get PPD informations and set vendor / modell / name */ 
210     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
211       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
212       return;
213     }
214     $ppdDesc  = $this->ppdManager->loadDescription($AbsoluteSourceName);
215     if($ppdDesc){
216       $Name   = $ppdDesc['name'];
217       $Vendor = $ppdDesc['manufacturer'];
218       $Model  = $ppdDesc['model'];
219     }    
221     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
222     $PPDName      = $Vendor."/".$PrinterName.".ppd";
223     
224     /* Create the vendors path, if it doesn't exists already */
225     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
226       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
227         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
228         return(false);
229       }
230     }
232     /* Create destination file handle */
233     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
234     if(!$fp){
235       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
236       return(false);
237     }
239     $str = file_get_contents($AbsoluteSourceName);
240     fputs($fp,$str);
241     @fclose($fp);
243     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
245     $tmp3['link']   =$PPDName;
246     $this->selectedPPD = $tmp3;
247     $this->getPrinterReload(); 
248     return($PPDName);
249   }
252   /* This function adds a new ppd file to the list of available ppds. 
253      All required paths and files will be created 
254       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
255   function AddPPD($_PathOnHdd,$overwrite = FALSE)
256   {
257     /* Check if file exists && is readable */
258     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
259       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
260       return(false);
261     }
262     
263     /* Reload list to detect changes e.g. a file has been deleted */
264     $this->getPrinterReload();
266     /* Get Description from ppd, & parse out some informations */   
267     $ppdDesc  = @$this->ppdManager->loadDescription($_PathOnHdd);
268     if($ppdDesc){
269       $name   = $ppdDesc['name'];
270       $vendor = $ppdDesc['manufacturer'];
271       $model  = $ppdDesc['model'];
272     }    
274     /* Check if parse was successfull */
275     if(empty($name) || empty($vendor)){
276       msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
277       return(false);
278     }
280     /* Prepare list of ppds */
281     if(!isset($this->ppdList[$vendor])){
282       $this->ppdList[$vendor] = array();
283     }
285     /* Create ppd file and fill in the source contents */
286     $ppdname      = $vendor."/".$name.".ppd";
287     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
288     $filename     = $this->pathToPPD.$ppdname;
289     $contents     = file_get_contents($_PathOnHdd);
292     /* Check if this ppd already exists */
293     $found = false;
294     foreach($this->ppdList[$vendor] as $key => $val){
295       if(preg_match("/".$model.".*/i",$key)){
296         $found = true;
297         if(!$overwrite){
298           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
299             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
300           }else{
301             $this->add_ppd_later = $_PathOnHdd."_back";
302             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
303                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
304           }
305           return;
306         }
307       }
308     }
310     /* Create the vendors path, if it doesn't exists already */
311     if(!is_dir($this->pathToPPD.$vendor)){
312       if(!(@mkdir($this->pathToPPD.$vendor))){
313         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
314         return(false);
315       }
316     }
317   
318     /* Open file handle */
319     $fp           = fopen($filename,"w+");
321     /* Check file handle & contents */
322     if(!$fp){
323       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
324       return;
325     }
326     if(empty($contents)){
327       msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
328       return;
329     }
330     
331     /* Fille file with data */
332     fputs($fp,$contents);
333     @fclose($fp);
335     /* Our job is done here */
336     return($ppdname);
337   }
340   /* This function reloads the list of available printers/vendors 
341      $this->ppdListHeader 
342      Compaq        => 1
343      $this->ppdList
344      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
345      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
346      ppd  => Compaq - Co    
347    */
348   function getPrinterReload()
349   {
350     if(is_readable($this->pathToPPD)){
351       $tmp = @$this->ppdManager->getPrinterList(true);
353       $this->ppdListHeader = $this->ppdList = array();
355       /* Sort all available files, and create header (Vendor index) */
356       foreach($tmp as $file=>$ppd){
357                 
358         if(preg_match("#".$this->pathToModified."#",$file)) continue;
360         if(!isset($this->ppdListHeader[$ppd['manufacturer']])){
361           $this->ppdListHeader[$ppd['manufacturer']]=0;
362         }
363        
364         $tmp3['name']   =$ppd['name'];
365         $tmp3['link']   =$file;
366         $tmp3['ppd']    =$ppd;
367         $this->ppdListHeader[$ppd['manufacturer']]++;
368         $this->ppdList[$ppd['manufacturer']][$ppd['name']]=$tmp3;
369       }
370     }
371   }
374   /* Save all options posted from ppd dialog */
375   function save_object()
376   {
377     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
378       return;
379     }
381     foreach($this->ppdConfig as $cat => $obj){
382       foreach($obj as $attr => $attributes){
383         if(isset($_POST[base64_encode($attributes['_name'])])){
384           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
385         }
386       }
387     }
388   }
391   /* Save modified ppd */
392   function save_ppd()
393   {
394     if($this->ppdManager){
395       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
396     }
397   }
400   /* Return selected ppd path, if none is selected then false */
401   function save()
402   {
403     /* return the selected PPD, and in future the selected options too */
404     return($this->pathToModified.$this->selectedPPD['link']);
405   }
408   /* Get Information for a single PPD entry 
409    * This will be shown on top of template
410    */
411   function getPPDInformation()
412   {
413     $str = "none";
414     if(!empty($this->selectedPPD)){
415       $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
416       $str = $ppdDesc['name'];
417     }
418     return($str) ; 
419   }
421   /* Display all options from the selected ppd file */
422   function generateProperties()
423   { 
424     /* Set Headline */
425     $str = "";
426     $feed= "";
428     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
430     /* If ppd exists and is readable */
431     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
433       /* If there is no initial Configuration, load it */
434       if($this->ppdConfig == false){
435         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
436       }
438       /* Create a table */
439       $str .= "<div style='padding-left:30px;'><table summary=''>";
441       /* Input all data to the table */
442       foreach($this->ppdConfig as $cat => $obj){
444         /* Add new category */
445         $str .= "<tr><td colspan='2'>$feed";
446         if ($feed == ""){
447           $feed= "<br>";
448         }
449         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
450         $str .= "</td></tr>";       
452         /* Add attributes of the current category */
453         foreach($obj as $attr => $settings){
455           /* Skip all entries beginning with _ */
456           if($attr[0] == "_") continue;  
458           /* Prepare data */
459           $values   = array();
460           $name     = $settings['_name'];
462           if (!isset($settings['_default'])){
463             $default  = "";
464           } else {
465             $default  = $settings['_default'];
466           }
468           $type     = $settings['_type'];
470           /* Add name to table */ 
471           $str .= "<tr><td style='padding-left:40px;'>\n";
472           $str .= $name."<br>\n";
473           $str .= "</td><td>\n";
475           /* Get all values */ 
476           foreach( $settings as $vname => $value){
477             if($vname[0] != "_"){
478               $values[$vname]= $value;
479             }
480           }
482           /* preparing Html output
483            * Supported types are PickOne/Boolean
484            */
486           /* If type is PickOne, create a select box */
487           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
489             $str  .=  "<select name='".base64_encode($name)."'>\n";
490             foreach($values as $optionKey => $value){
491               $selected = "";
492               if($optionKey == $default){
493                 $selected = " selected ";
494               }
495               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
496             }
497             $str  .=  "</select>\n";
499           }elseif($type == "Boolean"){
501             /* If type is Boolean & no values are given */
502             $str  .=  "<select name='".base64_encode($name)."'>\n";
503             if($default == "False"){
504               $str  .=    "<option value='True' >"._("True")."</option>\n";
505               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
506             }else{
507               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
508               $str  .=    "<option value='False' >"._("False")."</option>\n";
509             }          
510             $str  .=  "</select>\n";
512           }else{
513             msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
514           }
515           $str .= "</td></tr>\n";
516         }
517       }
518       $str .= "</table></div>\n";
519     }
520     return($str);
521   }
523   function removeModifiedPPD()
524   {
525     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
527     if(file_exists($path)){
528       if(is_writeable($path)){
529         if(!@unlink($path)){
530           msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
531         }
532       }else{
533         msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
534       }
535     }else{
536       msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
537     }
538   }
540   function update_ppd_url()
541   {
542     $this->SelectPPD("modified/".$this->selectedPPD['link']);
543     return("modified/".$this->selectedPPD['link']);
544   }
545   
546   function check()
547   {  
548     $message = plugin::check();
549     if(empty($this->selectedPPD['link'])){
550       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
551     }
552     return($message); 
553   }
555 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
556 ?>