1 <?php
3 class ppdManager
4 {
5 var $path= "";
6 var $cachedList= array();
8 function ppdManager($path)
9 {
10 $this->path= $path;
11 echo "Path set to $path<br>";
12 }
15 function findPPD($path)
16 {
17 $list= array();
18 $currentDir= getcwd();
20 $dh = opendir($path);
21 while(false !== ($file = readdir($dh))){
23 /* Skip well known files */
24 if( $file == '.' || $file == '..'){
25 continue;
26 }
28 /* Recurse through all "common" directories */
29 if(is_dir($path.'/'.$file)){
30 $list= array_merge($list, $this->findPPD($path.'/'.$file));
31 continue;
32 }
34 /* Check for PPD extension */
35 if (preg_match('/\.ppd$/i', $file)){
36 $list[]= $path.'/'.$file;
37 }
38 }
40 closedir($dh);
41 chdir ($currentDir);
42 return ($list);
43 }
46 function saveProperties($ppdFile, $properties)
47 {
48 echo "<pre>";
49 print_r ($properties);
50 echo "</pre>";
51 }
54 function loadProperties($ppdFile)
55 {
56 $group= "";
57 $option= "";
58 $properties= array();
60 $fh= fopen ($ppdFile, 'r');
61 while (!feof($fh)) {
63 /* Read line */
64 $line= fgets($fh, 256);
65 if (strlen($line) >= 256){
66 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
67 }
69 /* Trigger for option groups */
70 if (preg_match('/^\*OpenGroup:/i', $line)){
72 /* Sanity checks */
73 if ($group != ""){
74 trigger_error(_('Nested groups are not supported!'), E_USER_WARNING);
75 continue;
76 }
77 if (in_array($group, $properties)){
78 trigger_error(_('Group name not unique!'), E_USER_WARNING);
79 continue;
80 }
82 // TODO: Symbol values are not supported yet!
83 if (preg_match('/\^/', $line)){
84 trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
85 }
86 $complete= preg_replace('@^\*OpenGroup:\s+(.*)$@i', '\1', $line);
87 $complete= trim($complete, '"');
88 if (preg_match('@/@', $complete)){
89 $group= trim(preg_replace('@^\*OpenGroup:\s+"?([^/]+)/.*$@i', '\1', $line));
90 $name = preg_replace('@^\*OpenGroup:\s+"?[^/]+/([^/]+).*$@i', '\1', $line);
91 } else {
92 $group= $complete;
93 $name = $complete;
94 }
95 $properties[$group]= array('_name' => $name);
96 continue;
97 }
98 if (preg_match("/^\*CloseGroup:\s+\"?$group\"?/i", $line)){
99 $group= "";
100 continue;
101 }
103 /* Trigger for options */
104 if (preg_match('/^\*OpenUI\s+/i', $line)){
106 /* Sanity check */
107 if ($option != ""){
108 trigger_error(_('Nested options are not supported!'), E_USER_WARNING);
109 continue;
110 }
112 // TODO: Symbol values are not supported yet!
113 if (preg_match('/\^/', $line)){
114 trigger_error(_('Symbol values are not supported yet!'), E_USER_WARNING);
115 }
116 $complete= preg_replace('@^\*OpenUI\s+(.*)$@i', '\1', $line);
117 $complete= trim($complete, '"');
118 if (preg_match('@/@', $complete)){
119 $option= trim(preg_replace('@^\*OpenUI\s+([^/]+)/.*$@i', '\1', $line));
120 $name = trim(preg_replace('@^\*OpenUI\s+[^/]+/([^/]+).*$@i', '\1', $line));
121 } else {
122 $option= trim($complete);
123 $name = trim($complete);
124 }
126 /* Extract option type */
127 $type= trim(preg_replace('/^[^:]+:\s+/', '', $line));
128 $name= preg_replace('/:.*$/', '', $name);
129 $option= preg_replace('/:.*$/', '', $option);
131 // TODO: PickMany is not supported yet!
132 if (preg_match('/PickMany/i', $type)){
133 trigger_error(_('PickMany is not supported yet!'), E_USER_WARNING);
134 }
136 $properties[$group][$option]= array('_name' => $name, '_type' => $type);
137 continue;
138 }
139 /* Show interest for option parsing */
140 if ($option != ""){
142 $eoption= preg_replace('@\*@', '', $option);
144 /* Close section? */
145 if (preg_match("@^\*CloseUI:\s+\*$eoption@i", $line)){
146 $option= "";
147 continue;
148 }
150 /* Default value? */
151 if (preg_match("@^\*Default$eoption:@", $line)){
152 $c= preg_replace("@^\*Default$eoption:\s+@", "", $line);
153 $properties[$group][$option]['_default']= trim(trim($c, '"'));
154 continue;
155 }
157 /* Possible value? */
158 if (preg_match("@^\*$eoption\s+@", $line)){
159 #*PageSize Letter/US Letter: "<>setpagedevice"
160 $c= preg_replace("@^\*$eoption\s+([^/]+).*$@", "$1", $line);
161 $d= preg_replace("@^\*$eoption\s+[^/]+/([^:]+).*$@", "$1", $line);
162 $properties[$group][$option][trim($c)]= trim($d);
163 continue;
164 }
165 }
167 }
168 fclose ($fh);
170 return ($properties);
171 }
173 function loadDescription($ppdFile)
174 {
175 $model= "";
176 $manufacturer= "";
178 $fh= fopen ($ppdFile, 'r');
179 while (!feof($fh)) {
181 /* Read line */
182 $line= fgets($fh, 256);
183 if (strlen($line) >= 256){
184 trigger_error(_('Parsing PPD file %s failed - line too long. Trailing characters have been ignored'), E_USER_WARNING);
185 }
187 /* Extract interesting informations */
188 if (preg_match('/^\*Manufacturer:/i', $line)){
189 $manufacturer= preg_replace('/^\*Manufacturer:\s+"?([^"]+)"?.*$/i', '\1', $line);
190 }
191 if (preg_match('/^\*ModelName:/i', $line)){
192 $model= preg_replace('/^\*ModelName:\s+"?([^"]+)"?.*$/i', '\1', $line);
193 }
195 /* Got everything we need? Skip rest for speed reasons... */
196 if ($model != '' && $manufacturer != ''){
197 break;
198 }
199 }
200 fclose ($fh);
202 /* Write out a notice that the PPD file seems to be broken if we can't
203 extract any usefull informations */
204 if ($model == '' || $manufacturer == ''){
205 trigger_error(sprintf(_('Parsing PPD file %s failed - no information found.'), $ppdFile), E_USER_WARNING);
206 }
208 return ($manufacturer.' - '.$model);
209 }
212 function getPrinterList($reload= false)
213 {
214 /* Load list of PPD files */
215 if (count($this->cachedList) == 0 || $reload){
216 $list= $this->findPPD($this->path);
218 /* Load descriptive informations to build final printer list */
219 $this->cachedList= array();
220 foreach ($list as $ppdFile){
221 $this->cachedList[$ppdFile]= $this->loadDescription($ppdFile);
222 }
224 }
226 return ($this->cachedList);
227 }
229 }
231 ?>