Code

Updated workstation - Startup
[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   /* If there is already a ppd file for the same type of printer, 
30    *  remember the path to ppd file and display a dialog which allows 
31    *  to overwrite the current ppd file. 
32    */
33   var $add_ppd_later            = "";
34   var $add_later_msg_dialog     = NULL;
36   function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
37   {
38     plugin::plugin ($config, $dn);
39     $this->depselect = $this->config->current['BASE'];
41     /* Get PPD path and remove double //, and add trailing /  */
42     if(isset($_SESSION['config']->data['MAIN']['PPD_PATH'])){
43       $this->pathToPPD = $_SESSION['config']->data['MAIN']['PPD_PATH'];
44       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
45       if(!preg_match("/\/$/",$this->pathToPPD)){
46         $this->pathToPPD = $this->pathToPPD."/";
47       }
48     }else{
49       $this->pathToPPD = "";
50     }
52     /* It seams that we have an existing PPD path, so go on */
53     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
55       /* Load all available PPD files and sort them into an array */
56       $this->ppdManager= new ppdManager($this->pathToPPD);
57       $this->getPrinterReload ();
59       /* The user has already a valid PPD assigned
60        * Get some informations about this PPD
61        * and set it as selected. 
62        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
63        *     e.g. "/Compaq/Compaq-J1200.ppd" */
64       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
65         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
66         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
67           print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
68         }else{
69           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
70           if($res){
71             $tmp = split("\n",$res);
72             $tmp3 = array(); 
73             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
74             $tmp3['link']   = $ppdfile;
75             $tmp3['ppd']    = $res;
76           }    
77           $this->selectedPPD = $tmp3;
78         }
79       }
80     }
81   }
84   function execute()
85   {
86     /* Call parent execute */
87     plugin::execute();
89     /* Fill templating stuff */
90     $display= "";
91     $smarty= get_smarty();
92     $smarty->assign("ppdString", _("Can't get ppd informations."));
93     $smarty->assign("showOptions", "");
95     /* Check these paths */
96     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
98     /* If one of our required paths is not available, stop here and display some info */
99     foreach($paths as $path){
100     
101       /* Check if path is write/readable*/
102       $is_r = @is_readable($path);  
103       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
104         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));
105         /* Print out template */
106         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
107         return($display);
108       }
109     }
111     // PPD selection / upload / dialog handling 
113     /* Is there a new PPD file uploaded ? */
114     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
115       $file = ($_FILES['NewPPDFile']);
116       if($file['size'] != 0 ){
117         if($name = $this->AddPPD($file['tmp_name'])){
118           $this->SelectPPD($name); 
119         }
120       }else{
121         print_red(_("Please specify a valid ppd file."));
122       }
123     }
125     /* Overwrite existing PPD file and select it as currently used for this object */
126     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
127       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
128         $this->SelectPPD($name);
129       }
130       $this->add_ppd_later = "";
131       $this->add_later_msg_dialog = NULL;
132     } 
134     /* Open a dialog that allow us to select different PPDs */
135     if(isset($_POST['SelectPPD'])){
136       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
137     }
139     /* The selection dialog fpr PPDs is canceled */
140     if(isset($_POST['ClosePPDSelection'])){
141       unset($this->dialog);
142       $this->dialog=FALSE;
143     }
145     /* Div Selection */ 
146     if((isset($_GET['act']))&&($_GET['act']=="use")){
147       $this->SelectPPD(base64_decode($_GET['id']));
148       unset($this->dialog);
149       $this->dialog=FALSE;
151     }
153     /* if a dialog is open, print the dialog instead of this class */
154     if(is_object($this->dialog)){
155       $display = $this->dialog->execute();
156       return($display);
157     }
159     // ENDE  PPD selection / upload / dialog handling 
161     /* Give smarty the information it needs */
162     $smarty->assign("ppdString" ,$this->getPPDInformation());
163     $tmp= $this->generateProperties();
164     if ($tmp == ""){
165       $smarty->assign("showOptions", 0);
166     } else {
167       $smarty->assign("showOptions", 1);
168       $smarty->assign("properties",$this->generateProperties());
169     }
171     /* Print out template */
172     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
173     return($display);
174   }
177   /* Select PPD */
178   function SelectPPD($name)
179   {
180     /* Replace base path we don't need it here 
181        The path we need looks like this : "/Vendor/ModellName.ppd"; 
182        thats all */
183     $name = preg_replace("#".$this->pathToPPD."#","",$name);
185     /* Intialise some base vars */
186     $AbsoluteSourceName       = $this->pathToPPD.$name;   
187     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
188     $Vendor                   = ""; // Vendor 
189     $Name                     = ""; // Name 
190     $Modell                   = ""; // Modell
191     $PrinterName              = ""; // The new name of the printer 
192     $PPDName                  = "";
193  
194     /* Force reload of config dialog */ 
195     $this->ppdConfig            = false;
196     $this->selectedPPD['link']  = false;
198     /* Get PPD informations and set vendor / modell / name */ 
199     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
200       print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));   
201       return;
202     }
203     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
204     if($res){
205       $tmp = split("\n",$res);
206       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
207       $Vendor = trim($tmp[0]);
208       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
209     }    
211     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
212     $PPDName      = $Vendor."/".$PrinterName.".ppd";
213     
214     /* Create the vendors path, if it doesn't exists already */
215     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
216       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
217         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
218         return(false);
219       }
220     }
222     /* Create destination file handle */
223     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
224     if(!$fp){
225       print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
226       return(false);
227     }
229     $str = file_get_contents($AbsoluteSourceName);
230     fputs($fp,$str);
231     @fclose($fp);
233     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
235     $tmp3['link']   =$PPDName;
236     $this->selectedPPD = $tmp3;
237     $this->getPrinterReload(); 
238     return($PPDName);
239   }
242   /* This function adds a new ppd file to the list of available ppds. 
243      All required paths and files will be created 
244       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
245   function AddPPD($_PathOnHdd,$overwrite = FALSE)
246   {
247     /* Check if file exists && is readable */
248     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
249       print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
250       return(false);
251     }
252     
253     /* Reload list to detect changes e.g. a file has been deleted */
254     $this->getPrinterReload();
256     /* Get Description from ppd, & parse out some informations */   
257     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
258     if($res){
259       $tmp = split("\n",$res);
260       $name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
261       $vendor = trim($tmp[0]);
262       $model  = trim(preg_replace("/".$vendor."/","",$name));
263     }    
265     /* Check if parse was successfull */
266     if(empty($name) || empty($vendor)){
267       print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any model or vendor informations."),$_PathOnHdd));
268       return(false);
269     }
271     /* Prepare list of ppds */
272     if(!isset($this->ppdList[$vendor])){
273       $this->ppdList[$vendor] = array();
274     }
276     /* Create ppd file and fill in the source contents */
277     $ppdname      = $vendor."/".$name.".ppd";
278     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
279     $filename     = $this->pathToPPD.$ppdname;
280     $contents     = file_get_contents($_PathOnHdd);
283     /* Check if this ppd already exists */
284     $found = false;
285     foreach($this->ppdList[$vendor] as $key => $val){
286       if(preg_match("/".$model.".*/i",$key)){
287         $found = true;
288         if(!$overwrite){
289           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
290             print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));         
291           }else{
292             $this->add_ppd_later = $_PathOnHdd."_back";
293             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
294                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
295           }
296           return;
297         }
298       }
299     }
301     /* Create the vendors path, if it doesn't exists already */
302     if(!is_dir($this->pathToPPD.$vendor)){
303       if(!(@mkdir($this->pathToPPD.$vendor))){
304         print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
305         return(false);
306       }
307     }
308   
309     /* Open file handle */
310     $fp           = fopen($filename,"w+");
312     /* Check file handle & contents */
313     if(!$fp){
314       print_red(sprintf(_("Can't save file '%s'."),$filename));
315       return;
316     }
317     if(empty($contents)){
318       print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
319       return;
320     }
321     
322     /* Fille file with data */
323     fputs($fp,$contents);
324     @fclose($fp);
326     /* Our job is done here */
327     return($ppdname);
328   }
331   /* This function reloads the list of available printers/vendors 
332      $this->ppdListHeader 
333      Compaq        => 1
334      $this->ppdList
335      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
336      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
337      ppd  => Compaq - Co    
338    */
339   function getPrinterReload()
340   {
341     if(is_readable($this->pathToPPD)){
342       $tmp = @$this->ppdManager->getPrinterList(true);
344       $this->ppdListHeader = $this->ppdList = array();
346       /* Sort all available files, and create header (Vendor index) */
347       foreach($tmp as $file=>$ppd){
349         if(preg_match("#".$this->pathToModified."#",$file)) continue;
351         $tmp2 = split("\n",$ppd);
352         if(!isset($this->ppdListHeader[$tmp2[0]])){
353           $this->ppdListHeader[$tmp2[0]]=0;
354         }
355         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
356         $tmp3['link']   =$file;
357         $tmp3['ppd']    =$ppd;
358         $this->ppdListHeader[$tmp2[0]]++;
359         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
360       }
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   {
385     if($this->ppdManager){
386       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
387     }
388   }
391   /* Return selected ppd path, if none is selected then false */
392   function save()
393   {
394     /* return the selected PPD, and in future the selected options too */
395     return($this->pathToModified.$this->selectedPPD['link']);
396   }
399   /* Get Information for a single PPD entry 
400    * This will be shown on top of template
401    */
402   function getPPDInformation()
403   {
404     $str = "none";
405     if(!empty($this->selectedPPD)){
406       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
407     }
408     return($str) ; 
409   }
412   /* Display all options from the selected ppd file */
413   function generateProperties()
414   { 
415     /* Set Headline */
416     $str = "";
417     $feed= "";
419     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
421     /* If ppd exists and is readable */
422     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
424       /* If there is no initial Configuration, load it */
425       if($this->ppdConfig == false){
426         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
427       }
429       /* Create a table */
430       $str .= "<div style='padding-left:30px;'><table summary=''>";
432       /* Input all data to the table */
433       foreach($this->ppdConfig as $cat => $obj){
435         /* Add new category */
436         $str .= "<tr><td colspan='2'>$feed";
437         if ($feed == ""){
438           $feed= "<br>";
439         }
440         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
441         $str .= "</td></tr>";       
443         /* Add attributes of the current category */
444         foreach($obj as $attr => $settings){
446           /* Skip all entries beginning with _ */
447           if($attr[0] == "_") continue;  
449           /* Prepare data */
450           $values   = array();
451           $name     = $settings['_name'];
453           if (!isset($settings['_default'])){
454             $default  = "";
455           } else {
456             $default  = $settings['_default'];
457           }
459           $type     = $settings['_type'];
461           /* Add name to table */ 
462           $str .= "<tr><td style='padding-left:40px;'>\n";
463           $str .= $name."<br>\n";
464           $str .= "</td><td>\n";
466           /* Get all values */ 
467           foreach( $settings as $vname => $value){
468             if($vname[0] != "_"){
469               $values[$vname]= $value;
470             }
471           }
473           /* preparing Html output
474            * Supported types are PickOne/Boolean
475            */
477           /* If type is PickOne, create a select box */
478           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
480             $str  .=  "<select name='".base64_encode($name)."'>\n";
481             foreach($values as $optionKey => $value){
482               $selected = "";
483               if($optionKey == $default){
484                 $selected = " selected ";
485               }
486               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
487             }
488             $str  .=  "</select>\n";
490           }elseif($type == "Boolean"){
492             /* If type is Boolean & no values are given */
493             $str  .=  "<select name='".base64_encode($name)."'>\n";
494             if($default == "False"){
495               $str  .=    "<option value='True' >"._("True")."</option>\n";
496               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
497             }else{
498               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
499               $str  .=    "<option value='False' >"._("False")."</option>\n";
500             }          
501             $str  .=  "</select>\n";
503           }else{
504             print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
505           }
506           $str .= "</td></tr>\n";
507         }
508       }
509       $str .= "</table></div>\n";
510     }
511     return($str);
512   }
514   function removeModifiedPPD()
515   {
516     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
518     if(file_exists($path)){
519       if(is_writeable($path)){
520         if(!@unlink($path)){
521           print_red(sprintf(_("Removing old ppd file '%s' failed."),$path));
522         }
523       }else{
524         print_red(sprintf(_("Removing old ppd file '%s' failed. File is not accessible."),$path));
525       }
526     }else{
527       print_red(sprintf(_("Removing old ppd file '%s' failed. File does not exists or is not accessible."),$path));
528     }
529   }
531   function update_ppd_url()
532   {
533     $this->SelectPPD("modified/".$this->selectedPPD['link']);
534   }
535   
536   function check()
537   {  
538     $message = plugin::check();
539     if(empty($this->selectedPPD['link'])){
540       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
541     }
542     return($message); 
543   }
545 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
546 ?>