Code

Refactor parts of the plugin:
[gosa.git] / 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("ppd_path") != ""){
39       $this->pathToPPD = $config->get_cfg_value("ppd_path");
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     /* It seams that we have an existing PPD path, so go on */
49     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
51       /* Load all available PPD files and sort them into an array */
52       $this->ppdManager= new ppdManager($this->pathToPPD);
53       $this->getPrinterReload ();
55       /* The user has already a valid PPD assigned
56        * Get some informations about this PPD
57        * and set it as selected. 
58        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
59        *     e.g. "/Compaq/Compaq-J1200.ppd" */
60       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
61         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
62         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
63           msg_dialog::display(_("PPD error"), sprintf(_("Cannot open PPD '%s'!"), $ppdfile), ERROR_DIALOG);
64         }else{
65           $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
66           if($ppdDesc){            
67             $selectedPPD = array(); 
68             $selectedPPD['name']   = $ppdDesc['name'];
69             $selectedPPD['link']   = $ppdfile;
70             $selectedPPD['ppd']    = $ppdDesc;
71           }    
72           $this->selectedPPD = $selectedPPD;
73         }
74       }
75     }
76   }
79   function execute()
80   {
81     /* Call parent execute */
82     plugin::execute();
84     /* Fill templating stuff */
85     $display= "";
86     $smarty= get_smarty();
87     $smarty->assign("ppdString", _("Can't get ppd informations."));
88     $smarty->assign("showOptions", "");
90     /* Check these paths */
91     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
93     /* If one of our required paths is not available, stop here and display some info */
94     foreach($paths as $path){
95     
96       /* Check if path is write/readable*/
97       $is_r = @is_readable($path);  
98       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
99         msg_dialog::display(_("Configuration error"), sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
101         /* Print out template */
102         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
103         return($display);
104       }
105     }
107     // PPD selection / upload / dialog handling 
109     /* Is there a new PPD file uploaded ? */
110     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
111       $file = ($_FILES['NewPPDFile']);
112       if($file['size'] != 0 ){
113         if($name = $this->AddPPD($file['tmp_name'])){
114           $this->SelectPPD($name); 
115         }
116       }else{
117         msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
118       }
119     }
121     /* Overwrite existing PPD file and select it as currently used for this object */
122     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
123       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
124         $this->SelectPPD($name);
125       }
126       $this->add_ppd_later = "";
127       $this->add_later_msg_dialog = NULL;
128     } 
130     /* Open a dialog that allow us to select different PPDs */
131     if(isset($_POST['SelectPPD'])){
132       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
133     }
135     /* The selection dialog fpr PPDs is canceled */
136     if(isset($_POST['ClosePPDSelection'])){
137       unset($this->dialog);
138       $this->dialog=FALSE;
139     }
141     /* Div Selection */ 
142     if((isset($_GET['act']))&&($_GET['act']=="use")){
143       $this->SelectPPD(base64_decode($_GET['id']));
144       unset($this->dialog);
145       $this->dialog=FALSE;
147     }
149     /* if a dialog is open, print the dialog instead of this class */
150     if(is_object($this->dialog)){
151       $display = $this->dialog->execute();
152       return($display);
153     }
155     // ENDE  PPD selection / upload / dialog handling 
157     /* Give smarty the information it needs */
158     $smarty->assign("ppdString" ,$this->getPPDInformation());
159     $tmp= $this->generateProperties();
160     if ($tmp == ""){
161       $smarty->assign("showOptions", 0);
162     } else {
163       $smarty->assign("showOptions", 1);
164       $smarty->assign("properties",$this->generateProperties());
165     }
167     /* Print out template */
168     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
169     return($display);
170   }
173   /* Select PPD */
174   function SelectPPD($name)
175   {
176     /* Replace base path we don't need it here 
177        The path we need looks like this : "/Vendor/ModellName.ppd"; 
178        thats all */
179     $name = preg_replace("#".$this->pathToPPD."#","",$name);
181     /* Intialise some base vars */
182     $AbsoluteSourceName       = $this->pathToPPD.$name;   
183     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
184     $Vendor                   = ""; // Vendor 
185     $Name                     = ""; // Name 
186     $Modell                   = ""; // Modell
187     $PrinterName              = ""; // The new name of the printer 
188     $PPDName                  = "";
189  
190     /* Force reload of config dialog */ 
191     $this->ppdConfig            = false;
192     $this->selectedPPD['link']  = false;
194     /* Get PPD informations and set vendor / modell / name */ 
195     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
196       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
197       return;
198     }
199     $ppdDesc  = $this->ppdManager->loadDescription($AbsoluteSourceName);
200     if($ppdDesc){
201       $Name   = $ppdDesc['name'];
202       $Vendor = $ppdDesc['manufacturer'];
203       $Model  = $ppdDesc['model'];
204     }    
206     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
207     $PPDName      = $Vendor."/".$PrinterName.".ppd";
208     
209     /* Create the vendors path, if it doesn't exists already */
210     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
211       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
212         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
213         return(false);
214       }
215     }
217     /* Create destination file handle */
218     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
219     if(!$fp){
220       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
221       return(false);
222     }
224     $str = file_get_contents($AbsoluteSourceName);
225     fputs($fp,$str);
226     @fclose($fp);
228     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
230     $tmp3['link']   =$PPDName;
231     $this->selectedPPD = $tmp3;
232     $this->getPrinterReload(); 
233     return($PPDName);
234   }
237   /* This function adds a new ppd file to the list of available ppds. 
238      All required paths and files will be created 
239       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
240   function AddPPD($_PathOnHdd,$overwrite = FALSE)
241   {
242     /* Check if file exists && is readable */
243     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
244       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
245       return(false);
246     }
247     
248     /* Reload list to detect changes e.g. a file has been deleted */
249     $this->getPrinterReload();
251     /* Get Description from ppd, & parse out some informations */   
252     $ppdDesc  = @$this->ppdManager->loadDescription($_PathOnHdd);
253     if($ppdDesc){
254       $name   = $ppdDesc['name'];
255       $vendor = $ppdDesc['manufacturer'];
256       $model  = $ppdDesc['model'];
257     }    
259     /* Check if parse was successfull */
260     if(empty($name) || empty($vendor)){
261       msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
262       return(false);
263     }
265     /* Prepare list of ppds */
266     if(!isset($this->ppdList[$vendor])){
267       $this->ppdList[$vendor] = array();
268     }
270     /* Create ppd file and fill in the source contents */
271     $ppdname      = $vendor."/".$name.".ppd";
272     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
273     $filename     = $this->pathToPPD.$ppdname;
274     $contents     = file_get_contents($_PathOnHdd);
277     /* Check if this ppd already exists */
278     $found = false;
279     foreach($this->ppdList[$vendor] as $key => $val){
280       if(preg_match("/".$model.".*/i",$key)){
281         $found = true;
282         if(!$overwrite){
283           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
284             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
285           }else{
286             $this->add_ppd_later = $_PathOnHdd."_back";
287             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
288                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
289           }
290           return;
291         }
292       }
293     }
295     /* Create the vendors path, if it doesn't exists already */
296     if(!is_dir($this->pathToPPD.$vendor)){
297       if(!(@mkdir($this->pathToPPD.$vendor))){
298         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
299         return(false);
300       }
301     }
302   
303     /* Open file handle */
304     $fp           = fopen($filename,"w+");
306     /* Check file handle & contents */
307     if(!$fp){
308       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
309       return;
310     }
311     if(empty($contents)){
312       msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
313       return;
314     }
315     
316     /* Fille file with data */
317     fputs($fp,$contents);
318     @fclose($fp);
320     /* Our job is done here */
321     return($ppdname);
322   }
325   /* This function reloads the list of available printers/vendors 
326      $this->ppdListHeader 
327      Compaq        => 1
328      $this->ppdList
329      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
330      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
331      ppd  => Compaq - Co    
332    */
333   function getPrinterReload()
334   {
335     if(is_readable($this->pathToPPD)){
336       $tmp = @$this->ppdManager->getPrinterList(true);
338       $this->ppdListHeader = $this->ppdList = array();
340       /* Sort all available files, and create header (Vendor index) */
341       foreach($tmp as $file=>$ppd){
342                 
343         if(preg_match("#".$this->pathToModified."#",$file)) continue;
345         if(!isset($this->ppdListHeader[$ppd['manufacturer']])){
346           $this->ppdListHeader[$ppd['manufacturer']]=0;
347         }
348        
349         $tmp3['name']   =$ppd['name'];
350         $tmp3['link']   =$file;
351         $tmp3['ppd']    =$ppd;
352         $this->ppdListHeader[$ppd['manufacturer']]++;
353         $this->ppdList[$ppd['manufacturer']][$ppd['name']]=$tmp3;
354       }
355     }
356   }
359   /* Save all options posted from ppd dialog */
360   function save_object()
361   {
362     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
363       return;
364     }
366     foreach($this->ppdConfig as $cat => $obj){
367       foreach($obj as $attr => $attributes){
368         if(isset($_POST[base64_encode($attributes['_name'])])){
369           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
370         }
371       }
372     }
373   }
376   /* Save modified ppd */
377   function save_ppd()
378   {
379     if($this->ppdManager){
380       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
381     }
382   }
385   /* Return selected ppd path, if none is selected then false */
386   function save()
387   {
388     /* return the selected PPD, and in future the selected options too */
389     return($this->pathToModified.$this->selectedPPD['link']);
390   }
393   /* Get Information for a single PPD entry 
394    * This will be shown on top of template
395    */
396   function getPPDInformation()
397   {
398     $str = "none";
399     if(!empty($this->selectedPPD)){
400       $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
401       $str = $ppdDesc['name'];
402     }
403     return($str) ; 
404   }
406   /* Display all options from the selected ppd file */
407   function generateProperties()
408   { 
409     /* Set Headline */
410     $str = "";
411     $feed= "";
413     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
415     /* If ppd exists and is readable */
416     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
418       /* If there is no initial Configuration, load it */
419       if($this->ppdConfig == false){
420         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
421       }
423       /* Create a table */
424       $str .= "<div style='padding-left:30px;'><table summary=''>";
426       /* Input all data to the table */
427       foreach($this->ppdConfig as $cat => $obj){
429         /* Add new category */
430         $str .= "<tr><td colspan='2'>$feed";
431         if ($feed == ""){
432           $feed= "<br>";
433         }
434         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
435         $str .= "</td></tr>";       
437         /* Add attributes of the current category */
438         foreach($obj as $attr => $settings){
440           /* Skip all entries beginning with _ */
441           if($attr[0] == "_") continue;  
443           /* Prepare data */
444           $values   = array();
445           $name     = $settings['_name'];
447           if (!isset($settings['_default'])){
448             $default  = "";
449           } else {
450             $default  = $settings['_default'];
451           }
453           $type     = $settings['_type'];
455           /* Add name to table */ 
456           $str .= "<tr><td style='padding-left:40px;'>\n";
457           $str .= $name."<br>\n";
458           $str .= "</td><td>\n";
460           /* Get all values */ 
461           foreach( $settings as $vname => $value){
462             if($vname[0] != "_"){
463               $values[$vname]= $value;
464             }
465           }
467           /* preparing Html output
468            * Supported types are PickOne/Boolean
469            */
471           /* If type is PickOne, create a select box */
472           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
474             $str  .=  "<select name='".base64_encode($name)."'>\n";
475             foreach($values as $optionKey => $value){
476               $selected = "";
477               if($optionKey == $default){
478                 $selected = " selected ";
479               }
480               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
481             }
482             $str  .=  "</select>\n";
484           }elseif($type == "Boolean"){
486             /* If type is Boolean & no values are given */
487             $str  .=  "<select name='".base64_encode($name)."'>\n";
488             if($default == "False"){
489               $str  .=    "<option value='True' >"._("True")."</option>\n";
490               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
491             }else{
492               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
493               $str  .=    "<option value='False' >"._("False")."</option>\n";
494             }          
495             $str  .=  "</select>\n";
497           }else{
498             msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
499           }
500           $str .= "</td></tr>\n";
501         }
502       }
503       $str .= "</table></div>\n";
504     }
505     return($str);
506   }
508   function removeModifiedPPD()
509   {
510     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
512     if(file_exists($path)){
513       if(is_writeable($path)){
514         if(!@unlink($path)){
515           msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
516         }
517       }else{
518         msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
519       }
520     }else{
521       msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
522     }
523   }
525   function update_ppd_url()
526   {
527     $this->SelectPPD("modified/".$this->selectedPPD['link']);
528     return("modified/".$this->selectedPPD['link']);
529   }
530   
531   function check()
532   {  
533     $message = plugin::check();
534     if(empty($this->selectedPPD['link'])){
535       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
536     }
537     return($message); 
538   }
540 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
541 ?>