Code

2f176e75a93eed251cc7bce270434166127c9ae2
[gosa.git] / trunk / 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           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
75           if($res){
76             $tmp = split("\n",$res);
77             $tmp3 = array(); 
78             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
79             $tmp3['link']   = $ppdfile;
80             $tmp3['ppd']    = $res;
81           }    
82           $this->selectedPPD = $tmp3;
83         }
84       }
85     }
86   }
89   function execute()
90   {
91     /* Call parent execute */
92     plugin::execute();
94     /* Fill templating stuff */
95     $display= "";
96     $smarty= get_smarty();
97     $smarty->assign("ppdString", _("Can't get ppd informations."));
98     $smarty->assign("showOptions", "");
99     $smarty->assign("path_valid", TRUE);
100     $smarty->assign("acl",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"));
102     $acl = $this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD");
104     if(empty($this->pathToPPD)){
106         /* Print out template */
107         $smarty->assign("path_valid", FALSE);
108         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
109         return($display);
110     }
112     /* Check these paths */
113     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
115     /* If one of our required paths is not available, stop here and display some info */
116     foreach($paths as $path){
118       /* Check if path is write/readable*/
119       $is_r = @is_readable($path);  
120       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
121         msg_dialog::display(_("Configuration error"), 
122             sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
124         /* Print out template */
125         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
126         return($display);
127       }
128     }
130     // PPD selection / upload / dialog handling 
132     /* Is there a new PPD file uploaded ? */
133     if(preg_match("/w/",$acl)){
134       if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
135         $file = ($_FILES['NewPPDFile']);
136         if($file['size'] != 0 ){
137           if($name = $this->AddPPD($file['tmp_name'])){
138             $this->SelectPPD($name); 
139           }
140         }else{
141           msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
142         }
143       }
144     }
146     /* Overwrite existing PPD file and select it as currently used for this object */
147     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
148       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
149         $this->SelectPPD($name);
150       }
151       $this->add_ppd_later = "";
152       $this->add_later_msg_dialog = NULL;
153     } 
155     /* Open a dialog that allow us to select different PPDs */
156     if(preg_match("/w/",$acl)){
157       if(isset($_POST['SelectPPD'])){
158         $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
159       }
160     }
162     /* The selection dialog fpr PPDs is canceled */
163     if(isset($_POST['ClosePPDSelection'])){
164       unset($this->dialog);
165       $this->dialog=FALSE;
166     }
168     /* Div Selection */ 
169     if((isset($_GET['act']))&&($_GET['act']=="use")){
170       $this->SelectPPD(base64_decode($_GET['id']));
171       unset($this->dialog);
172       $this->dialog=FALSE;
174     }
176     /* if a dialog is open, print the dialog instead of this class */
177     if(is_object($this->dialog)){
178       $display = $this->dialog->execute();
179       return($display);
180     }
182     // ENDE  PPD selection / upload / dialog handling 
184     /* Give smarty the information it needs */
185     $smarty->assign("ppdString" ,$this->getPPDInformation());
186     $tmp= $this->generateProperties();
187     if ($tmp == ""){
188       $smarty->assign("showOptions", 0);
189     } else {
190       $smarty->assign("showOptions", 1);
191       $smarty->assign("properties",$this->generateProperties());
192     }
194     /* Print out template */
195     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
196     return($display);
197   }
200   /* Select PPD */
201   function SelectPPD($name)
202   {
203     /* Replace base path we don't need it here 
204        The path we need looks like this : "/Vendor/ModellName.ppd"; 
205        thats all */
206     $name = preg_replace("#".$this->pathToPPD."#","",$name);
208     /* Intialise some base vars */
209     $AbsoluteSourceName       = $this->pathToPPD.$name;   
210     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
211     $Vendor                   = ""; // Vendor 
212     $Name                     = ""; // Name 
213     $Modell                   = ""; // Modell
214     $PrinterName              = ""; // The new name of the printer 
215     $PPDName                  = "";
216  
217     /* Force reload of config dialog */ 
218     $this->ppdConfig            = false;
219     $this->selectedPPD['link']  = false;
221     /* Get PPD informations and set vendor / modell / name */ 
222     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
223       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
224       return;
225     }
226     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
227     if($res){
228       $tmp = split("\n",$res);
229       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
230       $Vendor = trim($tmp[0]);
231       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
232     }    
234     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
235     $PPDName      = $Vendor."/".$PrinterName.".ppd";
236     
237     /* Create the vendors path, if it doesn't exists already */
238     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
239       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
240         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
241         return(false);
242       }
243     }
245     /* Create destination file handle */
246     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
247     if(!$fp){
248       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
249       return(false);
250     }
252     $str = file_get_contents($AbsoluteSourceName);
253     fputs($fp,$str);
254     @fclose($fp);
256     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
258     $tmp3['link']   =$PPDName;
259     $this->selectedPPD = $tmp3;
260     $this->getPrinterReload(); 
261     return($PPDName);
262   }
265   /* This function adds a new ppd file to the list of available ppds. 
266      All required paths and files will be created 
267       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
268   function AddPPD($_PathOnHdd,$overwrite = FALSE)
269   {
270     /* Check if file exists && is readable */
271     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
272       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
273       return(false);
274     }
275     
276     /* Reload list to detect changes e.g. a file has been deleted */
277     $this->getPrinterReload();
279     /* Get Description from ppd, & parse out some informations */   
280     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
281     if($res){
282       $tmp = split("\n",$res);
283       $name   = @trim(preg_replace("/^\-/","",trim($tmp[1])));
284       $vendor = @trim($tmp[0]);
285       $model  = @trim(preg_replace("/".$vendor."/","",$name));
286     }    
288     /* Check if parse was successfull */
289     if(empty($name) || empty($vendor)){
290       msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
291       return(false);
292     }
294     /* Prepare list of ppds */
295     if(!isset($this->ppdList[$vendor])){
296       $this->ppdList[$vendor] = array();
297     }
299     /* Create ppd file and fill in the source contents */
300     $ppdname      = $vendor."/".$name.".ppd";
301     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
302     $filename     = $this->pathToPPD.$ppdname;
303     $contents     = file_get_contents($_PathOnHdd);
306     /* Check if this ppd already exists */
307     $found = false;
308     foreach($this->ppdList[$vendor] as $key => $val){
309       if(preg_match("/".$model.".*/i",$key)){
310         $found = true;
311         if(!$overwrite){
312           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
313             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
314           }else{
315             $this->add_ppd_later = $_PathOnHdd."_back";
316             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
317                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
318           }
319           return;
320         }
321       }
322     }
324     /* Create the vendors path, if it doesn't exists already */
325     if(!is_dir($this->pathToPPD.$vendor)){
326       if(!(@mkdir($this->pathToPPD.$vendor))){
327         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
328         return(false);
329       }
330     }
331   
332     /* Open file handle */
333     $fp           = fopen($filename,"w+");
335     /* Check file handle & contents */
336     if(!$fp){
337       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
338       return;
339     }
340     if(empty($contents)){
341       msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
342       return;
343     }
344     
345     /* Fille file with data */
346     fputs($fp,$contents);
347     @fclose($fp);
349     /* Our job is done here */
350     return($ppdname);
351   }
354   /* This function reloads the list of available printers/vendors 
355      $this->ppdListHeader 
356      Compaq        => 1
357      $this->ppdList
358      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
359      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
360      ppd  => Compaq - Co    
361    */
362   function getPrinterReload()
363   {
364     if(is_readable($this->pathToPPD)){
365       $tmp = @$this->ppdManager->getPrinterList(true);
367       $this->ppdListHeader = $this->ppdList = array();
369       /* Sort all available files, and create header (Vendor index) */
370       foreach($tmp as $file=>$ppd){
372         if(preg_match("#".$this->pathToModified."#",$file)) continue;
374         $tmp2 = split("\n",$ppd);
375         if(!isset($this->ppdListHeader[$tmp2[0]])){
376           $this->ppdListHeader[$tmp2[0]]=0;
377         }
378         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
379         $tmp3['link']   =$file;
380         $tmp3['ppd']    =$ppd;
381         $this->ppdListHeader[$tmp2[0]]++;
382         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
383       }
384     }
385   }
388   /* Save all options posted from ppd dialog */
389   function save_object()
390   {
391     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
392       return;
393     }
395     if(preg_match("/w/",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"))){
396       foreach($this->ppdConfig as $cat => $obj){
397         foreach($obj as $attr => $attributes){
398           if(isset($_POST[base64_encode($attributes['_name'])])){
399             $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
400           }
401         }
402       }
403     }
404   }
407   /* Save modified ppd */
408   function save_ppd()
409   {
410     if($this->ppdManager){
411       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
412     }
413   }
416   /* Return selected ppd path, if none is selected then false */
417   function save()
418   {
419     /* return the selected PPD, and in future the selected options too */
420     return($this->pathToModified.$this->selectedPPD['link']);
421   }
424   /* Get Information for a single PPD entry 
425    * This will be shown on top of template
426    */
427   function getPPDInformation()
428   {
429     $str = "none";
430     if(!empty($this->selectedPPD)){
431       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
432     }
433     return($str) ; 
434   }
437   /* Display all options from the selected ppd file */
438   function generateProperties()
439   { 
440     /* Set Headline */
441     $str = "";
442     $feed= "";
444     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
446     /* If ppd exists and is readable */
447     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
449       /* If there is no initial Configuration, load it */
450       if($this->ppdConfig == false){
451         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
452       }
454       /* Create a table */
455       $str .= "<div style='padding-left:30px;'><table summary=''>";
457       /* Input all data to the table */
458       foreach($this->ppdConfig as $cat => $obj){
460         /* Add new category */
461         $str .= "<tr><td colspan='2'>$feed";
462         if ($feed == ""){
463           $feed= "<br>";
464         }
465         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
466         $str .= "</td></tr>";       
468         /* Add attributes of the current category */
469         foreach($obj as $attr => $settings){
471           /* Skip all entries beginning with _ */
472           if($attr[0] == "_") continue;  
474           /* Prepare data */
475           $values   = array();
476           $name     = $settings['_name'];
478           if (!isset($settings['_default'])){
479             $default  = "";
480           } else {
481             $default  = $settings['_default'];
482           }
484           $type     = $settings['_type'];
486           /* Add name to table */ 
487           $str .= "<tr><td style='padding-left:40px;'>\n";
488           $str .= $name."<br>\n";
489           $str .= "</td><td>\n";
491           /* Get all values */ 
492           foreach( $settings as $vname => $value){
493             if($vname[0] != "_"){
494               $values[$vname]= $value;
495             }
496           }
498           $acl ="";
499           if(!preg_match("/w/",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"))){
500             $acl = "disabled";
501           }
503           /* preparing Html output
504            * Supported types are PickOne/Boolean
505            */
507           /* If type is PickOne, create a select box */
508           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
510             $str  .=  "<select name='".base64_encode($name)."' $acl >\n";
511             foreach($values as $optionKey => $value){
512               $selected = "";
513               if($optionKey == $default){
514                 $selected = " selected ";
515               }
516               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
517             }
518             $str  .=  "</select>\n";
520           }elseif($type == "Boolean"){
522             /* If type is Boolean & no values are given */
523             $str  .=  "<select name='".base64_encode($name)."' $acl>\n";
524             if($default == "False"){
525               $str  .=    "<option value='True' >"._("True")."</option>\n";
526               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
527             }else{
528               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
529               $str  .=    "<option value='False' >"._("False")."</option>\n";
530             }          
531             $str  .=  "</select>\n";
533           }else{
534             msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
535           }
536           $str .= "</td></tr>\n";
537         }
538       }
539       $str .= "</table></div>\n";
540     }
541     return($str);
542   }
544   function removeModifiedPPD()
545   {
546     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
548     if(file_exists($path)){
549       if(is_writeable($path)){
550         if(!@unlink($path)){
551           msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
552         }
553       }else{
554         msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
555       }
556     }else{
557       msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
558     }
559   }
561   function update_ppd_url()
562   {
563     $this->SelectPPD("modified/".$this->selectedPPD['link']);
564     return("modified/".$this->selectedPPD['link']);
565   }
566   
567   function check()
568   {  
569     $message = plugin::check();
570     if(empty($this->selectedPPD['link'])){
571       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
572     }
573     return($message); 
574   }
576 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
577 ?>