Code

Updated partition handling
[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  
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("core","ppdPath") != ""){
42             $this->pathToPPD = $config->get_cfg_value("core","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 information."));
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(gosa_file_name($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($this->dialog instanceOf printerPPDSelectionDialog){
169             $this->dialog->save_object();
170             if($this->dialog->isSelected()){
171                 $this->SelectPPD($this->dialog->save());
172                 unset($this->dialog);
173                 $this->dialog=FALSE;
174             }
175         }
177         /* if a dialog is open, print the dialog instead of this class */
178         if(is_object($this->dialog)){
179             $display = $this->dialog->execute();
180             return($display);
181         }
183         // ENDE  PPD selection / upload / dialog handling 
185         /* Give smarty the information it needs */
186         $smarty->assign("ppdString" ,$this->getPPDInformation());
187         $tmp= $this->generateProperties();
188         if ($tmp == ""){
189             $smarty->assign("showOptions", 0);
190         } else {
191             $smarty->assign("showOptions", 1);
192             $smarty->assign("properties",$this->generateProperties());
193         }
195         /* Print out template */
196         $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
197         return($display);
198     }
201     /* Select PPD */
202     function SelectPPD($name)
203     {
204         /* Replace base path we don't need it here 
205            The path we need looks like this : "/Vendor/ModellName.ppd"; 
206            thats all */
207         $name = preg_replace("#".$this->pathToPPD."#","",$name);
209         /* Intialise some base vars */
210         $AbsoluteSourceName       = $this->pathToPPD.$name;   
211         $AbsoluteDestinationPath  = $this->pathToPPD.$this->pathToModified;
212         $Vendor                   = ""; // Vendor 
213         $Name                     = ""; // Name 
214         $Modell                   = ""; // Modell
215         $PrinterName              = ""; // The new name of the printer 
216         $PPDName                  = "";
218         /* Force reload of config dialog */ 
219         $this->ppdConfig            = false;
220         $this->selectedPPD['link']  = false;
222         /* Get PPD informations and set vendor / modell / name */ 
223         if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
224             msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
225             return;
226         }
227         $ppdDesc  = $this->ppdManager->loadDescription($AbsoluteSourceName);
228         if($ppdDesc){
229             $Name   = $ppdDesc['name'];
230             $Vendor = $ppdDesc['manufacturer'];
231             $Model  = $ppdDesc['model'];
232         }    
234         $PrinterName  = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
235         $PPDName      = $Vendor."/".$PrinterName.".ppd";
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         }
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         $ppdDesc  = @$this->ppdManager->loadDescription($_PathOnHdd);
281         if($ppdDesc){
282             $name   = preg_replace("/\//","-",$ppdDesc['name']);
283             $vendor = $ppdDesc['manufacturer'];
284             $model  = $ppdDesc['model'];
285         }    
287         /* Check if parse was successfull */
288         if(empty($name) || empty($vendor)){
289             msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
290             return(false);
291         }
293         /* Prepare list of ppds */
294         if(!isset($this->ppdList[$vendor])){
295             $this->ppdList[$vendor] = array();
296         }
298         /* Create ppd file and fill in the source contents */
299         $ppdname      = $vendor."/".$name.".ppd";
300         $filename     = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
301         $filename     = $this->pathToPPD.$ppdname;
302         $contents     = file_get_contents($_PathOnHdd);
305         /* Check if this ppd already exists */
306         $found = false;
308         foreach($this->ppdList[$vendor] as $key => $val){
309             if(preg_match("/".preg_quote($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         }
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         }
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                 // Append the nickname to the ppds name, to be able to have multiple 
373                 //  ppd files for a printer type
374                 if(isset($ppd['nickname']) && !empty($ppd['nickname'])){
375                     $ppd['name'] .= " (".$ppd['nickname'].")";
376                 }
378                 if(preg_match("#".preg_quote($this->pathToModified,'#')."#",$file)) continue;
380                 if(!isset($ppd['manufacturer'])) continue;
382                 if(!isset($this->ppdListHeader[$ppd['manufacturer']])){
383                     $this->ppdListHeader[$ppd['manufacturer']]=0;
384                 }
386                 $tmp3['name']   =$ppd['name'];
387                 $tmp3['link']   =$file;
388                 $tmp3['ppd']    =$ppd;
389                 $this->ppdListHeader[$ppd['manufacturer']]++;
390                 $this->ppdList[$ppd['manufacturer']][$ppd['name']]=$tmp3;
391             }
392         }
393     }
396     /* Save all options posted from ppd dialog */
397     function save_object()
398     {
399         if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
400             return;
401         }
403         if(preg_match("/w/",$this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD"))){
404             foreach($this->ppdConfig as $cat => $obj){
405                 foreach($obj as $attr => $attributes){
406                     if(isset($_POST[base64_encode($attributes['_name'])])){
407                         $this->ppdConfig[$cat][$attr]['_default'] = get_post(base64_encode($attributes['_name']));
408                     }
409                 }
410             }
411         }
412     }
415     /* Save modified ppd */
416     function save_ppd()
417     {
418         if($this->ppdManager){
419             $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
420         }
421     }
424     /* Return selected ppd path, if none is selected then false */
425     function save()
426     {
427         /* return the selected PPD, and in future the selected options too */
428         return($this->pathToModified.$this->selectedPPD['link']);
429     }
432     /* Get Information for a single PPD entry 
433      * This will be shown on top of template
434      */
435     function getPPDInformation()
436     {
437         $str = "none";
438         if(!empty($this->selectedPPD)){
439             $ppdDesc = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
440             $str = $ppdDesc['name'];
441         }
442         return($str) ; 
443     }
445     /* Display all options from the selected ppd file */
446     function generateProperties()
447     { 
448         /* Set Headline */
449         $str = "";
450         $feed= "";
452         $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
454         /* If ppd exists and is readable */
455         if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
457             /* If there is no initial Configuration, load it */
458             if($this->ppdConfig == false){
459                 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
460             }
462             /* Create a table */
463             $str .= "<div style='padding-left:30px;'><table summary=''>";
465             /* Input all data to the table */
466             foreach($this->ppdConfig as $cat => $obj){
468                 /* Add new category */
469                 $str .= "<tr><td colspan='2'>$feed";
470                 if ($feed == ""){
471                     $feed= "<br>";
472                 }
473                 $str .= "<b>"._("Section")." '".$cat."'&nbsp;</b><br>";
474                 $str .= "</td></tr>";       
476                 /* Add attributes of the current category */
477                 foreach($obj as $attr => $settings){
479                     /* Skip all entries beginning with _ */
480                     if($attr[0] == "_") continue;  
482                     /* Prepare data */
483                     $values   = array();
484                     $name     = $settings['_name'];
486                     if (!isset($settings['_default'])){
487                         $default  = "";
488                     } else {
489                         $default  = $settings['_default'];
490                     }
492                     $type     = $settings['_type'];
494                     /* Add name to table */ 
495                     $str .= "<tr><td style='padding-left:40px;'>\n";
496                     $str .= $name."<br>\n";
497                     $str .= "</td><td>\n";
499                     /* Get all values */ 
500                     foreach( $settings as $vname => $value){
501                         if($vname[0] != "_"){
502                             $values[$vname]= $value;
503                         }
504                     }
506                     $acl ="";
507                     if(!preg_match("/w/",$this->ui->get_permissions($this->acl_base,"printer/printgeneric","gotoPrinterPPD"))){
508                         $acl = "disabled";
509                     }
511                     /* preparing Html output
512                      * Supported types are PickOne/Boolean
513                      */
515                     /* If type is PickOne, create a select box */
516                     if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
518                         $str  .=  "<select name='".base64_encode($name)."' $acl size='1'>\n";
519                         foreach($values as $optionKey => $value){
520                             $selected = "";
521                             if($optionKey == $default){
522                                 $selected = " selected ";
523                             }
524                             $str  .=  "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
525                         }
526                         $str  .=  "</select>\n";
528                     }elseif($type == "Boolean"){
530                         /* If type is Boolean & no values are given */
531                         $str  .=  "<select name='".base64_encode($name)."' $acl size='1'>\n";
532                         if($default == "False"){
533                             $str  .=    "<option value='True' >"._("True")."</option>\n";
534                             $str  .=    "<option value='False' selected>"._("False")."</option>\n";
535                         }else{
536                             $str  .=    "<option value='True' selected>"._("True")."</option>\n";
537                             $str  .=    "<option value='False' >"._("False")."</option>\n";
538                         }          
539                         $str  .=  "</select>\n";
541                     }elseif($this->config->get_cfg_value("core","displayErrors") == "true"){
542                         msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
543                     }
544                     $str .= "</td></tr>\n";
545                 }
546             }
547             $str .= "</table></div>\n";
548         }
549         return($str);
550     }
552     function removeModifiedPPD()
553     {
554         $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
556         if(file_exists($path)){
557             if(is_writeable($path)){
558                 if(!@unlink($path)){
559                     msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
560                 }
561             }else{
562                 msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
563             }
564         }else{
565             msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
566         }
567     }
569     function update_ppd_url()
570     {
571         $this->SelectPPD("modified/".$this->selectedPPD['link']);
572         return("modified/".$this->selectedPPD['link']);
573     }
575     function check()
576     {  
577         $message = plugin::check();
578         if(empty($this->selectedPPD['link'])){
579             $message[] = _("Please select a valid PPD file or use 'Cancel' to go back to printer configuration.");
580         }
581         return($message); 
582     }
584 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
585 ?>