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,
29 function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
30 {
31 plugin::plugin ($config, $dn);
32 $this->depselect = $this->config->current['BASE'];
34 /* Get PPD path and remove double //, and add trailing / */
35 if(isset($_SESSION['config']->data['MAIN']['PPD_PATH'])){
36 $this->pathToPPD = $_SESSION['config']->data['MAIN']['PPD_PATH'];
37 $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
38 if(!preg_match("/\/$/",$this->pathToPPD)){
39 $this->pathToPPD = $this->pathToPPD."/";
40 }
41 }else{
42 $this->pathToPPD = "";
43 }
45 /* It seams that we have an existing PPD path, so go on */
46 if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){
48 /* Load all available PPD files and sort them into an array */
49 $this->ppdManager= new ppdManager($this->pathToPPD);
50 $this->getPrinterReload ();
52 /* The user has already a valid PPD assigned
53 * Get some informations about this PPD
54 * and set it as selected.
55 * The ppdpath ['link'] should be relative from .../ppd/modified/
56 * e.g. "/Compaq/Compaq-J1200.ppd" */
57 if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
58 $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
59 if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
60 print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
61 }else{
62 $res = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
63 if($res){
64 $tmp = split("\n",$res);
65 $tmp3 = array();
66 $tmp3['name'] = trim(preg_replace("/^\-/","",trim($tmp[1])));
67 $tmp3['link'] = $ppdfile;
68 $tmp3['ppd'] = $res;
69 }
70 $this->selectedPPD = $tmp3;
71 }
72 }
73 }
74 }
77 function execute()
78 {
79 /* Call parent execute */
80 plugin::execute();
82 /* Fill templating stuff */
83 $display= "";
84 $smarty= get_smarty();
85 $smarty->assign("ppdString", _("Can't get ppd informations."));
86 $smarty->assign("showOptions", "");
88 /* Check these paths */
89 $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
91 /* If one of our required paths is not available, stop here and display some info */
92 foreach($paths as $path){
94 /* Check if path is write/readable*/
95 $is_r = @is_readable($path);
96 if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
97 print_red(sprintf(_("The specified path '%s' which results from PPD_PATH in your gosa.conf is invalid, can't read/write any ppd informations."),$path));
98 /* Print out template */
99 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
100 return($display);
101 }
102 }
104 // PPD selection / upload / dialog handling
106 /* Is there a new PPD file uploaded ? */
107 if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
108 $file = ($_FILES['NewPPDFile']);
109 if($file['size'] != 0 ){
110 if($name = $this->AddPPD($file['tmp_name'])){
111 $this->SelectPPD($name);
112 }
113 }else{
114 print_red(_("Please specify a valid ppd file."));
115 }
116 }
118 /* Open a dialog that allow us to select different PPDs */
119 if(isset($_POST['SelectPPD'])){
120 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
121 }
123 /* The selection dialog fpr PPDs is canceled */
124 if(isset($_POST['ClosePPDSelection'])){
125 unset($this->dialog);
126 $this->dialog=FALSE;
127 }
129 /* Div Selection */
130 if((isset($_GET['act']))&&($_GET['act']=="use")){
131 $this->SelectPPD(base64_decode($_GET['id']));
132 unset($this->dialog);
133 $this->dialog=FALSE;
135 }
137 /* if a dialog is open, print the dialog instead of this class */
138 if(is_object($this->dialog)){
139 $display = $this->dialog->execute();
140 return($display);
141 }
143 // ENDE PPD selection / upload / dialog handling
145 /* Give smarty the information it needs */
146 $smarty->assign("ppdString" ,$this->getPPDInformation());
147 $tmp= $this->generateProperties();
148 if ($tmp == ""){
149 $smarty->assign("showOptions", 0);
150 } else {
151 $smarty->assign("showOptions", 1);
152 $smarty->assign("properties",$this->generateProperties());
153 }
155 /* Print out template */
156 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
157 return($display);
158 }
161 /* Select PPD */
162 function SelectPPD($name)
163 {
164 /* Replace base path we don't need it here
165 The path we need looks like this : "/Vendor/ModellName.ppd";
166 thats all */
167 $name = preg_replace("#".$this->pathToPPD."#","",$name);
169 /* Intialise some base vars */
170 $AbsoluteSourceName = $this->pathToPPD.$name;
171 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
172 $Vendor = ""; // Vendor
173 $Name = ""; // Name
174 $Modell = ""; // Modell
175 $PrinterName = ""; // The new name of the printer
176 $PPDName = "";
178 /* Force reload of config dialog */
179 $this->ppdConfig = false;
180 $this->selectedPPD['link'] = false;
182 /* Get PPD informations and set vendor / modell / name */
183 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
184 print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));
185 return;
186 }
187 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
188 if($res){
189 $tmp = split("\n",$res);
190 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
191 $Vendor = trim($tmp[0]);
192 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
193 }
195 $PrinterName = $this->cn."-".$Name;
196 $PPDName = $Vendor."/".$PrinterName.".ppd";
198 /* Create the vendors path, if it doesn't exists already */
199 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
200 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
201 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
202 return(false);
203 }
204 }
206 /* Create destination file handle */
207 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
208 if(!$fp){
209 print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
210 return(false);
211 }
213 $str = file_get_contents($AbsoluteSourceName);
214 fputs($fp,$str);
215 @fclose($fp);
217 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
219 $tmp3['link'] =$PPDName;
220 $this->selectedPPD = $tmp3;
221 $this->getPrinterReload();
222 return($PPDName);
223 }
226 /* This function adds a new ppd file to the list of available ppds.
227 All required paths and files will be created
228 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
229 function AddPPD($_PathOnHdd)
230 {
231 /* Check if file exists && is readable */
232 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
233 print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
234 return(false);
235 }
237 /* Reload list to detect changes e.g. a file has been deleted */
238 $this->getPrinterReload();
240 /* Get Description from ppd, & parse out some informations */
241 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
242 if($res){
243 $tmp = split("\n",$res);
244 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
245 $vendor = trim($tmp[0]);
246 $model = trim(preg_replace("/".$vendor."/","",$name));
247 }
249 /* Check if parse was successfull */
250 if(empty($name) || empty($vendor)){
251 print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any model or vendor informations."),$_PathOnHdd));
252 return(false);
253 }
255 /* Prepare list of ppds */
256 if(!isset($this->ppdList[$vendor])){
257 $this->ppdList[$vendor] = array();
258 }
260 /* Check if this ppd already exists */
261 $found = false;
262 foreach($this->ppdList[$vendor] as $key => $val){
263 if(preg_match("/".$model.".*/i",$key)){
264 $found = true;
265 print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
266 return;
267 }
268 }
270 /* Create the vendors path, if it doesn't exists already */
271 if(!is_dir($this->pathToPPD.$vendor)){
272 if(!(@mkdir($this->pathToPPD.$vendor))){
273 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
274 return(false);
275 }
276 }
278 /* Create ppd file and fill in the source contents */
279 $ppdname = $vendor."/".$name.".ppd";
280 $filename = $this->pathToPPD.$ppdname;
281 $fp = fopen($filename,"w+");
282 $contents = file_get_contents($_PathOnHdd);
284 /* Check file handle & contents */
285 if(!$fp){
286 print_red(sprintf(_("Can't save file '%s'."),$filename));
287 return;
288 }
289 if(empty($contents)){
290 print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
291 return;
292 }
294 /* Fille file with data */
295 fputs($fp,$contents);
296 @fclose($fp);
298 /* Our job is done here */
299 return($ppdname);
300 }
303 /* This function reloads the list of available printers/vendors
304 $this->ppdListHeader
305 Compaq => 1
306 $this->ppdList
307 Compaq => Compaq IJ1200 => name => Compaq IJ1200
308 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
309 ppd => Compaq - Co
310 */
311 function getPrinterReload()
312 {
313 if(is_readable($this->pathToPPD)){
314 $tmp = $this->ppdManager->getPrinterList(true);
316 $this->ppdListHeader = $this->ppdList = array();
318 /* Sort all available files, and create header (Vendor index) */
319 foreach($tmp as $file=>$ppd){
321 if(preg_match("#".$this->pathToModified."#",$file)) continue;
323 $tmp2 = split("\n",$ppd);
324 if(!isset($this->ppdListHeader[$tmp2[0]])){
325 $this->ppdListHeader[$tmp2[0]]=0;
326 }
327 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
328 $tmp3['link'] =$file;
329 $tmp3['ppd'] =$ppd;
330 $this->ppdListHeader[$tmp2[0]]++;
331 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
332 }
333 }
334 }
337 /* Save all options posted from ppd dialog */
338 function save_object()
339 {
340 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
341 return;
342 }
344 foreach($this->ppdConfig as $cat => $obj){
345 foreach($obj as $attr => $attributes){
346 if(isset($_POST[base64_encode($attributes['_name'])])){
347 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
348 }
349 }
350 }
351 }
354 /* Save modified ppd */
355 function save_ppd(){
356 if($this->ppdManager){
357 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
358 }
359 }
362 /* Return selected ppd path, if none is selected then false */
363 function save()
364 {
365 /* return the selected PPD, and in future the selected options too */
366 return($this->pathToModified.$this->selectedPPD['link']);
367 }
370 /* Get Information for a single PPD entry
371 * This will be shown on top of template
372 */
373 function getPPDInformation()
374 {
375 $str = "none";
376 if(!empty($this->selectedPPD)){
377 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
378 }
379 return($str) ;
380 }
383 /* Display all options from the selected ppd file */
384 function generateProperties()
385 {
386 /* Set Headline */
387 $str = "";
388 $feed= "";
390 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
392 /* If ppd exists and is readable */
393 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
395 /* If there is no initial Configuration, load it */
396 if($this->ppdConfig == false){
397 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
398 }
400 /* Create a table */
401 $str .= "<div style='padding-left:30px;'><table summary=''>";
403 /* Input all data to the table */
404 foreach($this->ppdConfig as $cat => $obj){
406 /* Add new category */
407 $str .= "<tr><td colspan='2'>$feed";
408 if ($feed == ""){
409 $feed= "<br>";
410 }
411 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
412 $str .= "</td></tr>";
414 /* Add attributes of the current category */
415 foreach($obj as $attr => $settings){
417 /* Skip all entries beginning with _ */
418 if($attr[0] == "_") continue;
420 /* Prepare data */
421 $values = array();
422 $name = $settings['_name'];
424 if (!isset($settings['_default'])){
425 $default = "";
426 } else {
427 $default = $settings['_default'];
428 }
430 $type = $settings['_type'];
432 /* Add name to table */
433 $str .= "<tr><td style='padding-left:40px;'>\n";
434 $str .= $name."<br>\n";
435 $str .= "</td><td>\n";
437 /* Get all values */
438 foreach( $settings as $vname => $value){
439 if($vname[0] != "_"){
440 $values[$vname]= $value;
441 }
442 }
444 /* preparing Html output
445 * Supported types are PickOne/Boolean
446 */
448 /* If type is PickOne, create a select box */
449 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
451 $str .= "<select name='".base64_encode($name)."'>\n";
452 foreach($values as $optionKey => $value){
453 $selected = "";
454 if($optionKey == $default){
455 $selected = " selected ";
456 }
457 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
458 }
459 $str .= "</select>\n";
461 }elseif($type == "Boolean"){
463 /* If type is Boolean & no values are given */
464 $str .= "<select name='".base64_encode($name)."'>\n";
465 if($default == "False"){
466 $str .= "<option value='True' >"._("True")."</option>\n";
467 $str .= "<option value='False' selected>"._("False")."</option>\n";
468 }else{
469 $str .= "<option value='True' selected>"._("True")."</option>\n";
470 $str .= "<option value='False' >"._("False")."</option>\n";
471 }
472 $str .= "</select>\n";
474 }else{
475 print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
476 }
477 $str .= "</td></tr>\n";
478 }
479 }
480 $str .= "</table></div>\n";
481 }
482 return($str);
483 }
485 function removeModifiedPPD()
486 {
487 $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
489 if(file_exists($path)){
490 if(is_writeable($path)){
491 if(!@unlink($path)){
492 print_red(sprintf(_("Removing old ppd file '%s' failed."),$path));
493 }
494 }else{
495 print_red(sprintf(_("Removing old ppd file '%s' failed. File is not accessible."),$path));
496 }
497 }else{
498 print_red(sprintf(_("Removing old ppd file '%s' failed. File does not exists or is not accessible."),$path));
499 }
500 }
502 function check()
503 {
504 $message = plugin::check();
505 if(empty($this->selectedPPD['link'])){
506 $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
507 }
508 return($message);
509 }
510 }
511 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
512 ?>