Code

64d23e3fd7b0e6001cf0125f5f807e1edc858501
[gosa.git] / trunk / 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         function ppdManager($path)
10         {
11                 if(is_dir($path)){
12                         $this->path= $path;
13                 }elseif(is_link($path) && (is_dir(readlink($path)))) {
14                     $this->path= $path;
15                 } else {
16                         msg_dialog::display(_("PPD manager error"), sprintf(_("The specified path '%s' does not exist."),$path), ERROR_DIALOG);
17                         return (false);
18                 }
19         }
22         function findPPD($path)
23         {
24                 $list= array();
25                 $currentDir= getcwd();
27                 $dh = opendir($path);
28                 while(false !== ($file = readdir($dh))){
30                         /* Skip well known files */
31                         if( $file == '.' || $file == '..'){
32                                 continue;
33                         }
35                         /* Recurse through all "common" directories */
36                         $check_path= $path.'/'.$file;
37                         if(is_dir($check_path) || (is_link($check_path) && (is_dir(readlink($check_path))))){
38                                 $list= array_merge($list, $this->findPPD($check_path));
39                                 continue;
40                         }
42                         /* Check for PPD extension */
43                         if (preg_match('/\.ppd(.gz)?$/i', $file)){
44                                 $list[]= $path.'/'.$file;
45                         }
46                 }
48                 closedir($dh);
49                 chdir ($currentDir);
50                 return ($list);
51         }
54         function updateAttribute($file, $section, $attribute, $value)
55         {
56                 $fsection= false;
57                 $fattribute= false;
58                 $section= preg_replace('/^\*/', '', $section);
59                 $attribute= preg_replace('/^\*/', '', $attribute);
61                 $rp= @gzopen($file, "r");
62                 $wp= @gzopen("$file.tmp", "w");
64                 
66                 while (!gzeof($rp)){
67                         $lines[]= gzgets($rp, 1024);
68                 }
70                 $ret = "";
71                 $done =false;
72                 foreach($lines as $nr => $line){
73         
74                         if (preg_match("/\*OpenGroup:*\s+\**$section\/*/", $line)){
75                 $fsection= true;
76                                 $ret .=$line; 
77                 continue;
78             }
80                         /* Change model name .. */
81                         if ((preg_match("/^\*".$attribute.":*\s+/",$line)) && ($attribute == "ModelName")){
82                                 $line= "*$attribute: \"$value\"\n";
83                                 $done =true;
84                         }
86                         if (($fsection) && ($section != "NO_SECTION")){
87                                 if (preg_match("/^\*CloseGroup:*\s+\**$section\/*/", $line)){
88                                         $fsection= false;
89                                         $ret .=$line; 
90                                         continue;
91                                 }
94                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
95                                         $fattribute= true;
96                                         $ret .= $line; 
97                                         continue;
98                                 }
100                                 if ($fattribute){
101                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
102                                                 $fattribute= false;
103                                                 $ret .= $line; 
104                                                 continue;
105                                         }
107                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
108                                                 $line= "*Default$attribute: $value\n";
109                                                 $done =true;
110                                         }
111                                 }
112                         }else{
113                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
114                                         $fattribute= true;
115                                         $ret .= $line; 
116                                         continue;
117                                 }
119                                 if ($fattribute){
120                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
121                                                 $fattribute= false;
122                                                 $ret .= $line; 
123                                                 continue;
124                                         }
126                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
127                                                 $line= "*Default$attribute: $value\n";
128                                                 $done =true;
129                                         }
130                                 }
131                         }
132                         $ret .=$line; 
133                 }
135                 gzwrite($wp,$ret);
136                 
137                 gzclose($wp);
138                 gzclose($rp);
140                 copy("$file.tmp", "$file");
141                 unlink("$file.tmp");
142         }
145         function saveProperties($ppdFile, $properties)
146         {
147                 if(!is_readable($ppdFile)){
148                         msg_dialog::display(_("PPD manager error"), sprintf(_("Specified PPD file '%s' cannot be opened for reading."),$ppdFile), ERROR_DIALOG);
149                 }elseif(!is_writeable(preg_replace("#(^.*/).*$#","\\1",$ppdFile.".tmp"))){
150                         msg_dialog::display(_("PPD manager error"), sprintf(_("The temporary file '%s' cannot be opened for writing."),$ppdFile.".tmp"), ERROR_DIALOG);
151                 }else{
152                         if(is_array($properties)){
153                                 foreach ($properties as $name => $section){
154                                         foreach ($section as $attribute => $value){
155                                                 if (is_array($value)){
156                                                         $this->updateAttribute($ppdFile, $name, $attribute, $value['_default']);
157                                                 }
158                                         }
159                                 }
160                         }
161                 }
162         }
164         function loadProperties($ppdFile)
165   {
166     if(!(filesize($ppdFile))) {
167       trigger_error(_('Parsing PPD file failed - File has 0 bytes'));
168       return;
169     }
171                 $group= "";
172                 $option= "";
173                 $properties= array();
175                 $fh= gzopen ($ppdFile, 'r');
176                 while (!gzeof($fh)) {
178                         /* Read line */
179                         $line= gzgets($fh, 256);
180                         if (strlen($line) >= 256){
181                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
182                         }
184                         /* Trigger for option groups */
185                         if (preg_match('/^\*OpenGroup:/i', $line)){
187                                 /* Sanity checks */
188                                 if ($group != ""){
189                                         trigger_error(_('Nested groups are not supported!'), E_USER_WARNING);
190                                         continue;
191                                 }
192                                 if (in_array($group, $properties)){
193                                         trigger_error(_('Group name not unique!'), E_USER_WARNING);
194                                         continue;
195                                 }
197                                 // TODO: Symbol values are not supported yet!
198                                 if (preg_match('/\^/', $line)){
199                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
200                                 }
201                                 $complete= preg_replace('@^\*OpenGroup:\s+(.*)$@i', '\1', $line);
202                                 $complete= trim($complete, '"');
203                                 if (preg_match('@/@', $complete)){
204                                         $group= trim(preg_replace('@^\*OpenGroup:\s+"?([^/]+)/.*$@i', '\1', $line));
205                                         $name = preg_replace('@^\*OpenGroup:\s+"?[^/]+/([^/]+).*$@i', '\1', $line);
206                                 } else {
207                                         $group= $complete;
208                                         $name = $complete;
209                                 }
210                                 $properties[$group]= array('_name' => $name);
211                                 continue;
212                         }
213                         if (preg_match("/^\*CloseGroup:\s+\"?$group\"?/i", $line)){
214                                 $group= "";
215                                 continue;
216                         }
218                         /* Trigger for options */
219                         if (preg_match('/^\*OpenUI\s+/i', $line)){
221                                 /* Sanity check */
222                                 if ($option != ""){
223                                         trigger_error(_('Nested options are not supported!'), E_USER_WARNING);
224                                         continue;
225                                 }
227                                 // TODO: Symbol values are not supported yet!
228                                 if (preg_match('/\^/', $line)){
229                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
230                                 }
231                                 $complete= preg_replace('@^\*OpenUI\s+(.*)$@i', '\1', $line);
232                                 $complete= trim($complete, '"');
233                                 if (preg_match('@/@', $complete)){
234                                         $option= trim(preg_replace('@^\*OpenUI\s+([^/]+)/.*$@i', '\1', $line));
235                                         $name = trim(preg_replace('@^\*OpenUI\s+[^/]+/([^/]+).*$@i', '\1', $line));
236                                 } else {
237                                         $option= trim($complete);
238                                         $name  = trim($complete);
239                                 }
241                                 /* Extract option type */
242                                 $type= trim(preg_replace('/^[^:]+:\s+/', '', $line));
243                                 $name= preg_replace('/:.*$/', '', $name);
244                                 $option= preg_replace('/:.*$/', '', $option);
246                                 // TODO: PickMany is not supported yet!
247                                 if (preg_match('/PickMany/i', $type)){
248                                         trigger_error(_('PickMany is not supported yet!'), E_USER_WARNING);
249                                 }
250                                 if(empty($group)){
251                                         $properties["NO_SECTION"][$option]= array('_name' => $name, '_type' => $type);
252                                 }else{
253                                         $properties[$group][$option]= array('_name' => $name, '_type' => $type);
254                                 }
255                                 continue;
256                         }
257                         /* Show interest for option parsing */
258                         if ($option != ""){
260                                 $eoption= preg_replace('@\*@', '', $option);
262                                 /* Close section? */
263                                 if (preg_match("@^\*CloseUI:\s+\*$eoption@i", $line)){
264                                         $option= "";
265                                         continue;
266                                 }
268                                 /* Default value? */
269                                 if (preg_match("@^\*Default$eoption:@", $line)){
270                                         $c= preg_replace("@^\*Default$eoption:\s+@", "", $line);
271                                         if(empty($group)){
272                                                 $properties["NO_SECTION"][$option]['_default']= trim(trim($c, '"'));
273                                         }else{
274                                                 $properties[$group][$option]['_default']= trim(trim($c, '"'));
275                                         }
276                                         continue;
277                                 }
279                                 /* Possible value? */
280                                 if (preg_match("@^\*$eoption\s+@", $line)){
281 #*PageSize Letter/US Letter: "<>setpagedevice"
282                                         $c= preg_replace("@^\*$eoption\s+([^/]+).*$@", "$1", $line);
283                                         $d= preg_replace("@^\*$eoption\s+[^/]+/([^:]+).*$@", "$1", $line);
284                                         if(empty($group)){
285                                                 $properties["NO_SECTION"][$option][trim($c)]= trim($d);
286                                         }else{
287                                                 $properties[$group][$option][trim($c)]= trim($d);
288                                         }
289                                         continue;
290                                 }
291                         }
292                 }
293                 gzclose ($fh);
294                 return ($properties);
295         }
297         function loadDescription($ppdFile)
298   {
299     if(!(filesize($ppdFile))) {
300       trigger_error(_('Parsing PPD file failed - File has 0 bytes'));
301       return;
302     }
304                 $ppdDesc = array();
305                                 
306                 /* Only parse complete PPD file again, if it was changed */
307                 $modified = filemtime($ppdFile);
308                 if(isset($this->cachedList[$ppdFile]) && isset($this->timestamps[$ppdFile]) && $modified == $this->timestamps[$ppdFile]){
309                         return($this->cachedList[$ppdFile]);
310                 }
312                 /* Remember modified timestamp, to speed up next request */
313                 $this->timestamps[$ppdFile] = filemtime($ppdFile);
315                 $fh= gzopen ($ppdFile, 'r');
316                 while ((!gzeof($fh))&&($fh)) {
318                         /* Read line */
319                         $line= gzgets($fh, 256);
320                         if (strlen($line) >= 256){
321                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
322                         }
324                         /* Extract interesting informations */
325                         if (preg_match('/^\*Manufacturer:/i', $line)){
326                                 $ppdDesc['manufacturer'] = trim(preg_replace('/^\*Manufacturer:\s+"?([^"]+)"?.*$/i', '\1', $line));
327                         }
328                         if (preg_match('/^\*ModelName:/i', $line)){
329                                 $ppdDesc['model'] = trim(preg_replace('/^\*ModelName:\s+"?([^"]+)"?.*$/i', '\1', $line));
330                         }
332                         /* Got everything we need? Skip rest for speed reasons... */
333                         if (isset($ppdDesc['manufacturer'])  && isset($ppdDesc['model'])){
334                                 break;
335                         }
336                 }
337                 gzclose ($fh);
339                 /* If model contains manufacturer strip it */
340                 $ppdDesc['model'] = str_replace($ppdDesc['manufacturer']." ", '', $ppdDesc['model']);
341                 
342                 /* Write out a notice that the PPD file seems to be broken if we can't
343                    extract any usefull informations */
344                 if ($ppdDesc['manufacturer'] == '' || $ppdDesc['model'] == ''){
345                         trigger_error(sprintf(_('Parsing PPD file %s failed - no information found.'), $ppdFile), E_USER_WARNING);
346                 }
348                 $ppdDesc['name'] = $ppdDesc['manufacturer'] . " - " . $ppdDesc['model'];
349                 
350                 return $ppdDesc;
351         }
354         function getPrinterList($reload= false)
355         {
356                 /* Load list of PPD files */
357                 if (count($this->cachedList) == 0 || $reload){
358                         $list= $this->findPPD($this->path);
360                         /* Load descriptive informations to build final printer list */
361                         $new = array();
362                         foreach ($list as $ppdFile){
363                                 $new[$ppdFile] = $this->loadDescription($ppdFile); 
364                         }
365                         $this->cachedList= $new ;
367                 }
369                 return ($this->cachedList);
370         }
373 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
374 ?>