Code

removed defaults from get_cfg_value and added some missing properties.
[gosa.git] / gosa-plugins / goto / admin / systems / ppd / class_ppdManager.inc
1 <?php
3 class ppdManager
4 {
5         var $path= "";
6         var $cachedList= array();
7         var $timestamps = array();
9   var $useGzip  = true;
11   function ppdManager($path)
12   {
13       global $config;
14       if($config->boolValueIsTrue("core","ppdGzip")){
15           $this->useGzip  = false;
16       }
18       if(is_dir($path)){
19           $this->path= $path;
20       }elseif(is_link($path) && (is_dir(readlink($path)))) {
21           $this->path= $path;
22       } else {
23           msg_dialog::display(_("PPD manager error"), sprintf(_("The specified path '%s' does not exist."),$path), ERROR_DIALOG);
24           return (false);
25       }
26   }
29         function findPPD($path)
30         {
31                 $list= array();
32                 $currentDir= getcwd();
34                 $dh = opendir($path);
35                 while(false !== ($file = readdir($dh))){
37                         /* Skip well known files */
38                         if( $file == '.' || $file == '..'){
39                                 continue;
40                         }
42                         /* Recurse through all "common" directories */
43                         $check_path= $path.'/'.$file;
44                         if(is_dir($check_path) || (is_link($check_path) && (is_dir(readlink($check_path))))){
45                                 $list= array_merge($list, $this->findPPD($check_path));
46                                 continue;
47                         }
49                         /* Check for PPD extension */
50                         if (preg_match('/\.ppd(.gz)?$/i', $file)){
51                                 $list[]= $path.'/'.$file;
52                         }
53                 }
55                 closedir($dh);
56                 chdir ($currentDir);
57                 return ($list);
58         }
61         function updateAttribute($file, $section, $attribute, $value)
62         {
63                 $fsection= false;
64                 $fattribute= false;
65                 $section= preg_replace('/^\*/', '', $section);
66                 $attribute= preg_replace('/^\*/', '', $attribute);
68     if($this->useGzip){
69       $rp= @gzopen($file, "r");
70       $wp= @gzopen("$file.tmp", "w");
71     }else{
72       $rp= @gzopen($file, "r");
73       $wp= @fopen("$file.tmp", "w");
74     }
76           if($this->useGzip){   
77       while (!gzeof($rp)){
78         $lines[]= gzgets($rp, 1024);
79       }
80     }else{
81       while (!feof($rp)){
82         $lines[]= fgets($rp, 1024);
83       }
84     }
86                 $ret = "";
87                 $done =false;
88                 foreach($lines as $nr => $line){
89         
90                         if (preg_match("/\*OpenGroup:*\s+\**$section\/*/", $line)){
91                 $fsection= true;
92                                 $ret .=$line; 
93                 continue;
94             }
96                         /* Change model name .. */
97                         if ((preg_match("/^\*".$attribute.":*\s+/",$line)) && ($attribute == "ModelName")){
98                                 $line= "*$attribute: \"$value\"\n";
99                                 $done =true;
100                         }
102                         if (($fsection) && ($section != "NO_SECTION")){
103                                 if (preg_match("/^\*CloseGroup:*\s+\**$section\/*/", $line)){
104                                         $fsection= false;
105                                         $ret .=$line; 
106                                         continue;
107                                 }
110                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
111                                         $fattribute= true;
112                                         $ret .= $line; 
113                                         continue;
114                                 }
116                                 if ($fattribute){
117                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
118                                                 $fattribute= false;
119                                                 $ret .= $line; 
120                                                 continue;
121                                         }
123                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
124                                                 $line= "*Default$attribute: $value\n";
125                                                 $done =true;
126                                         }
127                                 }
128                         }else{
129                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
130                                         $fattribute= true;
131                                         $ret .= $line; 
132                                         continue;
133                                 }
135                                 if ($fattribute){
136                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
137                                                 $fattribute= false;
138                                                 $ret .= $line; 
139                                                 continue;
140                                         }
142                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
143                                                 $line= "*Default$attribute: $value\n";
144                                                 $done =true;
145                                         }
146                                 }
147                         }
148                         $ret .=$line; 
149                 }
151     if($this->useGzip){
152       gzwrite($wp,$ret);
153       gzclose($wp);
154       gzclose($rp);
155     }else{
156      fwrite($wp,$ret);
157      fclose($wp);
158      gzclose($rp);
159     }
161                 copy("$file.tmp", "$file");
162                 unlink("$file.tmp");
163         }
166         function saveProperties($ppdFile, $properties)
167         {
168                 if(!is_readable($ppdFile)){
169                         msg_dialog::display(_("PPD manager error"), sprintf(_("Specified PPD file '%s' cannot be opened for reading."),$ppdFile), ERROR_DIALOG);
170                 }elseif(!is_writeable(preg_replace("#(^.*/).*$#","\\1",$ppdFile.".tmp"))){
171                         msg_dialog::display(_("PPD manager error"), sprintf(_("The temporary file '%s' cannot be opened for writing."),$ppdFile.".tmp"), ERROR_DIALOG);
172                 }else{
173                         if(is_array($properties)){
174                                 foreach ($properties as $name => $section){
175                                         foreach ($section as $attribute => $value){
176                                                 if (is_array($value)){
177                                                         $this->updateAttribute($ppdFile, $name, $attribute, $value['_default']);
178                                                 }
179                                         }
180                                 }
181                         }
182                 }
183         }
185         function loadProperties($ppdFile)
186         {
187                 $group= "";
188                 $option= "";
189                 $properties= array();
191                 // Check for empty files
192                 if(!filesize($ppdFile)) {
193                         trigger_error(_('Parsing PPD file failed - file is empty!'));
194                         return;
195                 }
197                 $fh= gzopen ($ppdFile, 'r');
198                 while (!gzeof($fh) && $fh){
200                         /* Read line */
201                         $line= gzgets($fh, 256);
202                         if (strlen($line) >= 256){
203                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored!'), E_USER_WARNING);
204                         }
206                         /* Trigger for option groups */
207                         if (preg_match('/^\*OpenGroup:/i', $line)){
209                                 /* Sanity checks */
210                                 if ($group != ""){
211                                         trigger_error(_('Nested groups are not supported!'), E_USER_WARNING);
212                                         continue;
213                                 }
214                                 if (in_array($group, $properties)){
215                                         trigger_error(_('Group name not unique!'), E_USER_WARNING);
216                                         continue;
217                                 }
219                                 // TODO: Symbol values are not supported yet!
220                                 if (preg_match('/\^/', $line)){
221                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
222                                 }
223                                 $complete= preg_replace('@^\*OpenGroup:\s+(.*)$@i', '\1', $line);
224                                 $complete= trim($complete, '"');
225                                 if (preg_match('@/@', $complete)){
226                                         $group= trim(preg_replace('@^\*OpenGroup:\s+"?([^/]+)/.*$@i', '\1', $line));
227                                         $name = preg_replace('@^\*OpenGroup:\s+"?[^/]+/([^/]+).*$@i', '\1', $line);
228                                 } else {
229                                         $group= $complete;
230                                         $name = $complete;
231                                 }
232                                 $properties[$group]= array('_name' => $name);
233                                 continue;
234                         }
235                         if (preg_match("/^\*CloseGroup:\s+\"?$group\"?/i", $line)){
236                                 $group= "";
237                                 continue;
238                         }
240                         /* Trigger for options */
241                         if (preg_match('/^\*OpenUI\s+/i', $line)){
243                                 /* Sanity check */
244                                 if ($option != ""){
245                                         trigger_error(_('Nested options are not supported!'), E_USER_WARNING);
246                                         continue;
247                                 }
249                                 // TODO: Symbol values are not supported yet!
250                                 if (preg_match('/\^/', $line)){
251                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
252                                 }
253                                 $complete= preg_replace('@^\*OpenUI\s+(.*)$@i', '\1', $line);
254                                 $complete= trim($complete, '"');
255                                 if (preg_match('@/@', $complete)){
256                                         $option= trim(preg_replace('@^\*OpenUI\s+([^/]+)/.*$@i', '\1', $line));
257                                         $name = trim(preg_replace('@^\*OpenUI\s+[^/]+/([^/]+).*$@i', '\1', $line));
258                                 } else {
259                                         $option= trim($complete);
260                                         $name  = trim($complete);
261                                 }
263                                 /* Extract option type */
264                                 $type= trim(preg_replace('/^[^:]+:\s+/', '', $line));
265                                 $name= preg_replace('/:.*$/', '', $name);
266                                 $option= preg_replace('/:.*$/', '', $option);
268                                 // TODO: PickMany is not supported yet!
269                                 if (preg_match('/PickMany/i', $type)){
270                                         trigger_error(_('PickMany is not supported yet!'), E_USER_WARNING);
271                                 }
272                                 if(empty($group)){
273                                         $properties["NO_SECTION"][$option]= array('_name' => $name, '_type' => $type);
274                                 }else{
275                                         $properties[$group][$option]= array('_name' => $name, '_type' => $type);
276                                 }
277                                 continue;
278                         }
279                         /* Show interest for option parsing */
280                         if ($option != ""){
282                                 $eoption= preg_replace('@\*@', '', $option);
284                                 /* Close section? */
285                                 if (preg_match("@^\*CloseUI:\s+\*$eoption@i", $line)){
286                                         $option= "";
287                                         continue;
288                                 }
290                                 /* Default value? */
291                                 if (preg_match("@^\*Default$eoption:@", $line)){
292                                         $c= preg_replace("@^\*Default$eoption:\s+@", "", $line);
293                                         if(empty($group)){
294                                                 $properties["NO_SECTION"][$option]['_default']= trim(trim($c, '"'));
295                                         }else{
296                                                 $properties[$group][$option]['_default']= trim(trim($c, '"'));
297                                         }
298                                         continue;
299                                 }
301                                 /* Possible value? */
302                                 if (preg_match("@^\*$eoption\s+@", $line)){
304                     // Detect what comes first, the  '/' or the ':'. 
305                     // We may have entries like this: 
306                     //  *Resolution 300dpi: "<</HWResolution [300 300] >> setpagedevice"
307                     // and
308                     //  *Resolution 300dpi/300: "<</HWResolution [300 300] >> setpagedevice"
309                     $name = $value = preg_replace("@^\*$eoption\s+([^:]+).*$@", "$1", $line);
310                     if(preg_match("/\//", $name)){
311                         list($name, $value) = preg_split("/\//", $name);
312                     }
313                                         if(empty($group)){
314                                                 $properties["NO_SECTION"][$option][$name]= $value;
315                                         }else{
316                                                 $properties[$group][$option][$name]= $value;
317                                         }
318                                         continue;
319                                 }
320                         }
321                 }
323         gzclose ($fh);
324                 return ($properties);
325         }
327         function loadDescription($ppdFile)
328         {
329                 // Check for empty files
330                 if(!filesize($ppdFile)) {
331                         trigger_error(_('Parsing PPD file failed - file is empty!'));
332                         return;
333                 }
335                 $ppdDesc = array();
336         
337                 /* Only parse complete PPD file again, if it was changed */
338                 $modified = filemtime($ppdFile);
339                 if(isset($this->cachedList[$ppdFile]) && isset($this->timestamps[$ppdFile]) && $modified == $this->timestamps[$ppdFile]){
340                         return($this->cachedList[$ppdFile]);
341                 }
343                 /* Remember modified timestamp, to speed up next request */
344                 $this->timestamps[$ppdFile] = filemtime($ppdFile);
345                 $fh= gzopen ($ppdFile, 'r');
347                 while (!gzeof($fh) && $fh){
349                         $line= gzgets($fh, 256);
350                         if (strlen($line) >= 256){
351                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
352                         }
354                         /* Extract interesting informations */
355                         if (preg_match('/^\*Manufacturer:/i', $line)){
356         $ppdDesc['manufacturer'] = trim(preg_replace('/^\*Manufacturer:\s+"?([^"]+)"?.*$/i', '\1',    $line));
357                         }
358                         if (preg_match('/^\*ModelName:/i', $line)){
359         $ppdDesc['model'] = trim(preg_replace('/^\*ModelName:\s+"?([^"]+)"?.*$/i', '\1', $line));
360                         }
362                         /* Got everything we need? Skip rest for speed reasons... */
363       if (isset($ppdDesc['manufacturer'])  && isset($ppdDesc['model'])){
364                                 break;
365                         }
366                 }
368                 gzclose ($fh);
370     /* If model contains manufacturer strip it */
371     $ppdDesc['model'] = str_replace($ppdDesc['manufacturer']." ", '', $ppdDesc['model']);
373                 /* Write out a notice that the PPD file seems to be broken if we can't
374                    extract any usefull informations */
375     if ($ppdDesc['manufacturer'] == '' || $ppdDesc['model'] == ''){
376                         trigger_error(sprintf(_('Parsing PPD file %s failed - no information found.'), $ppdFile), E_USER_WARNING);
377                 }
379     $ppdDesc['name'] = $ppdDesc['manufacturer'] . " - " . $ppdDesc['model'];
380     return $ppdDesc;
381         }
384         function getPrinterList($reload= false)
385         {
386                 /* Load list of PPD files */
387                 if (count($this->cachedList) == 0 || $reload){
388                         $list= $this->findPPD($this->path);
390                         /* Load descriptive informations to build final printer list */
391                         $new = array();
392                         foreach ($list as $ppdFile){
393                                 $new[$ppdFile] = $this->loadDescription($ppdFile); 
394                         }
395                         $this->cachedList= $new ;
397                 }
399                 return ($this->cachedList);
400         }
403 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
404 ?>