db3d54a25f1cd347b013f1777b92c3067caa5e36
1 <?php
3 class printerPPDDialog extends plugin
4 {
5 /* attribute list for save action */
6 var $ignore_account = TRUE;
7 var $attributes = array("cn");
8 var $objectclasses = array("whatever");
10 /* PPD Handling */
11 var $selectedPPD = false; // e.g. /vendor/device.ppd
12 var $ppdManager = false; // new ppdManager;
13 var $ppdConfig = false; // $this->ppdManager->loadProperties($this->selectedPPD['link']);
14 var $ppdList = array(); // Contains all Printer models
15 var $ppdListHeader = array(); // Contains all printer vendors
17 /* Paths */
18 var $pathToPPD = ""; // Base path, defined in gosa.conf e.g. "/var/spool/ppd/"
19 var $pathToModified = "modified/"; // used to store the modified ppds
21 /* Object Info */
22 var $cn = "" ; // Used to tag the ppds modified by the printer object,
23 var $ui;
25 /* If there is already a ppd file for the same type of printer,
26 * remember the path to ppd file and display a dialog which allows
27 * to overwrite the current ppd file.
28 */
29 var $add_ppd_later = "";
30 var $add_later_msg_dialog = NULL;
32 function printerPPDDialog (&$config, $dn= NULL, $ppdfile=NULL )
33 {
34 plugin::plugin ($config, $dn);
35 $this->depselect = $this->config->current['BASE'];
37 $this->ui = get_userinfo();
39 /* Get PPD path and remove double //, and add trailing / */
40 $config = session::get('config');
41 if($config->get_cfg_value("ppdPath") != ""){
42 $this->pathToPPD = $config->get_cfg_value("ppdPath");
43 $this->pathToPPD= preg_replace("/\/\//", "/", $this->pathToPPD);
44 if(!preg_match("/\/$/",$this->pathToPPD)){
45 $this->pathToPPD = $this->pathToPPD."/";
46 }
47 }else{
48 $this->pathToPPD = "";
49 }
51 /* Check if ppdPath is set in gosa.conf.
52 */
53 if(empty($this->pathToPPD)){
54 msg_dialog::display(_("Configuration error"), msgPool::invalidConfigurationAttribute("ppdPath"), ERROR_DIALOG);
55 }
57 /* It seams that we have an existing PPD path, so go on */
58 if(!((!is_dir($this->pathToPPD))||(empty($this->pathToPPD)))){
60 /* Load all available PPD files and sort them into an array */
61 $this->ppdManager= new ppdManager($this->pathToPPD);
62 $this->getPrinterReload ();
64 /* The user has already a valid PPD assigned
65 * Get some informations about this PPD
66 * and set it as selected.
67 * The ppdpath ['link'] should be relative from .../ppd/modified/
68 * e.g. "/Compaq/Compaq-J1200.ppd" */
69 if(($ppdfile!== NULL)&&(strlen($ppdfile)>0)){
70 $ppdfile = preg_replace("#".$this->pathToModified."#","",$ppdfile);
71 if(!file_exists($this->pathToPPD.$this->pathToModified.$ppdfile)){
72 msg_dialog::display(_("PPD error"), sprintf(_("Cannot open PPD '%s'!"), $ppdfile), ERROR_DIALOG);
73 }else{
74 $res = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$ppdfile);
75 if($res){
76 $tmp = split("\n",$res);
77 $tmp3 = array();
78 $tmp3['name'] = trim(preg_replace("/^\-/","",trim($tmp[1])));
79 $tmp3['link'] = $ppdfile;
80 $tmp3['ppd'] = $res;
81 }
82 $this->selectedPPD = $tmp3;
83 }
84 }
85 }
86 }
89 function execute()
90 {
91 /* Call parent execute */
92 plugin::execute();
94 /* Fill templating stuff */
95 $display= "";
96 $smarty= get_smarty();
97 $smarty->assign("ppdString", _("Can't get ppd informations."));
98 $smarty->assign("showOptions", "");
99 $smarty->assign("path_valid", TRUE);
100 $smarty->assign("acl",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"));
102 $acl = $this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD");
104 if(empty($this->pathToPPD)){
106 /* Print out template */
107 $smarty->assign("path_valid", FALSE);
108 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
109 return($display);
110 }
112 /* Check these paths */
113 $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
115 /* If one of our required paths is not available, stop here and display some info */
116 foreach($paths as $path){
118 /* Check if path is write/readable*/
119 $is_r = @is_readable($path);
120 if(((!is_dir($path))||(empty($path)) || (!$is_r)) && (!@mkdir($path))){
121 msg_dialog::display(_("Configuration error"),
122 sprintf(_("Cannot open PPD path '%s' for reading and writing!"), $path), ERROR_DIALOG);
124 /* Print out template */
125 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
126 return($display);
127 }
128 }
130 // PPD selection / upload / dialog handling
132 /* Is there a new PPD file uploaded ? */
133 if(preg_match("/w/",$acl)){
134 if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
135 $file = ($_FILES['NewPPDFile']);
136 if($file['size'] != 0 ){
137 if($name = $this->AddPPD($file['tmp_name'])){
138 $this->SelectPPD($name);
139 }
140 }else{
141 msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
142 }
143 }
144 }
146 /* Overwrite existing PPD file and select it as currently used for this object */
147 if(is_object($this->add_later_msg_dialog) && ($this->add_later_msg_dialog->is_confirmed()) && $this->add_ppd_later != ""){
148 if($name = $this->AddPPD($this->add_ppd_later,TRUE)){
149 $this->SelectPPD($name);
150 }
151 $this->add_ppd_later = "";
152 $this->add_later_msg_dialog = NULL;
153 }
155 /* Open a dialog that allow us to select different PPDs */
156 if(preg_match("/w/",$acl)){
157 if(isset($_POST['SelectPPD'])){
158 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
159 }
160 }
162 /* The selection dialog fpr PPDs is canceled */
163 if(isset($_POST['ClosePPDSelection'])){
164 unset($this->dialog);
165 $this->dialog=FALSE;
166 }
168 /* Div Selection */
169 if((isset($_GET['act']))&&($_GET['act']=="use")){
170 $this->SelectPPD(base64_decode($_GET['id']));
171 unset($this->dialog);
172 $this->dialog=FALSE;
174 }
176 /* if a dialog is open, print the dialog instead of this class */
177 if(is_object($this->dialog)){
178 $display = $this->dialog->execute();
179 return($display);
180 }
182 // ENDE PPD selection / upload / dialog handling
184 /* Give smarty the information it needs */
185 $smarty->assign("ppdString" ,$this->getPPDInformation());
186 $tmp= $this->generateProperties();
187 if ($tmp == ""){
188 $smarty->assign("showOptions", 0);
189 } else {
190 $smarty->assign("showOptions", 1);
191 $smarty->assign("properties",$this->generateProperties());
192 }
194 /* Print out template */
195 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
196 return($display);
197 }
200 /* Select PPD */
201 function SelectPPD($name)
202 {
203 /* Replace base path we don't need it here
204 The path we need looks like this : "/Vendor/ModellName.ppd";
205 thats all */
206 $name = preg_replace("#".$this->pathToPPD."#","",$name);
208 /* Intialise some base vars */
209 $AbsoluteSourceName = $this->pathToPPD.$name;
210 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
211 $Vendor = ""; // Vendor
212 $Name = ""; // Name
213 $Modell = ""; // Modell
214 $PrinterName = ""; // The new name of the printer
215 $PPDName = "";
217 /* Force reload of config dialog */
218 $this->ppdConfig = false;
219 $this->selectedPPD['link'] = false;
221 /* Get PPD informations and set vendor / modell / name */
222 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
223 msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($AbsoluteSourceName), ERROR_DIALOG);
224 return;
225 }
226 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
227 if($res){
228 $tmp = split("\n",$res);
229 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
230 $Vendor = trim($tmp[0]);
231 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
232 }
234 $PrinterName = $this->cn."-".preg_replace("/[^a-z0-9-_\.]/i","_",$Name);
235 $PPDName = $Vendor."/".$PrinterName.".ppd";
237 /* Create the vendors path, if it doesn't exists already */
238 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
239 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
240 msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($AbsoluteDestinationPath.$Vendor), ERROR_DIALOG);
241 return(false);
242 }
243 }
245 /* Create destination file handle */
246 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
247 if(!$fp){
248 msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($AbsoluteDestinationPath.$PPDName), ERROR_DIALOG);
249 return(false);
250 }
252 $str = file_get_contents($AbsoluteSourceName);
253 fputs($fp,$str);
254 @fclose($fp);
256 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
258 $tmp3['link'] =$PPDName;
259 $this->selectedPPD = $tmp3;
260 $this->getPrinterReload();
261 return($PPDName);
262 }
265 /* This function adds a new ppd file to the list of available ppds.
266 All required paths and files will be created
267 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
268 function AddPPD($_PathOnHdd,$overwrite = FALSE)
269 {
270 /* Check if file exists && is readable */
271 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
272 msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
273 return(false);
274 }
276 /* Reload list to detect changes e.g. a file has been deleted */
277 $this->getPrinterReload();
279 /* Get Description from ppd, & parse out some informations */
280 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
281 if($res){
282 $tmp = split("\n",$res);
283 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
284 $vendor = trim($tmp[0]);
285 $model = trim(preg_replace("/".$vendor."/","",$name));
286 }
288 /* Check if parse was successfull */
289 if(empty($name) || empty($vendor)){
290 msg_dialog::display(_("PPD error"), sprintf(_("Cannot parse PPD '%s'!"), $_PathOnHdd), ERROR_DIALOG);
291 return(false);
292 }
294 /* Prepare list of ppds */
295 if(!isset($this->ppdList[$vendor])){
296 $this->ppdList[$vendor] = array();
297 }
299 /* Create ppd file and fill in the source contents */
300 $ppdname = $vendor."/".$name.".ppd";
301 $filename = $this->pathToPPD.preg_replace("/[^a-z0-9-_\.\/]/i","_",$ppdname);
302 $filename = $this->pathToPPD.$ppdname;
303 $contents = file_get_contents($_PathOnHdd);
306 /* Check if this ppd already exists */
307 $found = false;
308 foreach($this->ppdList[$vendor] as $key => $val){
309 if(preg_match("/".$model.".*/i",$key)){
310 $found = true;
311 if(!$overwrite){
312 if(!copy($_PathOnHdd,$_PathOnHdd."_back")){
313 msg_dialog::display(_("PPD error"), msgPool::cannotReadFile($_PathOnHdd), ERROR_DIALOG);
314 }else{
315 $this->add_ppd_later = $_PathOnHdd."_back";
316 $this->add_later_msg_dialog = new msg_dialog(_("Overwrite existing PPD"),
317 _("There is already a ppd file for this kind of printer. Do you want to overwrite it?"),CONFIRM_DIALOG);
318 }
319 return;
320 }
321 }
322 }
324 /* Create the vendors path, if it doesn't exists already */
325 if(!is_dir($this->pathToPPD.$vendor)){
326 if(!(@mkdir($this->pathToPPD.$vendor))){
327 msg_dialog::display(_("PPD error"), msgPool::cannotCreateFolder($this->pathToPPD.$vendor), ERROR_DIALOG);
328 return(false);
329 }
330 }
332 /* Open file handle */
333 $fp = fopen($filename,"w+");
335 /* Check file handle & contents */
336 if(!$fp){
337 msg_dialog::display(_("PPD error"), msgPool::cannotWriteFile($filename), ERROR_DIALOG);
338 return;
339 }
340 if(empty($contents)){
341 msg_dialog::display(_("PPD error"), msgPool::incorrectUpload(_("file is empty")), ERROR_DIALOG);
342 return;
343 }
345 /* Fille file with data */
346 fputs($fp,$contents);
347 @fclose($fp);
349 /* Our job is done here */
350 return($ppdname);
351 }
354 /* This function reloads the list of available printers/vendors
355 $this->ppdListHeader
356 Compaq => 1
357 $this->ppdList
358 Compaq => Compaq IJ1200 => name => Compaq IJ1200
359 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
360 ppd => Compaq - Co
361 */
362 function getPrinterReload()
363 {
364 if(is_readable($this->pathToPPD)){
365 $tmp = @$this->ppdManager->getPrinterList(true);
367 $this->ppdListHeader = $this->ppdList = array();
369 /* Sort all available files, and create header (Vendor index) */
370 foreach($tmp as $file=>$ppd){
372 if(preg_match("#".$this->pathToModified."#",$file)) continue;
374 $tmp2 = split("\n",$ppd);
375 if(!isset($this->ppdListHeader[$tmp2[0]])){
376 $this->ppdListHeader[$tmp2[0]]=0;
377 }
378 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
379 $tmp3['link'] =$file;
380 $tmp3['ppd'] =$ppd;
381 $this->ppdListHeader[$tmp2[0]]++;
382 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
383 }
384 }
385 }
388 /* Save all options posted from ppd dialog */
389 function save_object()
390 {
391 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
392 return;
393 }
395 if(preg_match("/w/",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"))){
396 foreach($this->ppdConfig as $cat => $obj){
397 foreach($obj as $attr => $attributes){
398 if(isset($_POST[base64_encode($attributes['_name'])])){
399 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
400 }
401 }
402 }
403 }
404 }
407 /* Save modified ppd */
408 function save_ppd()
409 {
410 if($this->ppdManager){
411 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
412 }
413 }
416 /* Return selected ppd path, if none is selected then false */
417 function save()
418 {
419 /* return the selected PPD, and in future the selected options too */
420 return($this->pathToModified.$this->selectedPPD['link']);
421 }
424 /* Get Information for a single PPD entry
425 * This will be shown on top of template
426 */
427 function getPPDInformation()
428 {
429 $str = "none";
430 if(!empty($this->selectedPPD)){
431 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
432 }
433 return($str) ;
434 }
437 /* Display all options from the selected ppd file */
438 function generateProperties()
439 {
440 /* Set Headline */
441 $str = "";
442 $feed= "";
444 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
446 /* If ppd exists and is readable */
447 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
449 /* If there is no initial Configuration, load it */
450 if($this->ppdConfig == false){
451 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
452 }
454 /* Create a table */
455 $str .= "<div style='padding-left:30px;'><table summary=''>";
457 /* Input all data to the table */
458 foreach($this->ppdConfig as $cat => $obj){
460 /* Add new category */
461 $str .= "<tr><td colspan='2'>$feed";
462 if ($feed == ""){
463 $feed= "<br>";
464 }
465 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
466 $str .= "</td></tr>";
468 /* Add attributes of the current category */
469 foreach($obj as $attr => $settings){
471 /* Skip all entries beginning with _ */
472 if($attr[0] == "_") continue;
474 /* Prepare data */
475 $values = array();
476 $name = $settings['_name'];
478 if (!isset($settings['_default'])){
479 $default = "";
480 } else {
481 $default = $settings['_default'];
482 }
484 $type = $settings['_type'];
486 /* Add name to table */
487 $str .= "<tr><td style='padding-left:40px;'>\n";
488 $str .= $name."<br>\n";
489 $str .= "</td><td>\n";
491 /* Get all values */
492 foreach( $settings as $vname => $value){
493 if($vname[0] != "_"){
494 $values[$vname]= $value;
495 }
496 }
498 $acl ="";
499 if(!preg_match("/w/",$this->ui->get_permissions($this->dn,"printer/printgeneric","gotoPrinterPPD"))){
500 $acl = "disabled";
501 }
503 /* preparing Html output
504 * Supported types are PickOne/Boolean
505 */
507 /* If type is PickOne, create a select box */
508 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
510 $str .= "<select name='".base64_encode($name)."' $acl >\n";
511 foreach($values as $optionKey => $value){
512 $selected = "";
513 if($optionKey == $default){
514 $selected = " selected ";
515 }
516 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
517 }
518 $str .= "</select>\n";
520 }elseif($type == "Boolean"){
522 /* If type is Boolean & no values are given */
523 $str .= "<select name='".base64_encode($name)."' $acl>\n";
524 if($default == "False"){
525 $str .= "<option value='True' >"._("True")."</option>\n";
526 $str .= "<option value='False' selected>"._("False")."</option>\n";
527 }else{
528 $str .= "<option value='True' selected>"._("True")."</option>\n";
529 $str .= "<option value='False' >"._("False")."</option>\n";
530 }
531 $str .= "</select>\n";
533 }else{
534 msg_dialog::display(_("PPD error"), sprintf(_("PPD type '%s' is not supported!"), $type), ERROR_DIALOG);
535 }
536 $str .= "</td></tr>\n";
537 }
538 }
539 $str .= "</table></div>\n";
540 }
541 return($str);
542 }
544 function removeModifiedPPD()
545 {
546 $path = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
548 if(file_exists($path)){
549 if(is_writeable($path)){
550 if(!@unlink($path)){
551 msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
552 }
553 }else{
554 msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
555 }
556 }else{
557 msg_dialog::display(_("PPD error"), msgPool::cannotDeleteFile($path), ERROR_DIALOG);
558 }
559 }
561 function update_ppd_url()
562 {
563 $this->SelectPPD("modified/".$this->selectedPPD['link']);
564 return("modified/".$this->selectedPPD['link']);
565 }
567 function check()
568 {
569 $message = plugin::check();
570 if(empty($this->selectedPPD['link'])){
571 $message[] = _("Please select a valid ppd file or use 'Cancel' to go back to printer configuration.");
572 }
573 return($message);
574 }
575 }
576 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
577 ?>