1 <?php
3 class printerPPDDialog extends plugin
4 {
5 /* CLI vars */
6 var $cli_summary = "Manage server basic objects";
7 var $cli_description = "Some longer text\nfor help";
8 var $cli_parameters = array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10 /* attribute list for save action */
11 var $ignore_account = TRUE;
12 var $attributes = array("cn");
13 var $objectclasses = array("whatever");
15 /* PPD Handling */
16 var $selectedPPD = false; // e.g. /vendor/device.ppd
17 var $ppdManager = false; // new ppdManager;
18 var $ppdConfig = false; // $this->ppdManager->loadProperties($this->selectedPPD['link']);
19 var $ppdList = array(); // Contains all Printer models
20 var $ppdListHeader = array(); // Contains all printer vendors
22 /* Paths */
23 var $pathToPPD = ""; // Base path, defined in gosa.conf e.g. "/var/spool/ppd/"
24 var $pathToModified = "modified/"; // used to store the modified ppds
26 /* Object Info */
27 var $cn = "" ; // Used to tag the ppds modified by the printer object,
28 var $dialog = NULL; // Contains sub dialogs
30 function printerPPDDialog ($config, $dn= NULL,$ppdfile=NULL )
31 {
32 plugin::plugin ($config, $dn);
33 $this->depselect = $this->config->current['BASE'];
35 /* Get PPD path and remove double //, and add trailing / */
36 if(isset($_SESSION['config']->data['MAIN']['PPD_PATH'])){
37 $this->pathToPPD = $_SESSION['config']->data['MAIN']['PPD_PATH'];
38 $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
39 if(!preg_match("/\/$/",$this->pathToPPD)){
40 $this->pathToPPD = $this->pathToPPD."/";
41 }
42 }else{
43 $this->pathToPPD = "";
44 }
46 /* It seams that we have an existing PPD path, so go on */
47 if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){
49 /* Load all available PPD files and sort them into an array */
50 require_once ("class_ppdManager.inc");
51 $this->ppdManager= new ppdManager($this->pathToPPD);
52 $tmp = $this->ppdManager->getPrinterList();
54 /* Sort all available files, and create header (Vendor index) */
55 foreach($tmp as $file=>$ppd){
56 $tmp2 = split("\n",$ppd);
57 if(!isset($this->ppdListHeader[$tmp2[0]])){
58 $this->ppdListHeader[$tmp2[0]]=0;
59 }
60 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
61 $tmp3['link'] =preg_replace("/".str_replace("/","\/",$this->pathToPPD)."/i","",$file);
62 $tmp3['ppd'] =$ppd;
63 $this->ppdListHeader[$tmp2[0]]++;
64 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
65 }
67 /* The user has already a valid PPD assigned
68 * Get some informations about this PPD
69 * and set it as selected.
70 * The ppdpath ['link'] should be relative from .../ppd/modified/
71 * e.g. "/Compaq/Compaq-J1200.ppd" */
72 if(($ppdfile!= NULL)&&(strlen($ppdfile)>0)){
73 $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
74 if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
75 print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
76 }else{
77 $res = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
78 if($res){
79 $tmp = split("\n",$res);
80 $tmp3 = array();
81 $tmp3['name'] = trim(preg_replace("/^\-/","",trim($tmp[1])));
82 $tmp3['link'] = $ppdfile;
83 $tmp3['ppd'] = $res;
84 }
85 $this->selectedPPD = $tmp3;
86 }
87 }
88 }
89 }
93 function execute()
94 {
95 /* Call parent execute */
96 plugin::execute();
98 /* Fill templating stuff */
99 $display= "";
100 $smarty= get_smarty();
101 $smarty->assign("ppdString", _("Can't get ppd informations."));
102 $smarty->assign("showOptions", "");
104 /* Check these paths */
105 $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
107 /* If one of our required paths is not available, stop here and display some info */
108 foreach($paths as $path){
110 /* Check if path is write/readable*/
111 $is_r = @is_readable($path);
112 if((!is_dir($path))||(empty($path)) || (!$is_r)){
113 print_red(sprintf(_("The specified path '%s' which results from PPD_PATH in your gosa.conf is invalid,".
114 " can't read/write any ppd informations."),$path));
115 /* Print out template */
116 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
117 return($display);
118 }
119 }
121 /* Is there a new PPD file uploaded ? */
122 if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
123 $file = ($_FILES['NewPPDFile']);
124 if($file['size'] != 0 ){
125 if($name = $this->AddPPD($file['tmp_name'])){
126 $this->SelectPPD($name);
127 }
128 }else{
129 print_red(_("Please specify a valid ppd file."));
130 }
131 }
134 /* Open a dialog that allow us to select different PPDs
135 */
136 if(isset($_POST['SelectPPD'])){
137 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
138 }
140 /* The selection dialog fpr PPDs is canceled
141 */
142 if(isset($_POST['ClosePPDSelection'])){
143 unset($this->dialog);
144 $this->dialog=NULL;
145 }
147 /* A new PPDs was selected in the PPDs selection Dialog
148 * Perform a Check. If everything is fine, use the new PPD.
149 */
150 if(isset($_POST['SavePPDSelection'])){
151 if(!isset($_POST['PPDselection'])){
152 print_red(_("Please select a valid ppd."));
153 }else{
154 $this->SelectPPD($_POST['PPDselection']);
155 unset($this->dialog);
156 $this->dialog=NULL;
157 }
158 }
160 /* Div Selection */
161 if((isset($_GET['act']))&&($_GET['act']=="use")){
162 $this->SelectPPD(base64_decode($_GET['id']));
163 unset($this->dialog);
164 $this->dialog=NULL;
166 }
168 /* if a dialog is open, print the dialog instead of this class
169 */
170 if($this->dialog!=NULL){
171 $display = $this->dialog->execute();
172 return($display);
173 }
175 /* Give smarty the information it needs */
176 $smarty->assign("ppdString" ,$this->getPPDInformation());
177 $tmp= $this->generateProperties();
178 if ($tmp == ""){
179 $smarty->assign("showOptions", 0);
180 } else {
181 $smarty->assign("showOptions", 1);
182 $smarty->assign("properties",$this->generateProperties());
183 }
185 /* Print out template */
186 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
187 return($display);
188 }
191 /* Select PPD */
192 function SelectPPD($name)
193 {
194 /* Replace base path we don't need it here
195 The path we need looks like this : "/Vendor/ModellName.ppd";
196 thats all */
197 $name = preg_replace("#".$this->pathToPPD."#","",$name);
199 /* Intialise some base vars */
200 $AbsoluteSourceName = $this->pathToPPD.$name;
201 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
202 $Vendor = ""; // Vendor
203 $Name = ""; // Name
204 $Modell = ""; // Modell
205 $PrinterName = ""; // The new name of the printer
206 $PPDName = "";
208 /* Force reload of config dialog */
209 $this->ppdConfig = false;
210 $this->selectedPPD['link'] = false;
212 /* Get PPD informations and set vendor / modell / name */
213 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
214 print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));
215 return;
216 }
217 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
218 if($res){
219 $tmp = split("\n",$res);
220 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
221 $Vendor = trim($tmp[0]);
222 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
223 }
225 $PrinterName = $this->cn."-".$Name;
226 $PPDName = $Vendor."/".$PrinterName.".ppd";
228 /* Create the vendors path, if it doesn't exists already */
229 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
230 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
231 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
232 return(false);
233 }
234 }
236 /* Create destination file handle */
237 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
238 if(!$fp){
239 print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
240 return(false);
241 }
243 $str = file_get_contents($AbsoluteSourceName);
244 fputs($fp,$str);
245 @fclose($fp);
247 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
249 $tmp3['link'] =$PPDName;
250 $this->selectedPPD = $tmp3;
251 $this->getPrinterReload();
252 return($PPDName);
253 }
256 /* This function adds a new ppd file to the list of available ppds.
257 All required paths and files will be created
258 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
259 function AddPPD($_PathOnHdd)
260 {
261 /* Check if file exists && is readable */
262 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
263 print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
264 return(false);
265 }
267 /* Reload list to detect changes e.g. a file has been deleted */
268 $this->getPrinterReload();
270 /* Get Description from ppd, & parse out some informations */
271 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
272 if($res){
273 $tmp = split("\n",$res);
274 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
275 $vendor = trim($tmp[0]);
276 $model = trim(preg_replace("/".$vendor."/","",$name));
277 }
279 /* Check if parse was successfull */
280 if(empty($name) || empty($vendor)){
281 print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
282 return(false);
283 }
285 /* Prepare list of ppds */
286 if(!isset($this->ppdList[$vendor])){
287 $this->ppdList[$vendor] = array();
288 }
290 /* Check if this ppd already exists */
291 $found = false;
292 foreach($this->ppdList[$vendor] as $key => $val){
293 if(preg_match("/".$model.".*/i",$key)){
294 $found = true;
295 print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
296 return;
297 }
298 }
300 /* Create the vendors path, if it doesn't exists already */
301 if(!is_dir($this->pathToPPD.$vendor)){
302 if(!(@mkdir($this->pathToPPD.$vendor))){
303 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
304 return(false);
305 }
306 }
308 /* Create ppd file and fill in the source contents */
309 $ppdname = $vendor."/".$name.".ppd";
310 $filename = $this->pathToPPD.$ppdname;
311 $fp = fopen($filename,"w+");
312 $contents = file_get_contents($_PathOnHdd);
314 /* Check file handle & contents */
315 if(!$fp){
316 print_red(sprintf(_("Can't save file '%s'."),$filename));
317 return;
318 }
319 if(empty($contents)){
320 print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
321 return;
322 }
324 /* Fille file with data */
325 fputs($fp,$contents);
326 @fclose($fp);
328 /* Our job is done here */
329 return($ppdname);
330 }
333 /* This function reloads the list of available printers/vendors
334 $this->ppdListHeader
335 Compaq => 1
336 $this->ppdList
337 Compaq => Compaq IJ1200 => name => Compaq IJ1200
338 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
339 ppd => Compaq - Co
340 */
341 function getPrinterReload()
342 {
343 $tmp = $this->ppdManager->getPrinterList(true);
345 $this->ppdListHeader = $this->ppdList = array();
347 /* Sort all available files, and create header (Vendor index) */
348 foreach($tmp as $file=>$ppd){
350 if(preg_match("#".$this->pathToModified."#",$file)) continue;
352 $tmp2 = split("\n",$ppd);
353 if(!isset($this->ppdListHeader[$tmp2[0]])){
354 $this->ppdListHeader[$tmp2[0]]=0;
355 }
356 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
357 $tmp3['link'] =$file;
358 $tmp3['ppd'] =$ppd;
359 $this->ppdListHeader[$tmp2[0]]++;
360 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
361 }
362 }
365 /* Save all options posted from ppd dialog */
366 function save_object()
367 {
368 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
369 return;
370 }
372 foreach($this->ppdConfig as $cat => $obj){
373 foreach($obj as $attr => $attributes){
374 if(isset($_POST[base64_encode($attributes['_name'])])){
375 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
376 }
377 }
378 }
379 }
382 /* Save modified ppd */
383 function save_ppd(){
384 if($this->ppdManager){
385 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
386 }
387 }
389 /* Return selected ppd path, if none is selected then false */
390 function save()
391 {
392 /* return the selected PPD, and in future the selected options too */
393 return($this->pathToModified.$this->selectedPPD['link']);
394 }
396 /* Get Information for a single PPD entry
397 * This will be shown on top of template
398 */
399 function getPPDInformation()
400 {
401 $str = "none";
402 if(!empty($this->selectedPPD)){
403 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
404 }
405 return($str) ;
406 }
408 /* Display all options from the selected ppd file */
409 function generateProperties()
410 {
411 /* Set Headline */
412 $str = "";
413 $feed= "";
415 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
417 /* If ppd exists and is readable */
418 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
420 /* If there is no initial Configuration, load it */
421 if($this->ppdConfig == false){
422 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
423 }
425 /* Create a table */
426 $str .= "<div style='padding-left:30px;'><table summary=''>";
428 /* Input all data to the table */
429 foreach($this->ppdConfig as $cat => $obj){
431 /* Add new category */
432 $str .= "<tr><td colspan='2'>$feed";
433 if ($feed == ""){
434 $feed= "<br>";
435 }
436 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
437 $str .= "</td></tr>";
439 /* Add attributes of the current category */
440 foreach($obj as $attr => $settings){
443 /* Skip all entries beginning with _ */
444 if($attr[0] == "_") continue;
446 /* Prepare data */
447 $values = array();
448 $name = $settings['_name'];
449 $default = $settings['_default'];
450 $type = $settings['_type'];
452 /* Add name to table */
453 $str .= "<tr><td style='padding-left:40px;'>\n";
454 $str .= $name."<br>\n";
455 $str .= "</td><td>\n";
457 /* Get all values */
458 foreach( $settings as $vname => $value){
459 if($vname[0] != "_"){
460 $values[$vname]= $value;
461 }
462 }
464 /* preparing Html output
465 * Supported types are PickOne/Boolean
466 */
468 /* If type is PickOne, create a select box */
469 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
471 $str .= "<select name='".base64_encode($name)."'>\n";
472 foreach($values as $optionKey => $value){
473 $selected = "";
474 if($optionKey == $default){
475 $selected = " selected ";
476 }
477 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
478 }
479 $str .= "</select>\n";
481 }elseif($type == "Boolean"){
483 /* If type is Boolean & no values are given */
484 $str .= "<select name='".base64_encode($name)."'>\n";
485 if($default == "False"){
486 $str .= "<option value='True' >"._("True")."</option>\n";
487 $str .= "<option value='False' selected>"._("False")."</option>\n";
488 }else{
489 $str .= "<option value='True' selected>"._("True")."</option>\n";
490 $str .= "<option value='False' >"._("False")."</option>\n";
491 }
492 $str .= "</select>\n";
494 }else{
495 print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
496 }
497 $str .= "</td></tr>\n";
498 }
499 }
500 $str .= "</table></div>\n";
501 }
502 return($str);
503 }
505 function check(){ return(plugin::check()); }
506 }
507 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
508 ?>