Code

<h2> => </h3>
[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, 
23   var $ui;
25   /* If there is already a ppd file for the same type of printer, 
26    *  remember the path to ppd file and display a dialog which allows 
27    *  to overwrite the current ppd file. 
28    */
29   var $add_ppd_later            = "";
30   var $add_later_msg_dialog     = NULL;
32   function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
33   {
34     plugin::plugin ($config, $dn);
35     $this->depselect = $this->config->current['BASE'];
37     $this->ui = get_userinfo();
39     /* Get PPD path and remove double //, and add trailing /  */
40     $config = session::get('config');
41     if($config->get_cfg_value("ppdPath") != ""){
42       $this->pathToPPD = $config->get_cfg_value("ppdPath");
43       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
44       if(!preg_match("/\/$/",$this->pathToPPD)){
45         $this->pathToPPD = $this->pathToPPD."/";
46       }
47     }else{
48       $this->pathToPPD = "";
49     }
51     /* Check if ppdPath is set in gosa.conf. 
52      */
53     if(empty($this->pathToPPD)){
54       msg_dialog::display(_("Configuration error"), msgPool::invalidConfigurationAttribute("ppdPath"), ERROR_DIALOG);
55     }
57     /* It seams that we have an existing PPD path, so go on */
58     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
60       /* Load all available PPD files and sort them into an array */
61       $this->ppdManager= new ppdManager($this->pathToPPD);
62       $this->getPrinterReload ();
64       /* The user has already a valid PPD assigned
65        * Get some informations about this PPD
66        * and set it as selected. 
67        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
68        *     e.g. "/Compaq/Compaq-J1200.ppd" */
69       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
70         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
71         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
72           msg_dialog::display(_("PPD error"), sprintf(_("Cannot open PPD '%s'!"), $ppdfile), ERROR_DIALOG);
73         }else{
74           $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
75           if($ppdDesc){            
76             $selectedPPD = array(); 
77             $selectedPPD['name']   = $ppdDesc['name'];
78             $selectedPPD['link']   = $ppdfile;
79             $selectedPPD['ppd']    = $ppdDesc;
80           }    
81           $this->selectedPPD = $selectedPPD;
82         }
83       }
84     }
85   }
88   function execute()
89   {
90     /* Call parent execute */
91     plugin::execute();
93     /* Fill templating stuff */
94     $display= "";
95     $smarty= get_smarty();
96     $smarty->assign("ppdString", _("Can't get ppd informations."));
97     $smarty->assign("showOptions", "");
98     $smarty->assign("path_valid", TRUE);
99     $smarty->assign("acl",$this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD"));
101     $acl = $this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD");
103     if(empty($this->pathToPPD)){
105         /* Print out template */
106         $smarty->assign("path_valid", FALSE);
107         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
108         return($display);
109     }
111     /* Check these paths */
112     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
114     /* If one of our required paths is not available, stop here and display some info */
115     foreach($paths as $path){
117       /* Check if path is write/readable*/
118       $is_r = @is_readable($path);  
119       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
120         msg_dialog::display(_("Configuration error"), 
121             sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
123         /* Print out template */
124         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
125         return($display);
126       }
127     }
129     // PPD selection / upload / dialog handling 
131     /* Is there a new PPD file uploaded ? */
132     if(preg_match("/w/",$acl)){
133       if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
134         $file = ($_FILES['NewPPDFile']);
135         if($file['size'] != 0 ){
136           if($name = $this->AddPPD($file['tmp_name'])){
137             $this->SelectPPD($name); 
138           }
139         }else{
140           msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
141         }
142       }
143     }
145     /* Overwrite existing PPD file and select it as currently used for this object */
146     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
147       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
148         $this->SelectPPD($name);
149       }
150       $this->add_ppd_later = "";
151       $this->add_later_msg_dialog = NULL;
152     } 
154     /* Open a dialog that allow us to select different PPDs */
155     if(preg_match("/w/",$acl)){
156       if(isset($_POST['SelectPPD'])){
157         $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
158       }
159     }
161     /* The selection dialog fpr PPDs is canceled */
162     if(isset($_POST['ClosePPDSelection'])){
163       unset($this->dialog);
164       $this->dialog=FALSE;
165     }
167     /* Div Selection */ 
168     if((isset($_GET['act']))&&($_GET['act']=="use")){
169       $this->SelectPPD(base64_decode($_GET['id']));
170       unset($this->dialog);
171       $this->dialog=FALSE;
173     }
175     /* if a dialog is open, print the dialog instead of this class */
176     if(is_object($this->dialog)){
177       $display = $this->dialog->execute();
178       return($display);
179     }
181     // ENDE  PPD selection / upload / dialog handling 
183     /* Give smarty the information it needs */
184     $smarty->assign("ppdString" ,$this->getPPDInformation());
185     $tmp= $this->generateProperties();
186     if ($tmp == ""){
187       $smarty->assign("showOptions", 0);
188     } else {
189       $smarty->assign("showOptions", 1);
190       $smarty->assign("properties",$this->generateProperties());
191     }
193     /* Print out template */
194     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
195     return($display);
196   }
199   /* Select PPD */
200   function SelectPPD($name)
201   {
202     /* Replace base path we don't need it here 
203        The path we need looks like this : "/Vendor/ModellName.ppd"; 
204        thats all */
205     $name = preg_replace("#".$this->pathToPPD."#","",$name);
207     /* Intialise some base vars */
208     $AbsoluteSourceName       = $this->pathToPPD.$name;   
209     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
210     $Vendor                   = ""; // Vendor 
211     $Name                     = ""; // Name 
212     $Modell                   = ""; // Modell
213     $PrinterName              = ""; // The new name of the printer 
214     $PPDName                  = "";
215  
216     /* Force reload of config dialog */ 
217     $this->ppdConfig            = false;
218     $this->selectedPPD['link']  = false;
220     /* Get PPD informations and set vendor / modell / name */ 
221     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
222       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
223       return;
224     }
225     $ppdDesc  = $this->ppdManager->loadDescription($AbsoluteSourceName);
226     if($ppdDesc){
227       $Name   = $ppdDesc['name'];
228       $Vendor = $ppdDesc['manufacturer'];
229       $Model  = $ppdDesc['model'];
230     }    
232     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
233     $PPDName      = $Vendor."/".$PrinterName.".ppd";
234     
235     /* Create the vendors path, if it doesn't exists already */
236     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
237       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
238         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
239         return(false);
240       }
241     }
243     /* Create destination file handle */
244     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
245     if(!$fp){
246       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
247       return(false);
248     }
250     $str = file_get_contents($AbsoluteSourceName);
251     fputs($fp,$str);
252     @fclose($fp);
254     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
256     $tmp3['link']   =$PPDName;
257     $this->selectedPPD = $tmp3;
258     $this->getPrinterReload(); 
259     return($PPDName);
260   }
263   /* This function adds a new ppd file to the list of available ppds. 
264      All required paths and files will be created 
265       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
266   function AddPPD($_PathOnHdd,$overwrite = FALSE)
267   {
268     /* Check if file exists && is readable */
269     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
270       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
271       return(false);
272     }
273     
274     /* Reload list to detect changes e.g. a file has been deleted */
275     $this->getPrinterReload();
277     /* Get Description from ppd, & parse out some informations */   
278     $ppdDesc  = @$this->ppdManager->loadDescription($_PathOnHdd);
279     if($ppdDesc){
280       $name   = preg_replace("/\//","-",$ppdDesc['name']);
281       $vendor = $ppdDesc['manufacturer'];
282       $model  = $ppdDesc['model'];
283     }    
285     /* Check if parse was successfull */
286     if(empty($name) || empty($vendor)){
287       msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
288       return(false);
289     }
291     /* Prepare list of ppds */
292     if(!isset($this->ppdList[$vendor])){
293       $this->ppdList[$vendor] = array();
294     }
296     /* Create ppd file and fill in the source contents */
297     $ppdname      = $vendor."/".$name.".ppd";
298     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
299     $filename     = $this->pathToPPD.$ppdname;
300     $contents     = file_get_contents($_PathOnHdd);
303     /* Check if this ppd already exists */
304     $found = false;
306     foreach($this->ppdList[$vendor] as $key => $val){
307       if(preg_match("/".preg_quote($model,'/').".*/i",$key)){
308         $found = true;
309         if(!$overwrite){
310           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
311             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
312           }else{
313             $this->add_ppd_later = $_PathOnHdd."_back";
314             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
315                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
316           }
317           return;
318         }
319       }
320     }
322     /* Create the vendors path, if it doesn't exists already */
323     if(!is_dir($this->pathToPPD.$vendor)){
324       if(!(@mkdir($this->pathToPPD.$vendor))){
325         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
326         return(false);
327       }
328     }
329   
330     /* Open file handle */
331     $fp           = fopen($filename,"w+");
333     /* Check file handle & contents */
334     if(!$fp){
335       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
336       return;
337     }
338     if(empty($contents)){
339       msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
340       return;
341     }
342     
343     /* Fille file with data */
344     fputs($fp,$contents);
345     @fclose($fp);
347     /* Our job is done here */
348     return($ppdname);
349   }
352   /* This function reloads the list of available printers/vendors 
353      $this->ppdListHeader 
354      Compaq        => 1
355      $this->ppdList
356      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
357      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
358      ppd  => Compaq - Co    
359    */
360   function getPrinterReload()
361   {
362     if(is_readable($this->pathToPPD)){
363       $tmp = @$this->ppdManager->getPrinterList(true);
365       $this->ppdListHeader = $this->ppdList = array();
367       /* Sort all available files, and create header (Vendor index) */
368       foreach($tmp as $file=>$ppd){
369                
370         if(preg_match("#".preg_quote($this->pathToModified,'#')."#",$file)) continue;
372         if(!isset($this->ppdListHeader[$ppd['manufacturer']])){
373           $this->ppdListHeader[$ppd['manufacturer']]=0;
374         }
375        
376         $tmp3['name']   =$ppd['name'];
377         $tmp3['link']   =$file;
378         $tmp3['ppd']    =$ppd;
379         $this->ppdListHeader[$ppd['manufacturer']]++;
380         $this->ppdList[$ppd['manufacturer']][$ppd['name']]=$tmp3;
381       }
382     }
383   }
386   /* Save all options posted from ppd dialog */
387   function save_object()
388   {
389     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
390       return;
391     }
393     if(preg_match("/w/",$this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD"))){
394       foreach($this->ppdConfig as $cat => $obj){
395         foreach($obj as $attr => $attributes){
396           if(isset($_POST[base64_encode($attributes['_name'])])){
397             $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
398           }
399         }
400       }
401     }
402   }
405   /* Save modified ppd */
406   function save_ppd()
407   {
408     if($this->ppdManager){
409       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
410     }
411   }
414   /* Return selected ppd path, if none is selected then false */
415   function save()
416   {
417     /* return the selected PPD, and in future the selected options too */
418     return($this->pathToModified.$this->selectedPPD['link']);
419   }
422   /* Get Information for a single PPD entry 
423    * This will be shown on top of template
424    */
425   function getPPDInformation()
426   {
427     $str = "none";
428     if(!empty($this->selectedPPD)){
429       $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
430       $str = $ppdDesc['name'];
431     }
432     return($str) ; 
433   }
435   /* Display all options from the selected ppd file */
436   function generateProperties()
437   { 
438     /* Set Headline */
439     $str = "";
440     $feed= "";
442     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
444     /* If ppd exists and is readable */
445     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
447       /* If there is no initial Configuration, load it */
448       if($this->ppdConfig == false){
449         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
450       }
452       /* Create a table */
453       $str .= "<div style='padding-left:30px;'><table summary=''>";
455       /* Input all data to the table */
456       foreach($this->ppdConfig as $cat => $obj){
458         /* Add new category */
459         $str .= "<tr><td colspan='2'>$feed";
460         if ($feed == ""){
461           $feed= "<br>";
462         }
463         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
464         $str .= "</td></tr>";       
466         /* Add attributes of the current category */
467         foreach($obj as $attr => $settings){
469           /* Skip all entries beginning with _ */
470           if($attr[0] == "_") continue;  
472           /* Prepare data */
473           $values   = array();
474           $name     = $settings['_name'];
476           if (!isset($settings['_default'])){
477             $default  = "";
478           } else {
479             $default  = $settings['_default'];
480           }
482           $type     = $settings['_type'];
484           /* Add name to table */ 
485           $str .= "<tr><td style='padding-left:40px;'>\n";
486           $str .= $name."<br>\n";
487           $str .= "</td><td>\n";
489           /* Get all values */ 
490           foreach( $settings as $vname => $value){
491             if($vname[0] != "_"){
492               $values[$vname]= $value;
493             }
494           }
496           $acl ="";
497           if(!preg_match("/w/",$this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD"))){
498             $acl = "disabled";
499           }
501           /* preparing Html output
502            * Supported types are PickOne/Boolean
503            */
505           /* If type is PickOne, create a select box */
506           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
508             $str  .=  "<select name='".base64_encode($name)."' $acl >\n";
509             foreach($values as $optionKey => $value){
510               $selected = "";
511               if($optionKey == $default){
512                 $selected = " selected ";
513               }
514               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
515             }
516             $str  .=  "</select>\n";
518           }elseif($type == "Boolean"){
520             /* If type is Boolean & no values are given */
521             $str  .=  "<select name='".base64_encode($name)."' $acl>\n";
522             if($default == "False"){
523               $str  .=    "<option value='True' >"._("True")."</option>\n";
524               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
525             }else{
526               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
527               $str  .=    "<option value='False' >"._("False")."</option>\n";
528             }          
529             $str  .=  "</select>\n";
531           }else{
532             msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
533           }
534           $str .= "</td></tr>\n";
535         }
536       }
537       $str .= "</table></div>\n";
538     }
539     return($str);
540   }
542   function removeModifiedPPD()
543   {
544     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
546     if(file_exists($path)){
547       if(is_writeable($path)){
548         if(!@unlink($path)){
549           msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
550         }
551       }else{
552         msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
553       }
554     }else{
555       msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
556     }
557   }
559   function update_ppd_url()
560   {
561     $this->SelectPPD("modified/".$this->selectedPPD['link']);
562     return("modified/".$this->selectedPPD['link']);
563   }
564   
565   function check()
566   {  
567     $message = plugin::check();
568     if(empty($this->selectedPPD['link'])){
569       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
570     }
571     return($message); 
572   }
574 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
575 ?>