Code

f6812ef8a6c97023404d3f3379b43fa4a99e53f0
[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       $this->getPrinterReload ();
54       /* The user has already a valid PPD assigned
55        * Get some informations about this PPD
56        * and set it as selected. 
57        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
58        *     e.g. "/Compaq/Compaq-J1200.ppd" */
59       if(($ppdfile!= NULL)&&(strlen($ppdfile)>0)){
60         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
61         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
62           print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
63         }else{
64           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
65           if($res){
66             $tmp = split("\n",$res);
67             $tmp3 = array(); 
68             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
69             $tmp3['link']   = $ppdfile;
70             $tmp3['ppd']    = $res;
71           }    
72           $this->selectedPPD = $tmp3;
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         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));
100         /* Print out template */
101         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
102         return($display);
103       }
104     }
106     // PPD selection / upload / dialog handling 
108     /* Is there a new PPD file uploaded ? */
109     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
110       $file = ($_FILES['NewPPDFile']);
111       if($file['size'] != 0 ){
112         if($name = $this->AddPPD($file['tmp_name'])){
113           $this->SelectPPD($name); 
114         }
115       }else{
116         print_red(_("Please specify a valid ppd file."));
117       }
118     }
120     /* Open a dialog that allow us to select different PPDs */
121     if(isset($_POST['SelectPPD'])){
122       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
123     }
125     /* The selection dialog fpr PPDs is canceled */
126     if(isset($_POST['ClosePPDSelection'])){
127       unset($this->dialog);
128       $this->dialog=NULL;
129     }
131     /* Div Selection */ 
132     if((isset($_GET['act']))&&($_GET['act']=="use")){
133       $this->SelectPPD(base64_decode($_GET['id']));
134       unset($this->dialog);
135       $this->dialog=NULL;
137     }
139     /* if a dialog is open, print the dialog instead of this class */
140     if($this->dialog!=NULL){
141       $display = $this->dialog->execute();
142       return($display);
143     }
145     // ENDE  PPD selection / upload / dialog handling 
147     /* Give smarty the information it needs */
148     $smarty->assign("ppdString" ,$this->getPPDInformation());
149     $tmp= $this->generateProperties();
150     if ($tmp == ""){
151       $smarty->assign("showOptions", 0);
152     } else {
153       $smarty->assign("showOptions", 1);
154       $smarty->assign("properties",$this->generateProperties());
155     }
157     /* Print out template */
158     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
159     return($display);
160   }
163   /* Select PPD */
164   function SelectPPD($name)
165   {
166     /* Replace base path we don't need it here 
167        The path we need looks like this : "/Vendor/ModellName.ppd"; 
168        thats all */
169     $name = preg_replace("#".$this->pathToPPD."#","",$name);
171     /* Intialise some base vars */
172     $AbsoluteSourceName       = $this->pathToPPD.$name;   
173     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
174     $Vendor                   = ""; // Vendor 
175     $Name                     = ""; // Name 
176     $Modell                   = ""; // Modell
177     $PrinterName              = ""; // The new name of the printer 
178     $PPDName                  = "";
179  
180     /* Force reload of config dialog */ 
181     $this->ppdConfig            = false;
182     $this->selectedPPD['link']  = false;
184     /* Get PPD informations and set vendor / modell / name */ 
185     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
186       print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));   
187       return;
188     }
189     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
190     if($res){
191       $tmp = split("\n",$res);
192       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
193       $Vendor = trim($tmp[0]);
194       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
195     }    
197     $PrinterName  = $this->cn."-".$Name; 
198     $PPDName      = $Vendor."/".$PrinterName.".ppd";
199     
200     /* Create the vendors path, if it doesn't exists already */
201     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
202       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
203         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
204         return(false);
205       }
206     }
208     /* Create destination file handle */
209     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
210     if(!$fp){
211       print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
212       return(false);
213     }
215     $str = file_get_contents($AbsoluteSourceName);
216     fputs($fp,$str);
217     @fclose($fp);
219     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
221     $tmp3['link']   =$PPDName;
222     $this->selectedPPD = $tmp3;
223     $this->getPrinterReload(); 
224     return($PPDName);
225   }
228   /* This function adds a new ppd file to the list of available ppds. 
229      All required paths and files will be created 
230       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
231   function AddPPD($_PathOnHdd)
232   {
233     /* Check if file exists && is readable */
234     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
235       print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
236       return(false);
237     }
238     
239     /* Reload list to detect changes e.g. a file has been deleted */
240     $this->getPrinterReload();
242     /* Get Description from ppd, & parse out some informations */   
243     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
244     if($res){
245       $tmp = split("\n",$res);
246       $name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
247       $vendor = trim($tmp[0]);
248       $model  = trim(preg_replace("/".$vendor."/","",$name));
249     }    
251     /* Check if parse was successfull */
252     if(empty($name) || empty($vendor)){
253       print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
254       return(false);
255     }
257     /* Prepare list of ppds */
258     if(!isset($this->ppdList[$vendor])){
259       $this->ppdList[$vendor] = array();
260     }
262     /* Check if this ppd already exists */
263     $found = false;
264     foreach($this->ppdList[$vendor] as $key => $val){
265       if(preg_match("/".$model.".*/i",$key)){
266         $found = true;
267         print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
268         return;
269       }
270     }
272     /* Create the vendors path, if it doesn't exists already */
273     if(!is_dir($this->pathToPPD.$vendor)){
274       if(!(@mkdir($this->pathToPPD.$vendor))){
275         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
276         return(false);
277       }
278     }
279   
280     /* Create ppd file and fill in the source contents */
281     $ppdname      = $vendor."/".$name.".ppd";
282     $filename     = $this->pathToPPD.$ppdname;
283     $fp           = fopen($filename,"w+");
284     $contents     = file_get_contents($_PathOnHdd);
286     /* Check file handle & contents */
287     if(!$fp){
288       print_red(sprintf(_("Can't save file '%s'."),$filename));
289       return;
290     }
291     if(empty($contents)){
292       print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
293       return;
294     }
295     
296     /* Fille file with data */
297     fputs($fp,$contents);
298     @fclose($fp);
300     /* Our job is done here */
301     return($ppdname);
302   }
305   /* This function reloads the list of available printers/vendors 
306      $this->ppdListHeader 
307      Compaq        => 1
308      $this->ppdList
309      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
310      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
311      ppd  => Compaq - Co    
312    */
313   function getPrinterReload()
314   {
315     if(is_readable($this->pathToPPD)){
316       $tmp = $this->ppdManager->getPrinterList(true);
318       $this->ppdListHeader = $this->ppdList = array();
320       /* Sort all available files, and create header (Vendor index) */
321       foreach($tmp as $file=>$ppd){
323         if(preg_match("#".$this->pathToModified."#",$file)) continue;
325         $tmp2 = split("\n",$ppd);
326         if(!isset($this->ppdListHeader[$tmp2[0]])){
327           $this->ppdListHeader[$tmp2[0]]=0;
328         }
329         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
330         $tmp3['link']   =$file;
331         $tmp3['ppd']    =$ppd;
332         $this->ppdListHeader[$tmp2[0]]++;
333         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
334       }
335     }
336   }
339   /* Save all options posted from ppd dialog */
340   function save_object()
341   {
342     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
343       return;
344     }
346     foreach($this->ppdConfig as $cat => $obj){
347       foreach($obj as $attr => $attributes){
348         if(isset($_POST[base64_encode($attributes['_name'])])){
349           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
350         }
351       }
352     }
353   }
356   /* Save modified ppd */
357   function save_ppd(){
358     if($this->ppdManager){
359       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
360     }
361   }
364   /* Return selected ppd path, if none is selected then false */
365   function save()
366   {
367     /* return the selected PPD, and in future the selected options too */
368     return($this->pathToModified.$this->selectedPPD['link']);
369   }
372   /* Get Information for a single PPD entry 
373    * This will be shown on top of template
374    */
375   function getPPDInformation()
376   {
377     $str = "none";
378     if(!empty($this->selectedPPD)){
379       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
380     }
381     return($str) ; 
382   }
385   /* Display all options from the selected ppd file */
386   function generateProperties()
387   { 
388     /* Set Headline */
389     $str = "";
390     $feed= "";
392     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
394     /* If ppd exists and is readable */
395     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
397       /* If there is no initial Configuration, load it */
398       if($this->ppdConfig == false){
399         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
400       }
402       /* Create a table */
403       $str .= "<div style='padding-left:30px;'><table summary=''>";
405       /* Input all data to the table */
406       foreach($this->ppdConfig as $cat => $obj){
408         /* Add new category */
409         $str .= "<tr><td colspan='2'>$feed";
410         if ($feed == ""){
411           $feed= "<br>";
412         }
413         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
414         $str .= "</td></tr>";       
416         /* Add attributes of the current category */
417         foreach($obj as $attr => $settings){
419           /* Skip all entries beginning with _ */
420           if($attr[0] == "_") continue;  
422           /* Prepare data */
423           $values   = array();
424           $name     = $settings['_name'];
426           if (!isset($settings['_default'])){
427             $default  = "";
428           } else {
429             $default  = $settings['_default'];
430           }
432           $type     = $settings['_type'];
434           /* Add name to table */ 
435           $str .= "<tr><td style='padding-left:40px;'>\n";
436           $str .= $name."<br>\n";
437           $str .= "</td><td>\n";
439           /* Get all values */ 
440           foreach( $settings as $vname => $value){
441             if($vname[0] != "_"){
442               $values[$vname]= $value;
443             }
444           }
446           /* preparing Html output
447            * Supported types are PickOne/Boolean
448            */
450           /* If type is PickOne, create a select box */
451           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
453             $str  .=  "<select name='".base64_encode($name)."'>\n";
454             foreach($values as $optionKey => $value){
455               $selected = "";
456               if($optionKey == $default){
457                 $selected = " selected ";
458               }
459               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
460             }
461             $str  .=  "</select>\n";
463           }elseif($type == "Boolean"){
465             /* If type is Boolean & no values are given */
466             $str  .=  "<select name='".base64_encode($name)."'>\n";
467             if($default == "False"){
468               $str  .=    "<option value='True' >"._("True")."</option>\n";
469               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
470             }else{
471               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
472               $str  .=    "<option value='False' >"._("False")."</option>\n";
473             }          
474             $str  .=  "</select>\n";
476           }else{
477             print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
478           }
479           $str .= "</td></tr>\n";
480         }
481       }
482       $str .= "</table></div>\n";
483     }
484     return($str);
485   }
487   function removeModifiedPPD()
488   {
489     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
491     if(file_exists($path)){
492       if(is_writeable($path)){
493         if(!@unlink($path)){
494           print_red(sprintf(_("Removing old ppd file '%s' failed."),$path));
495         }
496       }else{
497         print_red(sprintf(_("Removing old ppd file '%s' failed. File is not accessible."),$path));
498       }
499     }else{
500       print_red(sprintf(_("Removing old ppd file '%s' failed. File does not exists or is not accessible."),$path));
501     }
502   }
503   
504   function check()
505   {  
506     $message = plugin::check();
507     if(empty($this->selectedPPD['link'])){
508       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
509     }
510     return($message); 
511   }
513 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
514 ?>