Code

Fixed parsing/saving of ppd files
[gosa.git] / include / class_ppdManager.inc
1 <?php
3 class ppdManager
4 {
5         var $path= "";
6         var $cachedList= array();
8         function ppdManager($path)
9         {
10                 if(is_dir($path)){
11                 $this->path= $path;
12                 }else{
13                         print_red(sprintf(_("PPD manager : The specified path '%s' doesn't exists."),$path));
14                         return (false);
15                 }
16         }
19         function findPPD($path)
20         {
21                 $list= array();
22                 $currentDir= getcwd();
24                 $dh = opendir($path);
25                 while(false !== ($file = readdir($dh))){
27                         /* Skip well known files */
28                         if( $file == '.' || $file == '..'){
29                                 continue;
30                         }
32                         /* Recurse through all "common" directories */
33                         if(is_dir($path.'/'.$file)){
34                                 $list= array_merge($list, $this->findPPD($path.'/'.$file));
35                                 continue;
36                         }
38                         /* Check for PPD extension */
39                         if (preg_match('/\.ppd$/i', $file)){
40                                 $list[]= $path.'/'.$file;
41                         }
42                 }
44                 closedir($dh);
45                 chdir ($currentDir);
46                 return ($list);
47         }
50         function updateAttribute($file, $section, $attribute, $value)
51         {
52                 $fsection= false;
53                 $fattribute= false;
54                 $section= preg_replace('/^\*/', '', $section);
55                 $attribute= preg_replace('/^\*/', '', $attribute);
57                 $rp= fopen($file, "r");
58                 $wp= fopen("$file.tmp", "w");
60                 while (!feof($rp)){
61                         $lines[]= fgets($rp, 1024);
62                 }
64                 $ret = "";
65                 $done =false;
66                 foreach($lines as $nr => $line){
67         
68                         if (preg_match("/\*OpenGroup:*\s+\**$section\/*/", $line)){
69                 $fsection= true;
70                                 $ret .=$line; 
71                 continue;
72             }
74                         if (($fsection) && ($section != "NO_SECTION")){
75                                 if (preg_match("/^\*CloseGroup:*\s+\**$section\/*/", $line)){
76                                         $fsection= false;
77                                         $ret .=$line; 
78                                         continue;
79                                 }
82                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
83                                         $fattribute= true;
84                                         $ret .= $line; 
85                                         continue;
86                                 }
88                                 if ($fattribute){
89                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
90                                                 $fattribute= false;
91                                                 $ret .= $line; 
92                                                 continue;
93                                         }
95                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
96                                                 $line= "*Default$attribute: $value\n";
97                                                 $done =true;
98                                         }
99                                 }
100                         }else{
101                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
102                                         $fattribute= true;
103                                         $ret .= $line; 
104                                         continue;
105                                 }
107                                 if ($fattribute){
108                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
109                                                 $fattribute= false;
110                                                 $ret .= $line; 
111                                                 continue;
112                                         }
114                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
115                                                 $line= "*Default$attribute: $value\n";
116                                                 $done =true;
117                                         }
118                                 }
119                         }
120                         $ret .=$line; 
121                 }
123                 fwrite($wp,$ret);
124                 
125                 fclose($wp);
126                 fclose($rp);
128                 copy("$file.tmp", "$file");
129                 unlink("$file.tmp");
130         }
133         function saveProperties($ppdFile, $properties)
134         {
135                 foreach ($properties as $name => $section){
136                         foreach ($section as $attribute => $value){
137                                 if (is_array($value)){
138                                         $this->updateAttribute($ppdFile, $name, $attribute, $value['_default']);
139                                 }
140                         }
141                 }
142         }
144         function loadProperties($ppdFile)
145         {
146                 $group= "";
147                 $option= "";
148                 $properties= array();
150                 $fh= fopen ($ppdFile, 'r');
151                 while (!feof($fh)) {
153                         /* Read line */
154                         $line= fgets($fh, 256);
155                         if (strlen($line) >= 256){
156                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
157                         }
159                         /* Trigger for option groups */
160                         if (preg_match('/^\*OpenGroup:/i', $line)){
162                                 /* Sanity checks */
163                                 if ($group != ""){
164                                         trigger_error(_('Nested groups are not supported!'), E_USER_WARNING);
165                                         continue;
166                                 }
167                                 if (in_array($group, $properties)){
168                                         trigger_error(_('Group name not unique!'), E_USER_WARNING);
169                                         continue;
170                                 }
172                                 // TODO: Symbol values are not supported yet!
173                                 if (preg_match('/\^/', $line)){
174                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
175                                 }
176                                 $complete= preg_replace('@^\*OpenGroup:\s+(.*)$@i', '\1', $line);
177                                 $complete= trim($complete, '"');
178                                 if (preg_match('@/@', $complete)){
179                                         $group= trim(preg_replace('@^\*OpenGroup:\s+"?([^/]+)/.*$@i', '\1', $line));
180                                         $name = preg_replace('@^\*OpenGroup:\s+"?[^/]+/([^/]+).*$@i', '\1', $line);
181                                 } else {
182                                         $group= $complete;
183                                         $name = $complete;
184                                 }
185                                 $properties[$group]= array('_name' => $name);
186                                 continue;
187                         }
188                         if (preg_match("/^\*CloseGroup:\s+\"?$group\"?/i", $line)){
189                                 $group= "";
190                                 continue;
191                         }
193                         /* Trigger for options */
194                         if (preg_match('/^\*OpenUI\s+/i', $line)){
196                                 /* Sanity check */
197                                 if ($option != ""){
198                                         trigger_error(_('Nested options are not supported!'), E_USER_WARNING);
199                                         continue;
200                                 }
202                                 // TODO: Symbol values are not supported yet!
203                                 if (preg_match('/\^/', $line)){
204                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
205                                 }
206                                 $complete= preg_replace('@^\*OpenUI\s+(.*)$@i', '\1', $line);
207                                 $complete= trim($complete, '"');
208                                 if (preg_match('@/@', $complete)){
209                                         $option= trim(preg_replace('@^\*OpenUI\s+([^/]+)/.*$@i', '\1', $line));
210                                         $name = trim(preg_replace('@^\*OpenUI\s+[^/]+/([^/]+).*$@i', '\1', $line));
211                                 } else {
212                                         $option= trim($complete);
213                                         $name  = trim($complete);
214                                 }
216                                 /* Extract option type */
217                                 $type= trim(preg_replace('/^[^:]+:\s+/', '', $line));
218                                 $name= preg_replace('/:.*$/', '', $name);
219                                 $option= preg_replace('/:.*$/', '', $option);
221                                 // TODO: PickMany is not supported yet!
222                                 if (preg_match('/PickMany/i', $type)){
223                                         trigger_error(_('PickMany is not supported yet!'), E_USER_WARNING);
224                                 }
225                                 if(empty($group)){
226                                         $properties["NO_SECTION"][$option]= array('_name' => $name, '_type' => $type);
227                                 }else{
228                                         $properties[$group][$option]= array('_name' => $name, '_type' => $type);
229                                 }
230                                 continue;
231                         }
232                         /* Show interest for option parsing */
233                         if ($option != ""){
235                                 $eoption= preg_replace('@\*@', '', $option);
237                                 /* Close section? */
238                                 if (preg_match("@^\*CloseUI:\s+\*$eoption@i", $line)){
239                                         $option= "";
240                                         continue;
241                                 }
243                                 /* Default value? */
244                                 if (preg_match("@^\*Default$eoption:@", $line)){
245                                         $c= preg_replace("@^\*Default$eoption:\s+@", "", $line);
246                                         if(empty($group)){
247                                                 $properties["NO_SECTION"][$option]['_default']= trim(trim($c, '"'));
248                                         }else{
249                                                 $properties[$group][$option]['_default']= trim(trim($c, '"'));
250                                         }
251                                         continue;
252                                 }
254                                 /* Possible value? */
255                                 if (preg_match("@^\*$eoption\s+@", $line)){
256 #*PageSize Letter/US Letter: "<>setpagedevice"
257                                         $c= preg_replace("@^\*$eoption\s+([^/]+).*$@", "$1", $line);
258                                         $d= preg_replace("@^\*$eoption\s+[^/]+/([^:]+).*$@", "$1", $line);
259                                         if(empty($group)){
260                                                 $properties["NO_SECTION"][$option][trim($c)]= trim($d);
261                                         }else{
262                                                 $properties[$group][$option][trim($c)]= trim($d);
263                                         }
264                                         continue;
265                                 }
266                         }
267                 }
268                 fclose ($fh);
269                 return ($properties);
270         }
272         function loadDescription($ppdFile)
273         {
274                 $model= "";
275                 $manufacturer= "";
277                 $fh= fopen ($ppdFile, 'r');
278                 while ((!feof($fh))&&($fh)) {
280                         /* Read line */
281                         $line= fgets($fh, 256);
282                         if (strlen($line) >= 256){
283                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
284                         }
286                         /* Extract interesting informations */
287                         if (preg_match('/^\*Manufacturer:/i', $line)){
288                                 $manufacturer= preg_replace('/^\*Manufacturer:\s+"?([^"]+)"?.*$/i', '\1', $line);
289                         }
290                         if (preg_match('/^\*ModelName:/i', $line)){
291                                 $model= preg_replace('/^\*ModelName:\s+"?([^"]+)"?.*$/i', '\1', $line);
292                         }
294                         /* Got everything we need? Skip rest for speed reasons... */
295                         if ($model != '' && $manufacturer != ''){
296                                 break;
297                         }
298                 }
299                 fclose ($fh);
301                 /* Write out a notice that the PPD file seems to be broken if we can't
302                    extract any usefull informations */
303                 if ($model == '' || $manufacturer == ''){
304                         trigger_error(sprintf(_('Parsing PPD file %s failed - no information found.'), $ppdFile), E_USER_WARNING);
305                 }
307                 return ($manufacturer.' - '.$model);
308         }
311         function getPrinterList($reload= false)
312         {
313                 /* Load list of PPD files */
314                 if (count($this->cachedList) == 0 || $reload){
315                         $list= $this->findPPD($this->path);
317                         /* Load descriptive informations to build final printer list */
318                         $this->cachedList= array();
319                         foreach ($list as $ppdFile){
320                                 $this->cachedList[$ppdFile]= $this->loadDescription($ppdFile);
321                         }
323                 }
325                 return ($this->cachedList);
326         }
330 ?>