Code

update
[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                 
62                 while (!feof($rp)){
63                         $lines[]= fgets($rp, 1024);
64                 }
66                 $ret = "";
67                 $done =false;
68                 foreach($lines as $nr => $line){
69         
70                         if (preg_match("/\*OpenGroup:*\s+\**$section\/*/", $line)){
71                 $fsection= true;
72                                 $ret .=$line; 
73                 continue;
74             }
76                         if (($fsection) && ($section != "NO_SECTION")){
77                                 if (preg_match("/^\*CloseGroup:*\s+\**$section\/*/", $line)){
78                                         $fsection= false;
79                                         $ret .=$line; 
80                                         continue;
81                                 }
84                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
85                                         $fattribute= true;
86                                         $ret .= $line; 
87                                         continue;
88                                 }
90                                 if ($fattribute){
91                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
92                                                 $fattribute= false;
93                                                 $ret .= $line; 
94                                                 continue;
95                                         }
97                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
98                                                 $line= "*Default$attribute: $value\n";
99                                                 $done =true;
100                                         }
101                                 }
102                         }else{
103                                 if (preg_match("/^\*OpenUI:*\s+\**$attribute\/*/", $line)){
104                                         $fattribute= true;
105                                         $ret .= $line; 
106                                         continue;
107                                 }
109                                 if ($fattribute){
110                                         if (preg_match("/^\*CloseUI:*\s+\**$attribute\/*/", $line)){
111                                                 $fattribute= false;
112                                                 $ret .= $line; 
113                                                 continue;
114                                         }
116                                         if (preg_match("/^\*Default$attribute:*\s+/", $line)){
117                                                 $line= "*Default$attribute: $value\n";
118                                                 $done =true;
119                                         }
120                                 }
121                         }
122                         $ret .=$line; 
123                 }
125                 fwrite($wp,$ret);
126                 
127                 fclose($wp);
128                 fclose($rp);
130                 copy("$file.tmp", "$file");
131                 unlink("$file.tmp");
132         }
135         function saveProperties($ppdFile, $properties)
136         {
137                 if(!is_readable($ppdFile)){
138                         print_red(sprintf(_("Specified ppd file '%s' can't be opened for reading."),$ppdFile));
139                 }elseif(!is_writeable($ppdFile.".tmp")){
140                         print_red(sprintf(_("The required tmp file file '%s' can't be opened for writing."),$ppdFile.".tmp"));
141                 }else{
142                         foreach ($properties as $name => $section){
143                                 foreach ($section as $attribute => $value){
144                                         if (is_array($value)){
145                                                 $this->updateAttribute($ppdFile, $name, $attribute, $value['_default']);
146                                         }
147                                 }
148                         }
149                 }
150         }
152         function loadProperties($ppdFile)
153         {
154                 $group= "";
155                 $option= "";
156                 $properties= array();
158                 $fh= fopen ($ppdFile, 'r');
159                 while (!feof($fh)) {
161                         /* Read line */
162                         $line= fgets($fh, 256);
163                         if (strlen($line) >= 256){
164                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
165                         }
167                         /* Trigger for option groups */
168                         if (preg_match('/^\*OpenGroup:/i', $line)){
170                                 /* Sanity checks */
171                                 if ($group != ""){
172                                         trigger_error(_('Nested groups are not supported!'), E_USER_WARNING);
173                                         continue;
174                                 }
175                                 if (in_array($group, $properties)){
176                                         trigger_error(_('Group name not unique!'), E_USER_WARNING);
177                                         continue;
178                                 }
180                                 // TODO: Symbol values are not supported yet!
181                                 if (preg_match('/\^/', $line)){
182                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
183                                 }
184                                 $complete= preg_replace('@^\*OpenGroup:\s+(.*)$@i', '\1', $line);
185                                 $complete= trim($complete, '"');
186                                 if (preg_match('@/@', $complete)){
187                                         $group= trim(preg_replace('@^\*OpenGroup:\s+"?([^/]+)/.*$@i', '\1', $line));
188                                         $name = preg_replace('@^\*OpenGroup:\s+"?[^/]+/([^/]+).*$@i', '\1', $line);
189                                 } else {
190                                         $group= $complete;
191                                         $name = $complete;
192                                 }
193                                 $properties[$group]= array('_name' => $name);
194                                 continue;
195                         }
196                         if (preg_match("/^\*CloseGroup:\s+\"?$group\"?/i", $line)){
197                                 $group= "";
198                                 continue;
199                         }
201                         /* Trigger for options */
202                         if (preg_match('/^\*OpenUI\s+/i', $line)){
204                                 /* Sanity check */
205                                 if ($option != ""){
206                                         trigger_error(_('Nested options are not supported!'), E_USER_WARNING);
207                                         continue;
208                                 }
210                                 // TODO: Symbol values are not supported yet!
211                                 if (preg_match('/\^/', $line)){
212                                         trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
213                                 }
214                                 $complete= preg_replace('@^\*OpenUI\s+(.*)$@i', '\1', $line);
215                                 $complete= trim($complete, '"');
216                                 if (preg_match('@/@', $complete)){
217                                         $option= trim(preg_replace('@^\*OpenUI\s+([^/]+)/.*$@i', '\1', $line));
218                                         $name = trim(preg_replace('@^\*OpenUI\s+[^/]+/([^/]+).*$@i', '\1', $line));
219                                 } else {
220                                         $option= trim($complete);
221                                         $name  = trim($complete);
222                                 }
224                                 /* Extract option type */
225                                 $type= trim(preg_replace('/^[^:]+:\s+/', '', $line));
226                                 $name= preg_replace('/:.*$/', '', $name);
227                                 $option= preg_replace('/:.*$/', '', $option);
229                                 // TODO: PickMany is not supported yet!
230                                 if (preg_match('/PickMany/i', $type)){
231                                         trigger_error(_('PickMany is not supported yet!'), E_USER_WARNING);
232                                 }
233                                 if(empty($group)){
234                                         $properties["NO_SECTION"][$option]= array('_name' => $name, '_type' => $type);
235                                 }else{
236                                         $properties[$group][$option]= array('_name' => $name, '_type' => $type);
237                                 }
238                                 continue;
239                         }
240                         /* Show interest for option parsing */
241                         if ($option != ""){
243                                 $eoption= preg_replace('@\*@', '', $option);
245                                 /* Close section? */
246                                 if (preg_match("@^\*CloseUI:\s+\*$eoption@i", $line)){
247                                         $option= "";
248                                         continue;
249                                 }
251                                 /* Default value? */
252                                 if (preg_match("@^\*Default$eoption:@", $line)){
253                                         $c= preg_replace("@^\*Default$eoption:\s+@", "", $line);
254                                         if(empty($group)){
255                                                 $properties["NO_SECTION"][$option]['_default']= trim(trim($c, '"'));
256                                         }else{
257                                                 $properties[$group][$option]['_default']= trim(trim($c, '"'));
258                                         }
259                                         continue;
260                                 }
262                                 /* Possible value? */
263                                 if (preg_match("@^\*$eoption\s+@", $line)){
264 #*PageSize Letter/US Letter: "<>setpagedevice"
265                                         $c= preg_replace("@^\*$eoption\s+([^/]+).*$@", "$1", $line);
266                                         $d= preg_replace("@^\*$eoption\s+[^/]+/([^:]+).*$@", "$1", $line);
267                                         if(empty($group)){
268                                                 $properties["NO_SECTION"][$option][trim($c)]= trim($d);
269                                         }else{
270                                                 $properties[$group][$option][trim($c)]= trim($d);
271                                         }
272                                         continue;
273                                 }
274                         }
275                 }
276                 fclose ($fh);
277                 return ($properties);
278         }
280         function loadDescription($ppdFile)
281         {
282                 $model= "";
283                 $manufacturer= "";
285                 $fh= fopen ($ppdFile, 'r');
286                 while ((!feof($fh))&&($fh)) {
288                         /* Read line */
289                         $line= fgets($fh, 256);
290                         if (strlen($line) >= 256){
291                                 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
292                         }
294                         /* Extract interesting informations */
295                         if (preg_match('/^\*Manufacturer:/i', $line)){
296                                 $manufacturer= preg_replace('/^\*Manufacturer:\s+"?([^"]+)"?.*$/i', '\1', $line);
297                         }
298                         if (preg_match('/^\*ModelName:/i', $line)){
299                                 $model= preg_replace('/^\*ModelName:\s+"?([^"]+)"?.*$/i', '\1', $line);
300                         }
302                         /* Got everything we need? Skip rest for speed reasons... */
303                         if ($model != '' && $manufacturer != ''){
304                                 break;
305                         }
306                 }
307                 fclose ($fh);
309                 /* Write out a notice that the PPD file seems to be broken if we can't
310                    extract any usefull informations */
311                 if ($model == '' || $manufacturer == ''){
312                         trigger_error(sprintf(_('Parsing PPD file %s failed - no information found.'), $ppdFile), E_USER_WARNING);
313                 }
315                 return ($manufacturer.' - '.$model);
316         }
319         function getPrinterList($reload= false)
320         {
321                 /* Load list of PPD files */
322                 if (count($this->cachedList) == 0 || $reload){
323                         $list= $this->findPPD($this->path);
325                         /* Load descriptive informations to build final printer list */
326                         $this->cachedList= array();
327                         foreach ($list as $ppdFile){
328                                 $this->cachedList[$ppdFile]= $this->loadDescription($ppdFile);
329                         }
331                 }
333                 return ($this->cachedList);
334         }
338 ?>