Code

Reworked the printer ppd dialog:
[gosa.git] / plugins / admin / systems / class_printerPPDDialog.inc
1 <?php
3 class printerPPDDialog extends plugin
4 {
5   /* CLI vars */
6   var $cli_summary          = "Manage server basic objects";
7   var $cli_description      = "Some longer text\nfor help";
8   var $cli_parameters       = array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10   /* attribute list for save action */
11   var $ignore_account       = TRUE;
12   var $attributes           = array("cn");
13   var $objectclasses        = array("whatever");
15   /* PPD Handling */
16   var $selectedPPD          = false;        // e.g. /vendor/device.ppd 
17   var $ppdManager           = false;        // new ppdManager;
18   var $ppdConfig            = false;        // $this->ppdManager->loadProperties($this->selectedPPD['link']);
19   var $ppdList              = array();      // Contains all Printer models
20   var $ppdListHeader        = array();      // Contains all printer vendors
22   /* Paths */
23   var $pathToPPD            = "";           // Base path, defined in gosa.conf e.g. "/var/spool/ppd/"
24   var $pathToModified       = "modified/";  // used to store the modified ppds  
25       
26   /* Object Info */
27   var $cn                   = "" ;          // Used to tag the ppds modified by the printer object, 
28   var $dialog               = NULL;         // Contains sub dialogs 
30   function printerPPDDialog ($config, $dn= NULL,$ppdfile=NULL )
31   {
32     plugin::plugin ($config, $dn);
33     $this->depselect = $this->config->current['BASE'];
35     /* Get PPD path and remove double //, and add trailing /  */
36     if(isset($_SESSION['config']->data['MAIN']['PPD_PATH'])){
37       $this->pathToPPD = $_SESSION['config']->data['MAIN']['PPD_PATH'];
38       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
39       if(!preg_match("/\/$/",$this->pathToPPD)){
40         $this->pathToPPD = $this->pathToPPD."/";
41       }
42     }else{
43       $this->pathToPPD = "";
44     }
46     /* It seams that we have an existing PPD path, so go on */
47     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
49       /* Load all available PPD files and sort them into an array */
50       require_once ("class_ppdManager.inc");
51       $this->ppdManager= new ppdManager($this->pathToPPD);
52       $tmp = $this->ppdManager->getPrinterList();
54       /* Sort all available files, and create header (Vendor index) */
55       foreach($tmp as $file=>$ppd){
56         $tmp2 = split("\n",$ppd);
57         if(!isset($this->ppdListHeader[$tmp2[0]])){
58           $this->ppdListHeader[$tmp2[0]]=0;
59         }
60         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
61         $tmp3['link']   =preg_replace("/".str_replace("/","\/",$this->pathToPPD)."/i","",$file);
62         $tmp3['ppd']    =$ppd;
63         $this->ppdListHeader[$tmp2[0]]++;
64         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
65       }
67       /* The user has already a valid PPD assigned
68        * Get some informations about this PPD
69        * and set it as selected. 
70        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
71        *     e.g. "/Compaq/Compaq-J1200.ppd" */
72       if(($ppdfile!= NULL)&&(strlen($ppdfile)>0)){
73         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
74         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
75           print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
76         }else{
77           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
78           if($res){
79             $tmp = split("\n",$res);
80             $tmp3 = array(); 
81             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
82             $tmp3['link']   = $ppdfile;
83             $tmp3['ppd']    = $res;
84           }    
85           $this->selectedPPD = $tmp3;
86         }
87       }
88     }
89   }
93   function execute()
94   {
95     /* Call parent execute */
96     plugin::execute();
98     /* Fill templating stuff */
99     $display= "";
100     $smarty= get_smarty();
101     $smarty->assign("ppdString", _("Can't get ppd informations."));
102     $smarty->assign("showOptions", "");
104     /* Check these paths */
105     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
107     /* If one of our required paths is not available, stop here and display some info */
108     foreach($paths as $path){
109     
110       /* Check if path is write/readable*/
111       $is_r = @is_readable($path);  
112       if((!is_dir($path))||(empty($path)) || (!$is_r)){
113         print_red(sprintf(_("The specified path '%s' which results from PPD_PATH in your gosa.conf is invalid,".
114                             " can't read/write any ppd informations."),$path));
115         /* Print out template */
116         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
117         return($display);
118       }
119     }
121     /* Is there a new PPD file uploaded ? */
122     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
123       $file = ($_FILES['NewPPDFile']);
124       if($file['size'] != 0 ){
125         if($name = $this->AddPPD($file['tmp_name'])){
126           $this->SelectPPD($name); 
127         }
128       }else{
129         print_red(_("Please specify a valid ppd file."));
130       }
131     }
134     /* Open a dialog that allow us to select different PPDs
135      */
136     if(isset($_POST['SelectPPD'])){
137       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
138     }
140     /* The selection dialog fpr PPDs is canceled
141      */
142     if(isset($_POST['ClosePPDSelection'])){
143       unset($this->dialog);
144       $this->dialog=NULL;
145     }
147     /* A new PPDs was selected in the PPDs selection Dialog
148      * Perform a Check. If everything is fine, use the new PPD.
149      */
150     if(isset($_POST['SavePPDSelection'])){
151       if(!isset($_POST['PPDselection'])){
152         print_red(_("Please select a valid ppd."));
153       }else{
154         $this->SelectPPD($_POST['PPDselection']);
155         unset($this->dialog);
156         $this->dialog=NULL;
157       }
158     }
160     /* Div Selection */ 
161     if((isset($_GET['act']))&&($_GET['act']=="use")){
162       $this->SelectPPD(base64_decode($_GET['id']));
163       unset($this->dialog);
164       $this->dialog=NULL;
166     }
168     /* if a dialog is open, print the dialog instead of this class
169      */
170     if($this->dialog!=NULL){
171       $display = $this->dialog->execute();
172       return($display);
173     }
175     /* Give smarty the information it needs */
176     $smarty->assign("ppdString" ,$this->getPPDInformation());
177     $tmp= $this->generateProperties();
178     if ($tmp == ""){
179       $smarty->assign("showOptions", 0);
180     } else {
181       $smarty->assign("showOptions", 1);
182       $smarty->assign("properties",$this->generateProperties());
183     }
185     /* Print out template */
186     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
187     return($display);
188   }
191   /* Select PPD */
192   function SelectPPD($name)
193   {
194     /* Replace base path we don't need it here 
195        The path we need looks like this : "/Vendor/ModellName.ppd"; 
196        thats all */
197     $name = preg_replace("#".$this->pathToPPD."#","",$name);
199     /* Intialise some base vars */
200     $AbsoluteSourceName       = $this->pathToPPD.$name;   
201     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
202     $Vendor                   = ""; // Vendor 
203     $Name                     = ""; // Name 
204     $Modell                   = ""; // Modell
205     $PrinterName              = ""; // The new name of the printer 
206     $PPDName                  = "";
207  
208     /* Force reload of config dialog */ 
209     $this->ppdConfig            = false;
210     $this->selectedPPD['link']  = false;
212     /* Get PPD informations and set vendor / modell / name */ 
213     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
214       print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));   
215       return;
216     }
217     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
218     if($res){
219       $tmp = split("\n",$res);
220       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
221       $Vendor = trim($tmp[0]);
222       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
223     }    
225     $PrinterName  = $this->cn."-".$Name; 
226     $PPDName      = $Vendor."/".$PrinterName.".ppd";
227     
228     /* Create the vendors path, if it doesn't exists already */
229     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
230       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
231         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
232         return(false);
233       }
234     }
236     /* Create destination file handle */
237     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
238     if(!$fp){
239       print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
240       return(false);
241     }
243     $str = file_get_contents($AbsoluteSourceName);
244     fputs($fp,$str);
245     @fclose($fp);
247     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
249     $tmp3['link']   =$PPDName;
250     $this->selectedPPD = $tmp3;
251     $this->getPrinterReload(); 
252     return($PPDName);
253   }
256   /* This function adds a new ppd file to the list of available ppds. 
257      All required paths and files will be created 
258       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
259   function AddPPD($_PathOnHdd)
260   {
261     /* Check if file exists && is readable */
262     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
263       print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
264       return(false);
265     }
266     
267     /* Reload list to detect changes e.g. a file has been deleted */
268     $this->getPrinterReload();
270     /* Get Description from ppd, & parse out some informations */   
271     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
272     if($res){
273       $tmp = split("\n",$res);
274       $name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
275       $vendor = trim($tmp[0]);
276       $model  = trim(preg_replace("/".$vendor."/","",$name));
277     }    
279     /* Check if parse was successfull */
280     if(empty($name) || empty($vendor)){
281       print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
282       return(false);
283     }
285     /* Prepare list of ppds */
286     if(!isset($this->ppdList[$vendor])){
287       $this->ppdList[$vendor] = array();
288     }
290     /* Check if this ppd already exists */
291     $found = false;
292     foreach($this->ppdList[$vendor] as $key => $val){
293       if(preg_match("/".$model.".*/i",$key)){
294         $found = true;
295         print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
296         return;
297       }
298     }
300     /* Create the vendors path, if it doesn't exists already */
301     if(!is_dir($this->pathToPPD.$vendor)){
302       if(!(@mkdir($this->pathToPPD.$vendor))){
303         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
304         return(false);
305       }
306     }
307   
308     /* Create ppd file and fill in the source contents */
309     $ppdname      = $vendor."/".$name.".ppd";
310     $filename     = $this->pathToPPD.$ppdname;
311     $fp           = fopen($filename,"w+");
312     $contents     = file_get_contents($_PathOnHdd);
314     /* Check file handle & contents */
315     if(!$fp){
316       print_red(sprintf(_("Can't save file '%s'."),$filename));
317       return;
318     }
319     if(empty($contents)){
320       print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
321       return;
322     }
323     
324     /* Fille file with data */
325     fputs($fp,$contents);
326     @fclose($fp);
328     /* Our job is done here */
329     return($ppdname);
330   }
333   /* This function reloads the list of available printers/vendors 
334      $this->ppdListHeader 
335      Compaq        => 1
336      $this->ppdList
337      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
338      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
339      ppd  => Compaq - Co    
340    */
341   function getPrinterReload()
342   {
343     $tmp = $this->ppdManager->getPrinterList(true);
345     $this->ppdListHeader = $this->ppdList = array();
347     /* Sort all available files, and create header (Vendor index) */
348     foreach($tmp as $file=>$ppd){
350       if(preg_match("#".$this->pathToModified."#",$file)) continue;
352       $tmp2 = split("\n",$ppd);
353       if(!isset($this->ppdListHeader[$tmp2[0]])){
354         $this->ppdListHeader[$tmp2[0]]=0;
355       }
356       $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
357       $tmp3['link']   =$file;
358       $tmp3['ppd']    =$ppd;
359       $this->ppdListHeader[$tmp2[0]]++;
360       $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
361     }
362   }
365   /* Save all options posted from ppd dialog */
366   function save_object()
367   {
368     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
369       return;
370     }
372     foreach($this->ppdConfig as $cat => $obj){
373       foreach($obj as $attr => $attributes){
374         if(isset($_POST[base64_encode($attributes['_name'])])){
375           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
376         }
377       }
378     }
379   }
382   /* Save modified ppd */
383   function save_ppd(){
384     if($this->ppdManager){
385       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
386     }
387   }
389   /* Return selected ppd path, if none is selected then false */
390   function save()
391   {
392     /* return the selected PPD, and in future the selected options too */
393     return($this->pathToModified.$this->selectedPPD['link']);
394   }
396   /* Get Information for a single PPD entry 
397    * This will be shown on top of template
398    */
399   function getPPDInformation()
400   {
401     $str = "none";
402     if(!empty($this->selectedPPD)){
403       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
404     }
405     return($str) ; 
406   }
408   /* Display all options from the selected ppd file */
409   function generateProperties()
410   { 
411     /* Set Headline */
412     $str = "";
413     $feed= "";
415     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
417     /* If ppd exists and is readable */
418     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
420       /* If there is no initial Configuration, load it */
421       if($this->ppdConfig == false){
422         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
423       }
425       /* Create a table */
426       $str .= "<div style='padding-left:30px;'><table summary=''>";
428       /* Input all data to the table */
429       foreach($this->ppdConfig as $cat => $obj){
431         /* Add new category */
432         $str .= "<tr><td colspan='2'>$feed";
433         if ($feed == ""){
434           $feed= "<br>";
435         }
436         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
437         $str .= "</td></tr>";       
439         /* Add attributes of the current category */
440         foreach($obj as $attr => $settings){
443           /* Skip all entries beginning with _ */
444           if($attr[0] == "_") continue;  
446           /* Prepare data */
447           $values   = array();
448           $name     = $settings['_name'];
449           $default  = $settings['_default'];
450           $type     = $settings['_type'];
452           /* Add name to table */ 
453           $str .= "<tr><td style='padding-left:40px;'>\n";
454           $str .= $name."<br>\n";
455           $str .= "</td><td>\n";
457           /* Get all values */ 
458           foreach( $settings as $vname => $value){
459             if($vname[0] != "_"){
460               $values[$vname]= $value;
461             }
462           }
464           /* preparing Html output
465            * Supported types are PickOne/Boolean
466            */
468           /* If type is PickOne, create a select box */
469           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
471             $str  .=  "<select name='".base64_encode($name)."'>\n";
472             foreach($values as $optionKey => $value){
473               $selected = "";
474               if($optionKey == $default){
475                 $selected = " selected ";
476               }
477               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
478             }
479             $str  .=  "</select>\n";
481           }elseif($type == "Boolean"){
483             /* If type is Boolean & no values are given */
484             $str  .=  "<select name='".base64_encode($name)."'>\n";
485             if($default == "False"){
486               $str  .=    "<option value='True' >"._("True")."</option>\n";
487               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
488             }else{
489               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
490               $str  .=    "<option value='False' >"._("False")."</option>\n";
491             }          
492             $str  .=  "</select>\n";
494           }else{
495             print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
496           }
497           $str .= "</td></tr>\n";
498         }
499       }
500       $str .= "</table></div>\n";
501     }
502     return($str);
503   }
504   
505   function check(){  return(plugin::check()); }
507 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
508 ?>