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,".
100 " can't read/write any ppd informations."),$path));
101 /* Print out template */
102 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
103 return($display);
104 }
105 }
107 // PPD selection / upload / dialog handling
109 /* Is there a new PPD file uploaded ? */
110 if((isset($_FILES['NewPPDFile']))&&(isset($_POST['SubmitNewPPDFile']))){
111 $file = ($_FILES['NewPPDFile']);
112 if($file['size'] != 0 ){
113 if($name = $this->AddPPD($file['tmp_name'])){
114 $this->SelectPPD($name);
115 }
116 }else{
117 print_red(_("Please specify a valid ppd file."));
118 }
119 }
121 /* Open a dialog that allow us to select different PPDs */
122 if(isset($_POST['SelectPPD'])){
123 $this->dialog= new printerPPDSelectionDialog($this->config,$this->dn,$this->ppdList,$this->ppdListHeader,$this->selectedPPD);
124 }
126 /* The selection dialog fpr PPDs is canceled */
127 if(isset($_POST['ClosePPDSelection'])){
128 unset($this->dialog);
129 $this->dialog=NULL;
130 }
132 /* Div Selection */
133 if((isset($_GET['act']))&&($_GET['act']=="use")){
134 $this->SelectPPD(base64_decode($_GET['id']));
135 unset($this->dialog);
136 $this->dialog=NULL;
138 }
140 /* if a dialog is open, print the dialog instead of this class */
141 if($this->dialog!=NULL){
142 $display = $this->dialog->execute();
143 return($display);
144 }
146 // ENDE PPD selection / upload / dialog handling
148 /* Give smarty the information it needs */
149 $smarty->assign("ppdString" ,$this->getPPDInformation());
150 $tmp= $this->generateProperties();
151 if ($tmp == ""){
152 $smarty->assign("showOptions", 0);
153 } else {
154 $smarty->assign("showOptions", 1);
155 $smarty->assign("properties",$this->generateProperties());
156 }
158 /* Print out template */
159 $display.= $smarty->fetch(get_template_path('printerPPDDialog.tpl', TRUE,dirname(__FILE__)));
160 return($display);
161 }
164 /* Select PPD */
165 function SelectPPD($name)
166 {
167 /* Replace base path we don't need it here
168 The path we need looks like this : "/Vendor/ModellName.ppd";
169 thats all */
170 $name = preg_replace("#".$this->pathToPPD."#","",$name);
172 /* Intialise some base vars */
173 $AbsoluteSourceName = $this->pathToPPD.$name;
174 $AbsoluteDestinationPath = $this->pathToPPD.$this->pathToModified;
175 $Vendor = ""; // Vendor
176 $Name = ""; // Name
177 $Modell = ""; // Modell
178 $PrinterName = ""; // The new name of the printer
179 $PPDName = "";
181 /* Force reload of config dialog */
182 $this->ppdConfig = false;
183 $this->selectedPPD['link'] = false;
185 /* Get PPD informations and set vendor / modell / name */
186 if((!file_exists($AbsoluteSourceName)) || (!is_readable($AbsoluteSourceName))){
187 print_red(sprintf(_("Can't select PPD file '%s', the file is not readable"),$AbsoluteSourceName));
188 return;
189 }
190 $res = $this->ppdManager->loadDescription($AbsoluteSourceName);
191 if($res){
192 $tmp = split("\n",$res);
193 $Name = trim(preg_replace("/^\-/","",trim($tmp[1])));
194 $Vendor = trim($tmp[0]);
195 $Model = trim(preg_replace("/".$Vendor."/","",$Name));
196 }
198 $PrinterName = $this->cn."-".$Name;
199 $PPDName = $Vendor."/".$PrinterName.".ppd";
201 /* Create the vendors path, if it doesn't exists already */
202 if(!is_dir($AbsoluteDestinationPath.$Vendor)){
203 if(!(@mkdir($AbsoluteDestinationPath.$Vendor))){
204 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$AbsoluteDestinationPath.$Vendor));
205 return(false);
206 }
207 }
209 /* Create destination file handle */
210 $fp = @fopen($AbsoluteDestinationPath.$PPDName,"w+");
211 if(!$fp){
212 print_red(sprintf(_("Can't create file '%s' to store modifed ppd informations."),$AbsoluteDestinationPath.$PPDName));
213 return(false);
214 }
216 $str = file_get_contents($AbsoluteSourceName);
217 fputs($fp,$str);
218 @fclose($fp);
220 //$this->ppdManager->updateAttribute($filename,"NO_SECTION","ModelName",$printerName);
222 $tmp3['link'] =$PPDName;
223 $this->selectedPPD = $tmp3;
224 $this->getPrinterReload();
225 return($PPDName);
226 }
229 /* This function adds a new ppd file to the list of available ppds.
230 All required paths and files will be created
231 $_PathOnHdd e.g. = /tmp/PHP_tmpfile213452 */
232 function AddPPD($_PathOnHdd)
233 {
234 /* Check if file exists && is readable */
235 if((!is_file($_PathOnHdd)) || (!is_readable($_PathOnHdd))){
236 print_red(sprintf(_("Can't add new ppd file, the source file '%s' is not accessible."),$_PathOnHdd));
237 return(false);
238 }
240 /* Reload list to detect changes e.g. a file has been deleted */
241 $this->getPrinterReload();
243 /* Get Description from ppd, & parse out some informations */
244 $res = @$this->ppdManager->loadDescription($_PathOnHdd);
245 if($res){
246 $tmp = split("\n",$res);
247 $name = trim(preg_replace("/^\-/","",trim($tmp[1])));
248 $vendor = trim($tmp[0]);
249 $model = trim(preg_replace("/".$vendor."/","",$name));
250 }
252 /* Check if parse was successfull */
253 if(empty($name) || empty($vendor)){
254 print_red(sprintf(_("The given ppd file '%s' seams to be invalid, can't get any modell or vendor informations."),$_PathOnHdd));
255 return(false);
256 }
258 /* Prepare list of ppds */
259 if(!isset($this->ppdList[$vendor])){
260 $this->ppdList[$vendor] = array();
261 }
263 /* Check if this ppd already exists */
264 $found = false;
265 foreach($this->ppdList[$vendor] as $key => $val){
266 if(preg_match("/".$model.".*/i",$key)){
267 $found = true;
268 print_red(sprintf(_("There is already a ppd file for this kind of printer.")));
269 return;
270 }
271 }
273 /* Create the vendors path, if it doesn't exists already */
274 if(!is_dir($this->pathToPPD.$vendor)){
275 if(!(@mkdir($this->pathToPPD.$vendor))){
276 print_red(sprintf(_("Can't create folder '%s' for the uploaded ppd file."),$this->pathToPPD.$vendor));
277 return(false);
278 }
279 }
281 /* Create ppd file and fill in the source contents */
282 $ppdname = $vendor."/".$name.".ppd";
283 $filename = $this->pathToPPD.$ppdname;
284 $fp = fopen($filename,"w+");
285 $contents = file_get_contents($_PathOnHdd);
287 /* Check file handle & contents */
288 if(!$fp){
289 print_red(sprintf(_("Can't save file '%s'."),$filename));
290 return;
291 }
292 if(empty($contents)){
293 print_red(_("Uploaded ppd file is empty, can't create new ppd file."));
294 return;
295 }
297 /* Fille file with data */
298 fputs($fp,$contents);
299 @fclose($fp);
301 /* Our job is done here */
302 return($ppdname);
303 }
306 /* This function reloads the list of available printers/vendors
307 $this->ppdListHeader
308 Compaq => 1
309 $this->ppdList
310 Compaq => Compaq IJ1200 => name => Compaq IJ1200
311 link => /var/spool/ppd/Compaq/Compaq-J1200.ppd
312 ppd => Compaq - Co
313 */
314 function getPrinterReload()
315 {
316 if(is_readable($this->pathToPPD)){
317 $tmp = $this->ppdManager->getPrinterList(true);
319 $this->ppdListHeader = $this->ppdList = array();
321 /* Sort all available files, and create header (Vendor index) */
322 foreach($tmp as $file=>$ppd){
324 if(preg_match("#".$this->pathToModified."#",$file)) continue;
326 $tmp2 = split("\n",$ppd);
327 if(!isset($this->ppdListHeader[$tmp2[0]])){
328 $this->ppdListHeader[$tmp2[0]]=0;
329 }
330 $tmp3['name'] =preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2]);
331 $tmp3['link'] =$file;
332 $tmp3['ppd'] =$ppd;
333 $this->ppdListHeader[$tmp2[0]]++;
334 $this->ppdList[$tmp2[0]][preg_replace("/^ -/","",$tmp2[1]." - ".$tmp2[2])]=$tmp3;
335 }
336 }
337 }
340 /* Save all options posted from ppd dialog */
341 function save_object()
342 {
343 if(!((isset($_POST['PPDDisSubmitted'])) && (is_array($this->ppdConfig)))){
344 return;
345 }
347 foreach($this->ppdConfig as $cat => $obj){
348 foreach($obj as $attr => $attributes){
349 if(isset($_POST[base64_encode($attributes['_name'])])){
350 $this->ppdConfig[$cat][$attr]['_default'] = $_POST[base64_encode($attributes['_name'])];
351 }
352 }
353 }
354 }
357 /* Save modified ppd */
358 function save_ppd(){
359 if($this->ppdManager){
360 $this->ppdManager->saveProperties($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'],$this->ppdConfig);
361 }
362 }
365 /* Return selected ppd path, if none is selected then false */
366 function save()
367 {
368 /* return the selected PPD, and in future the selected options too */
369 return($this->pathToModified.$this->selectedPPD['link']);
370 }
373 /* Get Information for a single PPD entry
374 * This will be shown on top of template
375 */
376 function getPPDInformation()
377 {
378 $str = "none";
379 if(!empty($this->selectedPPD)){
380 $str = $this->ppdManager->loadDescription($this->pathToPPD.$this->pathToModified.$this->selectedPPD['link']);
381 }
382 return($str) ;
383 }
386 /* Display all options from the selected ppd file */
387 function generateProperties()
388 {
389 /* Set Headline */
390 $str = "";
391 $feed= "";
393 $s_ppd = $this->pathToPPD.$this->pathToModified.$this->selectedPPD['link'];
395 /* If ppd exists and is readable */
396 if((!empty($this->selectedPPD['link']))&&(file_exists($s_ppd))){
398 /* If there is no initial Configuration, load it */
399 if($this->ppdConfig == false){
400 $this->ppdConfig = $this->ppdManager->loadProperties($s_ppd);
401 }
403 /* Create a table */
404 $str .= "<div style='padding-left:30px;'><table summary=''>";
406 /* Input all data to the table */
407 foreach($this->ppdConfig as $cat => $obj){
409 /* Add new category */
410 $str .= "<tr><td colspan='2'>$feed";
411 if ($feed == ""){
412 $feed= "<br>";
413 }
414 $str .= "<b>"._("Section")." '".$cat."' </b><br>";
415 $str .= "</td></tr>";
417 /* Add attributes of the current category */
418 foreach($obj as $attr => $settings){
420 /* Skip all entries beginning with _ */
421 if($attr[0] == "_") continue;
423 /* Prepare data */
424 $values = array();
425 $name = $settings['_name'];
426 $default = $settings['_default'];
427 $type = $settings['_type'];
429 /* Add name to table */
430 $str .= "<tr><td style='padding-left:40px;'>\n";
431 $str .= $name."<br>\n";
432 $str .= "</td><td>\n";
434 /* Get all values */
435 foreach( $settings as $vname => $value){
436 if($vname[0] != "_"){
437 $values[$vname]= $value;
438 }
439 }
441 /* preparing Html output
442 * Supported types are PickOne/Boolean
443 */
445 /* If type is PickOne, create a select box */
446 if(($type == "PickOne")||(($type=="Boolean")&&(count($values)>1))){
448 $str .= "<select name='".base64_encode($name)."'>\n";
449 foreach($values as $optionKey => $value){
450 $selected = "";
451 if($optionKey == $default){
452 $selected = " selected ";
453 }
454 $str .= "<option value='".$optionKey."' ".$selected.">".$value."</option>\n";
455 }
456 $str .= "</select>\n";
458 }elseif($type == "Boolean"){
460 /* If type is Boolean & no values are given */
461 $str .= "<select name='".base64_encode($name)."'>\n";
462 if($default == "False"){
463 $str .= "<option value='True' >"._("True")."</option>\n";
464 $str .= "<option value='False' selected>"._("False")."</option>\n";
465 }else{
466 $str .= "<option value='True' selected>"._("True")."</option>\n";
467 $str .= "<option value='False' >"._("False")."</option>\n";
468 }
469 $str .= "</select>\n";
471 }else{
472 print_red(sprintf(_("Unsupported ppd type '%s' used for '%s' "),$type,$name));
473 }
474 $str .= "</td></tr>\n";
475 }
476 }
477 $str .= "</table></div>\n";
478 }
479 return($str);
480 }
482 function check(){ return(plugin::check()); }
483 }
484 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
485 ?>