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 $this->getPrinterReload ();
54 /* The user has already a valid PPD assigned
55 * Get some informations about this PPD
56 * and set it as selected.
57 * The ppdpath ['link'] should be relative from .../ppd/modified/
58 * e.g. "/Compaq/Compaq-J1200.ppd" */
59 if(($ppdfile!= NULL)&&(strlen($ppdfile)>0)){
60 $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
61 if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
62 print_red(sprintf(_("Can't open '%s', ppd settings resetted."),$ppdfile));
63 }else{
64 $res = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
65 if($res){
66 $tmp = split("\n",$res);
67 $tmp3 = array();
68 $tmp3['name'] = trim(preg_replace("/^\-/","",trim($tmp[1])));
69 $tmp3['link'] = $ppdfile;
70 $tmp3['ppd'] = $res;
71 }
72 $this->selectedPPD = $tmp3;
73 }
74 }
75 }
76 }
79 function execute()
80 {
81 /* Call parent execute */
82 plugin::execute();
84 /* Fill templating stuff */
85 $display= "";
86 $smarty= get_smarty();
87 $smarty->assign("ppdString", _("Can't get ppd informations."));
88 $smarty->assign("showOptions", "");
90 /* Check these paths */
91 $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
93 /* If one of our required paths is not available, stop here and display some info */
94 foreach($paths as $path){
96 /* Check if path is write/readable*/
97 $is_r = @is_readable($path);
98 if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
99 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));
100 /* Print out template */
101 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
102 return($display);
103 }
104 }
106 // PPD selection / upload / dialog handling
108 /* Is there a new PPD file uploaded ? */
109 if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
110 $file = ($_FILES['NewPPDFile']);
111 if($file['size'] != 0 ){
112 if($name = $this->AddPPD($file['tmp_name'])){
113 $this->SelectPPD($name);
114 }
115 }else{
116 print_red(_("Please specify a valid ppd file."));
117 }
118 }
120 /* Open a dialog that allow us to select different PPDs */
121 if(isset($_POST['SelectPPD'])){
122 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
123 }
125 /* The selection dialog fpr PPDs is canceled */
126 if(isset($_POST['ClosePPDSelection'])){
127 unset($this->dialog);
128 $this->dialog=NULL;
129 }
131 /* Div Selection */
132 if((isset($_GET['act']))&&($_GET['act']=="use")){
133 $this->SelectPPD(base64_decode($_GET['id']));
134 unset($this->dialog);
135 $this->dialog=NULL;
137 }
139 /* if a dialog is open, print the dialog instead of this class */
140 if($this->dialog!=NULL){
141 $display = $this->dialog->execute();
142 return($display);
143 }
145 // ENDE PPD selection / upload / dialog handling
147 /* Give smarty the information it needs */
148 $smarty->assign("ppdString" ,$this->getPPDInformation());
149 $tmp= $this->generateProperties();
150 if ($tmp == ""){
151 $smarty->assign("showOptions", 0);
152 } else {
153 $smarty->assign("showOptions", 1);
154 $smarty->assign("properties",$this->generateProperties());
155 }
157 /* Print out template */
158 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
159 return($display);
160 }
163 /* Select PPD */
164 function SelectPPD($name)
165 {
166 /* Replace base path we don't need it here
167 The path we need looks like this : "/Vendor/ModellName.ppd";
168 thats all */
169 $name = preg_replace("#".$this->pathToPPD."#","",$name);
171 /* Intialise some base vars */
172 $AbsoluteSourceName = $this->pathToPPD.$name;
173 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
174 $Vendor = ""; // Vendor
175 $Name = ""; // Name
176 $Modell = ""; // Modell
177 $PrinterName = ""; // The new name of the printer
178 $PPDName = "";
180 /* Force reload of config dialog */
181 $this->ppdConfig = false;
182 $this->selectedPPD['link'] = false;
184 /* Get PPD informations and set vendor / modell / name */
185 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
186 print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));
187 return;
188 }
189 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
190 if($res){
191 $tmp = split("\n",$res);
192 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
193 $Vendor = trim($tmp[0]);
194 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
195 }
197 $PrinterName = $this->cn."-".$Name;
198 $PPDName = $Vendor."/".$PrinterName.".ppd";
200 /* Create the vendors path, if it doesn't exists already */
201 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
202 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
203 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
204 return(false);
205 }
206 }
208 /* Create destination file handle */
209 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
210 if(!$fp){
211 print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
212 return(false);
213 }
215 $str = file_get_contents($AbsoluteSourceName);
216 fputs($fp,$str);
217 @fclose($fp);
219 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
221 $tmp3['link'] =$PPDName;
222 $this->selectedPPD = $tmp3;
223 $this->getPrinterReload();
224 return($PPDName);
225 }
228 /* This function adds a new ppd file to the list of available ppds.
229 All required paths and files will be created
230 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
231 function AddPPD($_PathOnHdd)
232 {
233 /* Check if file exists && is readable */
234 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
235 print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
236 return(false);
237 }
239 /* Reload list to detect changes e.g. a file has been deleted */
240 $this->getPrinterReload();
242 /* Get Description from ppd, & parse out some informations */
243 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
244 if($res){
245 $tmp = split("\n",$res);
246 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
247 $vendor = trim($tmp[0]);
248 $model = trim(preg_replace("/".$vendor."/","",$name));
249 }
251 /* Check if parse was successfull */
252 if(empty($name) || empty($vendor)){
253 print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
254 return(false);
255 }
257 /* Prepare list of ppds */
258 if(!isset($this->ppdList[$vendor])){
259 $this->ppdList[$vendor] = array();
260 }
262 /* Check if this ppd already exists */
263 $found = false;
264 foreach($this->ppdList[$vendor] as $key => $val){
265 if(preg_match("/".$model.".*/i",$key)){
266 $found = true;
267 print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
268 return;
269 }
270 }
272 /* Create the vendors path, if it doesn't exists already */
273 if(!is_dir($this->pathToPPD.$vendor)){
274 if(!(@mkdir($this->pathToPPD.$vendor))){
275 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
276 return(false);
277 }
278 }
280 /* Create ppd file and fill in the source contents */
281 $ppdname = $vendor."/".$name.".ppd";
282 $filename = $this->pathToPPD.$ppdname;
283 $fp = fopen($filename,"w+");
284 $contents = file_get_contents($_PathOnHdd);
286 /* Check file handle & contents */
287 if(!$fp){
288 print_red(sprintf(_("Can't save file '%s'."),$filename));
289 return;
290 }
291 if(empty($contents)){
292 print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
293 return;
294 }
296 /* Fille file with data */
297 fputs($fp,$contents);
298 @fclose($fp);
300 /* Our job is done here */
301 return($ppdname);
302 }
305 /* This function reloads the list of available printers/vendors
306 $this->ppdListHeader
307 Compaq => 1
308 $this->ppdList
309 Compaq => Compaq IJ1200 => name => Compaq IJ1200
310 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
311 ppd => Compaq - Co
312 */
313 function getPrinterReload()
314 {
315 if(is_readable($this->pathToPPD)){
316 $tmp = $this->ppdManager->getPrinterList(true);
318 $this->ppdListHeader = $this->ppdList = array();
320 /* Sort all available files, and create header (Vendor index) */
321 foreach($tmp as $file=>$ppd){
323 if(preg_match("#".$this->pathToModified."#",$file)) continue;
325 $tmp2 = split("\n",$ppd);
326 if(!isset($this->ppdListHeader[$tmp2[0]])){
327 $this->ppdListHeader[$tmp2[0]]=0;
328 }
329 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
330 $tmp3['link'] =$file;
331 $tmp3['ppd'] =$ppd;
332 $this->ppdListHeader[$tmp2[0]]++;
333 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
334 }
335 }
336 }
339 /* Save all options posted from ppd dialog */
340 function save_object()
341 {
342 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
343 return;
344 }
346 foreach($this->ppdConfig as $cat => $obj){
347 foreach($obj as $attr => $attributes){
348 if(isset($_POST[base64_encode($attributes['_name'])])){
349 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
350 }
351 }
352 }
353 }
356 /* Save modified ppd */
357 function save_ppd(){
358 if($this->ppdManager){
359 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
360 }
361 }
364 /* Return selected ppd path, if none is selected then false */
365 function save()
366 {
367 /* return the selected PPD, and in future the selected options too */
368 return($this->pathToModified.$this->selectedPPD['link']);
369 }
372 /* Get Information for a single PPD entry
373 * This will be shown on top of template
374 */
375 function getPPDInformation()
376 {
377 $str = "none";
378 if(!empty($this->selectedPPD)){
379 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
380 }
381 return($str) ;
382 }
385 /* Display all options from the selected ppd file */
386 function generateProperties()
387 {
388 /* Set Headline */
389 $str = "";
390 $feed= "";
392 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
394 /* If ppd exists and is readable */
395 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
397 /* If there is no initial Configuration, load it */
398 if($this->ppdConfig == false){
399 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
400 }
402 /* Create a table */
403 $str .= "<div style='padding-left:30px;'><table summary=''>";
405 /* Input all data to the table */
406 foreach($this->ppdConfig as $cat => $obj){
408 /* Add new category */
409 $str .= "<tr><td colspan='2'>$feed";
410 if ($feed == ""){
411 $feed= "<br>";
412 }
413 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
414 $str .= "</td></tr>";
416 /* Add attributes of the current category */
417 foreach($obj as $attr => $settings){
419 /* Skip all entries beginning with _ */
420 if($attr[0] == "_") continue;
422 /* Prepare data */
423 $values = array();
424 $name = $settings['_name'];
426 if (!isset($settings['_default'])){
427 $default = "";
428 } else {
429 $default = $settings['_default'];
430 }
432 $type = $settings['_type'];
434 /* Add name to table */
435 $str .= "<tr><td style='padding-left:40px;'>\n";
436 $str .= $name."<br>\n";
437 $str .= "</td><td>\n";
439 /* Get all values */
440 foreach( $settings as $vname => $value){
441 if($vname[0] != "_"){
442 $values[$vname]= $value;
443 }
444 }
446 /* preparing Html output
447 * Supported types are PickOne/Boolean
448 */
450 /* If type is PickOne, create a select box */
451 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
453 $str .= "<select name='".base64_encode($name)."'>\n";
454 foreach($values as $optionKey => $value){
455 $selected = "";
456 if($optionKey == $default){
457 $selected = " selected ";
458 }
459 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
460 }
461 $str .= "</select>\n";
463 }elseif($type == "Boolean"){
465 /* If type is Boolean & no values are given */
466 $str .= "<select name='".base64_encode($name)."'>\n";
467 if($default == "False"){
468 $str .= "<option value='True' >"._("True")."</option>\n";
469 $str .= "<option value='False' selected>"._("False")."</option>\n";
470 }else{
471 $str .= "<option value='True' selected>"._("True")."</option>\n";
472 $str .= "<option value='False' >"._("False")."</option>\n";
473 }
474 $str .= "</select>\n";
476 }else{
477 print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
478 }
479 $str .= "</td></tr>\n";
480 }
481 }
482 $str .= "</table></div>\n";
483 }
484 return($str);
485 }
487 function removeModifiedPPD()
488 {
489 $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
491 if(file_exists($path)){
492 if(is_writeable($path)){
493 if(!@unlink($path)){
494 print_red(sprintf(_("Removing old ppd file '%s' failed."),$path));
495 }
496 }else{
497 print_red(sprintf(_("Removing old ppd file '%s' failed. File is not accessible."),$path));
498 }
499 }else{
500 print_red(sprintf(_("Removing old ppd file '%s' failed. File does not exists or is not accessible."),$path));
501 }
502 }
504 function check()
505 {
506 $message = plugin::check();
507 if(empty($this->selectedPPD['link'])){
508 $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
509 }
510 return($message);
511 }
512 }
513 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
514 ?>