Code

Updated printer ppd saving
[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, 
29   function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
30   {
31     plugin::plugin ($config, $dn);
32     $this->depselect = $this->config->current['BASE'];
34     /* Get PPD path and remove double //, and add trailing /  */
35     if(isset($_SESSION['config']->data['MAIN']['PPD_PATH'])){
36       $this->pathToPPD = $_SESSION['config']->data['MAIN']['PPD_PATH'];
37       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
38       if(!preg_match("/\/$/",$this->pathToPPD)){
39         $this->pathToPPD = $this->pathToPPD."/";
40       }
41     }else{
42       $this->pathToPPD = "";
43     }
45     /* It seams that we have an existing PPD path, so go on */
46     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
48       /* Load all available PPD files and sort them into an array */
49       $this->ppdManager= new ppdManager($this->pathToPPD);
50       $this->getPrinterReload ();
52       /* The user has already a valid PPD assigned
53        * Get some informations about this PPD
54        * and set it as selected. 
55        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
56        *     e.g. "/Compaq/Compaq-J1200.ppd" */
57       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
58         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
59         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
60           print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
61         }else{
62           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
63           if($res){
64             $tmp = split("\n",$res);
65             $tmp3 = array(); 
66             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
67             $tmp3['link']   = $ppdfile;
68             $tmp3['ppd']    = $res;
69           }    
70           $this->selectedPPD = $tmp3;
71         }
72       }
73     }
74   }
77   function execute()
78   {
79     /* Call parent execute */
80     plugin::execute();
82     /* Fill templating stuff */
83     $display= "";
84     $smarty= get_smarty();
85     $smarty->assign("ppdString", _("Can't get ppd informations."));
86     $smarty->assign("showOptions", "");
88     /* Check these paths */
89     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
91     /* If one of our required paths is not available, stop here and display some info */
92     foreach($paths as $path){
93     
94       /* Check if path is write/readable*/
95       $is_r = @is_readable($path);  
96       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
97         print_red(sprintf(_("The specified path '%s' which results from PPD_PATH in your gosa.conf is invalid, can't read/write any ppd informations."),$path));
98         /* Print out template */
99         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
100         return($display);
101       }
102     }
104     // PPD selection / upload / dialog handling 
106     /* Is there a new PPD file uploaded ? */
107     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
108       $file = ($_FILES['NewPPDFile']);
109       if($file['size'] != 0 ){
110         if($name = $this->AddPPD($file['tmp_name'])){
111           $this->SelectPPD($name); 
112         }
113       }else{
114         print_red(_("Please specify a valid ppd file."));
115       }
116     }
118     /* Open a dialog that allow us to select different PPDs */
119     if(isset($_POST['SelectPPD'])){
120       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
121     }
123     /* The selection dialog fpr PPDs is canceled */
124     if(isset($_POST['ClosePPDSelection'])){
125       unset($this->dialog);
126       $this->dialog=FALSE;
127     }
129     /* Div Selection */ 
130     if((isset($_GET['act']))&&($_GET['act']=="use")){
131       $this->SelectPPD(base64_decode($_GET['id']));
132       unset($this->dialog);
133       $this->dialog=FALSE;
135     }
137     /* if a dialog is open, print the dialog instead of this class */
138     if(is_object($this->dialog)){
139       $display = $this->dialog->execute();
140       return($display);
141     }
143     // ENDE  PPD selection / upload / dialog handling 
145     /* Give smarty the information it needs */
146     $smarty->assign("ppdString" ,$this->getPPDInformation());
147     $tmp= $this->generateProperties();
148     if ($tmp == ""){
149       $smarty->assign("showOptions", 0);
150     } else {
151       $smarty->assign("showOptions", 1);
152       $smarty->assign("properties",$this->generateProperties());
153     }
155     /* Print out template */
156     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
157     return($display);
158   }
161   /* Select PPD */
162   function SelectPPD($name)
163   {
164     /* Replace base path we don't need it here 
165        The path we need looks like this : "/Vendor/ModellName.ppd"; 
166        thats all */
167     $name = preg_replace("#".$this->pathToPPD."#","",$name);
169     /* Intialise some base vars */
170     $AbsoluteSourceName       = $this->pathToPPD.$name;   
171     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
172     $Vendor                   = ""; // Vendor 
173     $Name                     = ""; // Name 
174     $Modell                   = ""; // Modell
175     $PrinterName              = ""; // The new name of the printer 
176     $PPDName                  = "";
177  
178     /* Force reload of config dialog */ 
179     $this->ppdConfig            = false;
180     $this->selectedPPD['link']  = false;
182     /* Get PPD informations and set vendor / modell / name */ 
183     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
184       print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));   
185       return;
186     }
187     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
188     if($res){
189       $tmp = split("\n",$res);
190       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
191       $Vendor = trim($tmp[0]);
192       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
193     }    
195     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
196     $PPDName      = $Vendor."/".$PrinterName.".ppd";
197     
198     /* Create the vendors path, if it doesn't exists already */
199     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
200       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
201         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
202         return(false);
203       }
204     }
206     /* Create destination file handle */
207     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
208     if(!$fp){
209       print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
210       return(false);
211     }
213     $str = file_get_contents($AbsoluteSourceName);
214     fputs($fp,$str);
215     @fclose($fp);
217     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
219     $tmp3['link']   =$PPDName;
220     $this->selectedPPD = $tmp3;
221     $this->getPrinterReload(); 
222     return($PPDName);
223   }
226   /* This function adds a new ppd file to the list of available ppds. 
227      All required paths and files will be created 
228       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
229   function AddPPD($_PathOnHdd)
230   {
231     /* Check if file exists && is readable */
232     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
233       print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
234       return(false);
235     }
236     
237     /* Reload list to detect changes e.g. a file has been deleted */
238     $this->getPrinterReload();
240     /* Get Description from ppd, & parse out some informations */   
241     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
242     if($res){
243       $tmp = split("\n",$res);
244       $name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
245       $vendor = trim($tmp[0]);
246       $model  = trim(preg_replace("/".$vendor."/","",$name));
247     }    
249     /* Check if parse was successfull */
250     if(empty($name) || empty($vendor)){
251       print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any model or vendor informations."),$_PathOnHdd));
252       return(false);
253     }
255     /* Prepare list of ppds */
256     if(!isset($this->ppdList[$vendor])){
257       $this->ppdList[$vendor] = array();
258     }
260     /* Check if this ppd already exists */
261     $found = false;
262     foreach($this->ppdList[$vendor] as $key => $val){
263       if(preg_match("/".$model.".*/i",$key)){
264         $found = true;
265         print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
266         return;
267       }
268     }
270     /* Create the vendors path, if it doesn't exists already */
271     if(!is_dir($this->pathToPPD.$vendor)){
272       if(!(@mkdir($this->pathToPPD.$vendor))){
273         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
274         return(false);
275       }
276     }
277   
278     /* Create ppd file and fill in the source contents */
279     $ppdname      = $vendor."/".$name.".ppd";
280     $filename     = $this->pathToPPD.$ppdname;
281     $fp           = fopen($filename,"w+");
282     $contents     = file_get_contents($_PathOnHdd);
284     /* Check file handle & contents */
285     if(!$fp){
286       print_red(sprintf(_("Can't save file '%s'."),$filename));
287       return;
288     }
289     if(empty($contents)){
290       print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
291       return;
292     }
293     
294     /* Fille file with data */
295     fputs($fp,$contents);
296     @fclose($fp);
298     /* Our job is done here */
299     return($ppdname);
300   }
303   /* This function reloads the list of available printers/vendors 
304      $this->ppdListHeader 
305      Compaq        => 1
306      $this->ppdList
307      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
308      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
309      ppd  => Compaq - Co    
310    */
311   function getPrinterReload()
312   {
313     if(is_readable($this->pathToPPD)){
314       $tmp = $this->ppdManager->getPrinterList(true);
316       $this->ppdListHeader = $this->ppdList = array();
318       /* Sort all available files, and create header (Vendor index) */
319       foreach($tmp as $file=>$ppd){
321         if(preg_match("#".$this->pathToModified."#",$file)) continue;
323         $tmp2 = split("\n",$ppd);
324         if(!isset($this->ppdListHeader[$tmp2[0]])){
325           $this->ppdListHeader[$tmp2[0]]=0;
326         }
327         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
328         $tmp3['link']   =$file;
329         $tmp3['ppd']    =$ppd;
330         $this->ppdListHeader[$tmp2[0]]++;
331         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
332       }
333     }
334   }
337   /* Save all options posted from ppd dialog */
338   function save_object()
339   {
340     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
341       return;
342     }
344     foreach($this->ppdConfig as $cat => $obj){
345       foreach($obj as $attr => $attributes){
346         if(isset($_POST[base64_encode($attributes['_name'])])){
347           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
348         }
349       }
350     }
351   }
354   /* Save modified ppd */
355   function save_ppd()
356   {
357     if($this->ppdManager){
358       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
359     }
360   }
363   /* Return selected ppd path, if none is selected then false */
364   function save()
365   {
366     /* return the selected PPD, and in future the selected options too */
367     return($this->pathToModified.$this->selectedPPD['link']);
368   }
371   /* Get Information for a single PPD entry 
372    * This will be shown on top of template
373    */
374   function getPPDInformation()
375   {
376     $str = "none";
377     if(!empty($this->selectedPPD)){
378       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
379     }
380     return($str) ; 
381   }
384   /* Display all options from the selected ppd file */
385   function generateProperties()
386   { 
387     /* Set Headline */
388     $str = "";
389     $feed= "";
391     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
393     /* If ppd exists and is readable */
394     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
396       /* If there is no initial Configuration, load it */
397       if($this->ppdConfig == false){
398         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
399       }
401       /* Create a table */
402       $str .= "<div style='padding-left:30px;'><table summary=''>";
404       /* Input all data to the table */
405       foreach($this->ppdConfig as $cat => $obj){
407         /* Add new category */
408         $str .= "<tr><td colspan='2'>$feed";
409         if ($feed == ""){
410           $feed= "<br>";
411         }
412         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
413         $str .= "</td></tr>";       
415         /* Add attributes of the current category */
416         foreach($obj as $attr => $settings){
418           /* Skip all entries beginning with _ */
419           if($attr[0] == "_") continue;  
421           /* Prepare data */
422           $values   = array();
423           $name     = $settings['_name'];
425           if (!isset($settings['_default'])){
426             $default  = "";
427           } else {
428             $default  = $settings['_default'];
429           }
431           $type     = $settings['_type'];
433           /* Add name to table */ 
434           $str .= "<tr><td style='padding-left:40px;'>\n";
435           $str .= $name."<br>\n";
436           $str .= "</td><td>\n";
438           /* Get all values */ 
439           foreach( $settings as $vname => $value){
440             if($vname[0] != "_"){
441               $values[$vname]= $value;
442             }
443           }
445           /* preparing Html output
446            * Supported types are PickOne/Boolean
447            */
449           /* If type is PickOne, create a select box */
450           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
452             $str  .=  "<select name='".base64_encode($name)."'>\n";
453             foreach($values as $optionKey => $value){
454               $selected = "";
455               if($optionKey == $default){
456                 $selected = " selected ";
457               }
458               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
459             }
460             $str  .=  "</select>\n";
462           }elseif($type == "Boolean"){
464             /* If type is Boolean & no values are given */
465             $str  .=  "<select name='".base64_encode($name)."'>\n";
466             if($default == "False"){
467               $str  .=    "<option value='True' >"._("True")."</option>\n";
468               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
469             }else{
470               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
471               $str  .=    "<option value='False' >"._("False")."</option>\n";
472             }          
473             $str  .=  "</select>\n";
475           }else{
476             print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
477           }
478           $str .= "</td></tr>\n";
479         }
480       }
481       $str .= "</table></div>\n";
482     }
483     return($str);
484   }
486   function removeModifiedPPD()
487   {
488     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
490     if(file_exists($path)){
491       if(is_writeable($path)){
492         if(!@unlink($path)){
493           print_red(sprintf(_("Removing old ppd file '%s' failed."),$path));
494         }
495       }else{
496         print_red(sprintf(_("Removing old ppd file '%s' failed. File is not accessible."),$path));
497       }
498     }else{
499       print_red(sprintf(_("Removing old ppd file '%s' failed. File does not exists or is not accessible."),$path));
500     }
501   }
503   function update_ppd_url()
504   {
505     $this->SelectPPD("modified/".$this->selectedPPD['link']);
506   }
507   
508   function check()
509   {  
510     $message = plugin::check();
511     if(empty($this->selectedPPD['link'])){
512       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
513     }
514     return($message); 
515   }
517 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
518 ?>