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 }
80 function execute()
81 {
82 /* Call parent execute */
83 plugin::execute();
85 /* Fill templating stuff */
86 $display= "";
87 $smarty= get_smarty();
88 $smarty->assign("ppdString", _("Can't get ppd informations."));
89 $smarty->assign("showOptions", "");
91 /* Check these paths */
92 $paths = array($this->pathToPPD, $this->pathToPPD.$this->pathToModified);
94 /* If one of our required paths is not available, stop here and display some info */
95 foreach($paths as $path){
97 /* Check if path is write/readable*/
98 $is_r = @is_readable($path);
99 if((!is_dir($path))||(empty($path)) || (!$is_r)){
100 print_red(sprintf(_("The specified path '%s' which results from PPD_PATH in your gosa.conf is invalid,".
101 " can't read/write any ppd informations."),$path));
102 /* Print out template */
103 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
104 return($display);
105 }
106 }
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 }
121 /* Open a dialog that allow us to select different PPDs
122 */
123 if(isset($_POST['SelectPPD'])){
124 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
125 }
127 /* The selection dialog fpr PPDs is canceled
128 */
129 if(isset($_POST['ClosePPDSelection'])){
130 unset($this->dialog);
131 $this->dialog=NULL;
132 }
134 /* A new PPDs was selected in the PPDs selection Dialog
135 * Perform a Check. If everything is fine, use the new PPD.
136 */
137 if(isset($_POST['SavePPDSelection'])){
138 if(!isset($_POST['PPDselection'])){
139 print_red(_("Please select a valid ppd."));
140 }else{
141 $this->SelectPPD($_POST['PPDselection']);
142 unset($this->dialog);
143 $this->dialog=NULL;
144 }
145 }
147 /* Div Selection */
148 if((isset($_GET['act']))&&($_GET['act']=="use")){
149 $this->SelectPPD(base64_decode($_GET['id']));
150 unset($this->dialog);
151 $this->dialog=NULL;
153 }
155 /* if a dialog is open, print the dialog instead of this class
156 */
157 if($this->dialog!=NULL){
158 $display = $this->dialog->execute();
159 return($display);
160 }
162 /* Give smarty the information it needs */
163 $smarty->assign("ppdString" ,$this->getPPDInformation());
164 $tmp= $this->generateProperties();
165 if ($tmp == ""){
166 $smarty->assign("showOptions", 0);
167 } else {
168 $smarty->assign("showOptions", 1);
169 $smarty->assign("properties",$this->generateProperties());
170 }
172 /* Print out template */
173 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
174 return($display);
175 }
178 /* Select PPD */
179 function SelectPPD($name)
180 {
181 /* Replace base path we don't need it here
182 The path we need looks like this : "/Vendor/ModellName.ppd";
183 thats all */
184 $name = preg_replace("#".$this->pathToPPD."#","",$name);
186 /* Intialise some base vars */
187 $AbsoluteSourceName = $this->pathToPPD.$name;
188 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
189 $Vendor = ""; // Vendor
190 $Name = ""; // Name
191 $Modell = ""; // Modell
192 $PrinterName = ""; // The new name of the printer
193 $PPDName = "";
195 /* Force reload of config dialog */
196 $this->ppdConfig = false;
197 $this->selectedPPD['link'] = false;
199 /* Get PPD informations and set vendor / modell / name */
200 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
201 print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));
202 return;
203 }
204 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
205 if($res){
206 $tmp = split("\n",$res);
207 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
208 $Vendor = trim($tmp[0]);
209 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
210 }
212 $PrinterName = $this->cn."-".$Name;
213 $PPDName = $Vendor."/".$PrinterName.".ppd";
215 /* Create the vendors path, if it doesn't exists already */
216 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
217 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
218 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
219 return(false);
220 }
221 }
223 /* Create destination file handle */
224 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
225 if(!$fp){
226 print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
227 return(false);
228 }
230 $str = file_get_contents($AbsoluteSourceName);
231 fputs($fp,$str);
232 @fclose($fp);
234 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
236 $tmp3['link'] =$PPDName;
237 $this->selectedPPD = $tmp3;
238 $this->getPrinterReload();
239 return($PPDName);
240 }
243 /* This function adds a new ppd file to the list of available ppds.
244 All required paths and files will be created
245 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
246 function AddPPD($_PathOnHdd)
247 {
248 /* Check if file exists && is readable */
249 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
250 print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
251 return(false);
252 }
254 /* Reload list to detect changes e.g. a file has been deleted */
255 $this->getPrinterReload();
257 /* Get Description from ppd, & parse out some informations */
258 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
259 if($res){
260 $tmp = split("\n",$res);
261 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
262 $vendor = trim($tmp[0]);
263 $model = trim(preg_replace("/".$vendor."/","",$name));
264 }
266 /* Check if parse was successfull */
267 if(empty($name) || empty($vendor)){
268 print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
269 return(false);
270 }
272 /* Prepare list of ppds */
273 if(!isset($this->ppdList[$vendor])){
274 $this->ppdList[$vendor] = array();
275 }
277 /* Check if this ppd already exists */
278 $found = false;
279 foreach($this->ppdList[$vendor] as $key => $val){
280 if(preg_match("/".$model.".*/i",$key)){
281 $found = true;
282 print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
283 return;
284 }
285 }
287 /* Create the vendors path, if it doesn't exists already */
288 if(!is_dir($this->pathToPPD.$vendor)){
289 if(!(@mkdir($this->pathToPPD.$vendor))){
290 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
291 return(false);
292 }
293 }
295 /* Create ppd file and fill in the source contents */
296 $ppdname = $vendor."/".$name.".ppd";
297 $filename = $this->pathToPPD.$ppdname;
298 $fp = fopen($filename,"w+");
299 $contents = file_get_contents($_PathOnHdd);
301 /* Check file handle & contents */
302 if(!$fp){
303 print_red(sprintf(_("Can't save file '%s'."),$filename));
304 return;
305 }
306 if(empty($contents)){
307 print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
308 return;
309 }
311 /* Fille file with data */
312 fputs($fp,$contents);
313 @fclose($fp);
315 /* Our job is done here */
316 return($ppdname);
317 }
320 /* This function reloads the list of available printers/vendors
321 $this->ppdListHeader
322 Compaq => 1
323 $this->ppdList
324 Compaq => Compaq IJ1200 => name => Compaq IJ1200
325 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
326 ppd => Compaq - Co
327 */
328 function getPrinterReload()
329 {
330 $tmp = $this->ppdManager->getPrinterList(true);
332 $this->ppdListHeader = $this->ppdList = array();
334 /* Sort all available files, and create header (Vendor index) */
335 foreach($tmp as $file=>$ppd){
337 if(preg_match("#".$this->pathToModified."#",$file)) continue;
339 $tmp2 = split("\n",$ppd);
340 if(!isset($this->ppdListHeader[$tmp2[0]])){
341 $this->ppdListHeader[$tmp2[0]]=0;
342 }
343 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
344 $tmp3['link'] =$file;
345 $tmp3['ppd'] =$ppd;
346 $this->ppdListHeader[$tmp2[0]]++;
347 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
348 }
349 }
352 /* Save all options posted from ppd dialog */
353 function save_object()
354 {
355 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
356 return;
357 }
359 foreach($this->ppdConfig as $cat => $obj){
360 foreach($obj as $attr => $attributes){
361 if(isset($_POST[base64_encode($attributes['_name'])])){
362 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
363 }
364 }
365 }
366 }
369 /* Save modified ppd */
370 function save_ppd(){
371 if($this->ppdManager){
372 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
373 }
374 }
376 /* Return selected ppd path, if none is selected then false */
377 function save()
378 {
379 /* return the selected PPD, and in future the selected options too */
380 return($this->pathToModified.$this->selectedPPD['link']);
381 }
383 /* Get Information for a single PPD entry
384 * This will be shown on top of template
385 */
386 function getPPDInformation()
387 {
388 $str = "none";
389 if(!empty($this->selectedPPD)){
390 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
391 }
392 return($str) ;
393 }
395 /* Display all options from the selected ppd file */
396 function generateProperties()
397 {
398 /* Set Headline */
399 $str = "";
400 $feed= "";
402 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
404 /* If ppd exists and is readable */
405 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
407 /* If there is no initial Configuration, load it */
408 if($this->ppdConfig == false){
409 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
410 }
412 /* Create a table */
413 $str .= "<div style='padding-left:30px;'><table summary=''>";
415 /* Input all data to the table */
416 foreach($this->ppdConfig as $cat => $obj){
418 /* Add new category */
419 $str .= "<tr><td colspan='2'>$feed";
420 if ($feed == ""){
421 $feed= "<br>";
422 }
423 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
424 $str .= "</td></tr>";
426 /* Add attributes of the current category */
427 foreach($obj as $attr => $settings){
430 /* Skip all entries beginning with _ */
431 if($attr[0] == "_") continue;
433 /* Prepare data */
434 $values = array();
435 $name = $settings['_name'];
436 $default = $settings['_default'];
437 $type = $settings['_type'];
439 /* Add name to table */
440 $str .= "<tr><td style='padding-left:40px;'>\n";
441 $str .= $name."<br>\n";
442 $str .= "</td><td>\n";
444 /* Get all values */
445 foreach( $settings as $vname => $value){
446 if($vname[0] != "_"){
447 $values[$vname]= $value;
448 }
449 }
451 /* preparing Html output
452 * Supported types are PickOne/Boolean
453 */
455 /* If type is PickOne, create a select box */
456 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
458 $str .= "<select name='".base64_encode($name)."'>\n";
459 foreach($values as $optionKey => $value){
460 $selected = "";
461 if($optionKey == $default){
462 $selected = " selected ";
463 }
464 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
465 }
466 $str .= "</select>\n";
468 }elseif($type == "Boolean"){
470 /* If type is Boolean & no values are given */
471 $str .= "<select name='".base64_encode($name)."'>\n";
472 if($default == "False"){
473 $str .= "<option value='True' >"._("True")."</option>\n";
474 $str .= "<option value='False' selected>"._("False")."</option>\n";
475 }else{
476 $str .= "<option value='True' selected>"._("True")."</option>\n";
477 $str .= "<option value='False' >"._("False")."</option>\n";
478 }
479 $str .= "</select>\n";
481 }else{
482 print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
483 }
484 $str .= "</td></tr>\n";
485 }
486 }
487 $str .= "</table></div>\n";
488 }
489 return($str);
490 }
492 function check(){ return(plugin::check()); }
493 }
494 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
495 ?>