Code

Fixed typo
[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, 
24   /* If there is already a ppd file for the same type of printer, 
25    *  remember the path to ppd file and display a dialog which allows 
26    *  to overwrite the current ppd file. 
27    */
28   var $add_ppd_later            = "";
29   var $add_later_msg_dialog     = NULL;
31   function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
32   {
33     plugin::plugin ($config, $dn);
34     $this->depselect = $this->config->current['BASE'];
36     /* Get PPD path and remove double //, and add trailing /  */
37     $config = session::get('config');
38     if(isset($config->data['MAIN']['PPD_PATH'])){
39       $this->pathToPPD = $config->data['MAIN']['PPD_PATH'];
40       $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
41       if(!preg_match("/\/$/",$this->pathToPPD)){
42         $this->pathToPPD = $this->pathToPPD."/";
43       }
44     }else{
45       $this->pathToPPD = "";
46     }
48     /* It seams that we have an existing PPD path, so go on */
49     if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){ 
51       /* Load all available PPD files and sort them into an array */
52       $this->ppdManager= new ppdManager($this->pathToPPD);
53       $this->getPrinterReload ();
55       /* The user has already a valid PPD assigned
56        * Get some informations about this PPD
57        * and set it as selected. 
58        * The ppdpath ['link'] should be relative from .../ppd/modified/ 
59        *     e.g. "/Compaq/Compaq-J1200.ppd" */
60       if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
61         $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
62         if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
63           msg_dialog::display(_("PPD error"), sprintf(_("Cannot open PPD '%s'!"), $ppdfile), ERROR_DIALOG);
64         }else{
65           $res  = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
66           if($res){
67             $tmp = split("\n",$res);
68             $tmp3 = array(); 
69             $tmp3['name']   = trim(preg_replace("/^\-/","",trim($tmp[1])));
70             $tmp3['link']   = $ppdfile;
71             $tmp3['ppd']    = $res;
72           }    
73           $this->selectedPPD = $tmp3;
74         }
75       }
76     }
77   }
80   function execute()
81   {
82     /* Call parent execute */
83     plugin::execute();
85     /* Fill templating stuff */
86     $display= "";
87     $smarty= get_smarty();
88     $smarty->assign("ppdString", _("Can't get ppd informations."));
89     $smarty->assign("showOptions", "");
91     /* Check these paths */
92     $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
94     /* If one of our required paths is not available, stop here and display some info */
95     foreach($paths as $path){
96     
97       /* Check if path is write/readable*/
98       $is_r = @is_readable($path);  
99       if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
100         msg_dialog(_("Configuration error"), sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
102         /* Print out template */
103         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
104         return($display);
105       }
106     }
108     // PPD selection / upload / dialog handling 
110     /* Is there a new PPD file uploaded ? */
111     if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
112       $file = ($_FILES['NewPPDFile']);
113       if($file['size'] != 0 ){
114         if($name = $this->AddPPD($file['tmp_name'])){
115           $this->SelectPPD($name); 
116         }
117       }else{
118         msg_dialog(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
119       }
120     }
122     /* Overwrite existing PPD file and select it as currently used for this object */
123     if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
124       if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
125         $this->SelectPPD($name);
126       }
127       $this->add_ppd_later = "";
128       $this->add_later_msg_dialog = NULL;
129     } 
131     /* Open a dialog that allow us to select different PPDs */
132     if(isset($_POST['SelectPPD'])){
133       $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
134     }
136     /* The selection dialog fpr PPDs is canceled */
137     if(isset($_POST['ClosePPDSelection'])){
138       unset($this->dialog);
139       $this->dialog=FALSE;
140     }
142     /* Div Selection */ 
143     if((isset($_GET['act']))&&($_GET['act']=="use")){
144       $this->SelectPPD(base64_decode($_GET['id']));
145       unset($this->dialog);
146       $this->dialog=FALSE;
148     }
150     /* if a dialog is open, print the dialog instead of this class */
151     if(is_object($this->dialog)){
152       $display = $this->dialog->execute();
153       return($display);
154     }
156     // ENDE  PPD selection / upload / dialog handling 
158     /* Give smarty the information it needs */
159     $smarty->assign("ppdString" ,$this->getPPDInformation());
160     $tmp= $this->generateProperties();
161     if ($tmp == ""){
162       $smarty->assign("showOptions", 0);
163     } else {
164       $smarty->assign("showOptions", 1);
165       $smarty->assign("properties",$this->generateProperties());
166     }
168     /* Print out template */
169     $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
170     return($display);
171   }
174   /* Select PPD */
175   function SelectPPD($name)
176   {
177     /* Replace base path we don't need it here 
178        The path we need looks like this : "/Vendor/ModellName.ppd"; 
179        thats all */
180     $name = preg_replace("#".$this->pathToPPD."#","",$name);
182     /* Intialise some base vars */
183     $AbsoluteSourceName       = $this->pathToPPD.$name;   
184     $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
185     $Vendor                   = ""; // Vendor 
186     $Name                     = ""; // Name 
187     $Modell                   = ""; // Modell
188     $PrinterName              = ""; // The new name of the printer 
189     $PPDName                  = "";
190  
191     /* Force reload of config dialog */ 
192     $this->ppdConfig            = false;
193     $this->selectedPPD['link']  = false;
195     /* Get PPD informations and set vendor / modell / name */ 
196     if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
197       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
198       return;
199     }
200     $res  = $this->ppdManager->loadDescription($AbsoluteSourceName);
201     if($res){
202       $tmp = split("\n",$res);
203       $Name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
204       $Vendor = trim($tmp[0]);
205       $Model  = trim(preg_replace("/".$Vendor."/","",$Name));
206     }    
208     $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
209     $PPDName      = $Vendor."/".$PrinterName.".ppd";
210     
211     /* Create the vendors path, if it doesn't exists already */
212     if(!is_dir($AbsoluteDestinationPath.$Vendor)){
213       if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
214         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
215         return(false);
216       }
217     }
219     /* Create destination file handle */
220     $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
221     if(!$fp){
222       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
223       return(false);
224     }
226     $str = file_get_contents($AbsoluteSourceName);
227     fputs($fp,$str);
228     @fclose($fp);
230     //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
232     $tmp3['link']   =$PPDName;
233     $this->selectedPPD = $tmp3;
234     $this->getPrinterReload(); 
235     return($PPDName);
236   }
239   /* This function adds a new ppd file to the list of available ppds. 
240      All required paths and files will be created 
241       $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
242   function AddPPD($_PathOnHdd,$overwrite = FALSE)
243   {
244     /* Check if file exists && is readable */
245     if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
246       msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
247       return(false);
248     }
249     
250     /* Reload list to detect changes e.g. a file has been deleted */
251     $this->getPrinterReload();
253     /* Get Description from ppd, & parse out some informations */   
254     $res  = @$this->ppdManager->loadDescription($_PathOnHdd);
255     if($res){
256       $tmp = split("\n",$res);
257       $name   = trim(preg_replace("/^\-/","",trim($tmp[1])));
258       $vendor = trim($tmp[0]);
259       $model  = trim(preg_replace("/".$vendor."/","",$name));
260     }    
262     /* Check if parse was successfull */
263     if(empty($name) || empty($vendor)){
264       msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
265       return(false);
266     }
268     /* Prepare list of ppds */
269     if(!isset($this->ppdList[$vendor])){
270       $this->ppdList[$vendor] = array();
271     }
273     /* Create ppd file and fill in the source contents */
274     $ppdname      = $vendor."/".$name.".ppd";
275     $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
276     $filename     = $this->pathToPPD.$ppdname;
277     $contents     = file_get_contents($_PathOnHdd);
280     /* Check if this ppd already exists */
281     $found = false;
282     foreach($this->ppdList[$vendor] as $key => $val){
283       if(preg_match("/".$model.".*/i",$key)){
284         $found = true;
285         if(!$overwrite){
286           if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
287             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
288           }else{
289             $this->add_ppd_later = $_PathOnHdd."_back";
290             $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
291                 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
292           }
293           return;
294         }
295       }
296     }
298     /* Create the vendors path, if it doesn't exists already */
299     if(!is_dir($this->pathToPPD.$vendor)){
300       if(!(@mkdir($this->pathToPPD.$vendor))){
301         msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
302         return(false);
303       }
304     }
305   
306     /* Open file handle */
307     $fp           = fopen($filename,"w+");
309     /* Check file handle & contents */
310     if(!$fp){
311       msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
312       return;
313     }
314     if(empty($contents)){
315       msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
316       return;
317     }
318     
319     /* Fille file with data */
320     fputs($fp,$contents);
321     @fclose($fp);
323     /* Our job is done here */
324     return($ppdname);
325   }
328   /* This function reloads the list of available printers/vendors 
329      $this->ppdListHeader 
330      Compaq        => 1
331      $this->ppdList
332      Compaq => Compaq IJ1200 => name => Compaq IJ1200 
333      link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
334      ppd  => Compaq - Co    
335    */
336   function getPrinterReload()
337   {
338     if(is_readable($this->pathToPPD)){
339       $tmp = @$this->ppdManager->getPrinterList(true);
341       $this->ppdListHeader = $this->ppdList = array();
343       /* Sort all available files, and create header (Vendor index) */
344       foreach($tmp as $file=>$ppd){
346         if(preg_match("#".$this->pathToModified."#",$file)) continue;
348         $tmp2 = split("\n",$ppd);
349         if(!isset($this->ppdListHeader[$tmp2[0]])){
350           $this->ppdListHeader[$tmp2[0]]=0;
351         }
352         $tmp3['name']   =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
353         $tmp3['link']   =$file;
354         $tmp3['ppd']    =$ppd;
355         $this->ppdListHeader[$tmp2[0]]++;
356         $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
357       }
358     }
359   }
362   /* Save all options posted from ppd dialog */
363   function save_object()
364   {
365     if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
366       return;
367     }
369     foreach($this->ppdConfig as $cat => $obj){
370       foreach($obj as $attr => $attributes){
371         if(isset($_POST[base64_encode($attributes['_name'])])){
372           $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
373         }
374       }
375     }
376   }
379   /* Save modified ppd */
380   function save_ppd()
381   {
382     if($this->ppdManager){
383       $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
384     }
385   }
388   /* Return selected ppd path, if none is selected then false */
389   function save()
390   {
391     /* return the selected PPD, and in future the selected options too */
392     return($this->pathToModified.$this->selectedPPD['link']);
393   }
396   /* Get Information for a single PPD entry 
397    * This will be shown on top of template
398    */
399   function getPPDInformation()
400   {
401     $str = "none";
402     if(!empty($this->selectedPPD)){
403       $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
404     }
405     return($str) ; 
406   }
409   /* Display all options from the selected ppd file */
410   function generateProperties()
411   { 
412     /* Set Headline */
413     $str = "";
414     $feed= "";
416     $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
418     /* If ppd exists and is readable */
419     if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
421       /* If there is no initial Configuration, load it */
422       if($this->ppdConfig == false){
423         $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
424       }
426       /* Create a table */
427       $str .= "<div style='padding-left:30px;'><table summary=''>";
429       /* Input all data to the table */
430       foreach($this->ppdConfig as $cat => $obj){
432         /* Add new category */
433         $str .= "<tr><td colspan='2'>$feed";
434         if ($feed == ""){
435           $feed= "<br>";
436         }
437         $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
438         $str .= "</td></tr>";       
440         /* Add attributes of the current category */
441         foreach($obj as $attr => $settings){
443           /* Skip all entries beginning with _ */
444           if($attr[0] == "_") continue;  
446           /* Prepare data */
447           $values   = array();
448           $name     = $settings['_name'];
450           if (!isset($settings['_default'])){
451             $default  = "";
452           } else {
453             $default  = $settings['_default'];
454           }
456           $type     = $settings['_type'];
458           /* Add name to table */ 
459           $str .= "<tr><td style='padding-left:40px;'>\n";
460           $str .= $name."<br>\n";
461           $str .= "</td><td>\n";
463           /* Get all values */ 
464           foreach( $settings as $vname => $value){
465             if($vname[0] != "_"){
466               $values[$vname]= $value;
467             }
468           }
470           /* preparing Html output
471            * Supported types are PickOne/Boolean
472            */
474           /* If type is PickOne, create a select box */
475           if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
477             $str  .=  "<select name='".base64_encode($name)."'>\n";
478             foreach($values as $optionKey => $value){
479               $selected = "";
480               if($optionKey == $default){
481                 $selected = " selected ";
482               }
483               $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
484             }
485             $str  .=  "</select>\n";
487           }elseif($type == "Boolean"){
489             /* If type is Boolean & no values are given */
490             $str  .=  "<select name='".base64_encode($name)."'>\n";
491             if($default == "False"){
492               $str  .=    "<option value='True' >"._("True")."</option>\n";
493               $str  .=    "<option value='False' selected>"._("False")."</option>\n";
494             }else{
495               $str  .=    "<option value='True' selected>"._("True")."</option>\n";
496               $str  .=    "<option value='False' >"._("False")."</option>\n";
497             }          
498             $str  .=  "</select>\n";
500           }else{
501             msg_dialog(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
502           }
503           $str .= "</td></tr>\n";
504         }
505       }
506       $str .= "</table></div>\n";
507     }
508     return($str);
509   }
511   function removeModifiedPPD()
512   {
513     $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
515     if(file_exists($path)){
516       if(is_writeable($path)){
517         if(!@unlink($path)){
518           msg_dialog(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
519         }
520       }else{
521         msg_dialog(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
522       }
523     }else{
524       msg_dialog(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
525     }
526   }
528   function update_ppd_url()
529   {
530     $this->SelectPPD("modified/".$this->selectedPPD['link']);
531     return("modified/".$this->selectedPPD['link']);
532   }
533   
534   function check()
535   {  
536     $message = plugin::check();
537     if(empty($this->selectedPPD['link'])){
538       $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
539     }
540     return($message); 
541   }
543 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
544 ?>