1 <?php
3 class termservice extends plugin
4 {
5 /* CLI vars */
6 var $cli_summary= "Manage terminal service aspects";
7 var $cli_description= "Some longer text\nfor help";
8 var $cli_parameters= array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
10 /* Generic terminal attributes */
11 var $gotoLpdEnable= FALSE;
12 var $gotoXMonitor= "";
13 var $gotoXMethod= "default";
14 var $gotoXdmcpServer= "";
15 var $gotoXDriver= "";
16 var $gotoXResolution= "";
17 var $gotoXColordepth= "";
18 var $gotoXHsync= "";
19 var $gotoXVsync= "";
20 var $gotoXKbModel= "";
21 var $gotoXKbLayout= "";
22 var $gotoXKbVariant= "";
23 var $gotoXMouseType= "";
24 var $gotoXMouseport= "";
25 var $gotoLpdServer= "";
26 var $gotoScannerEnable= "";
27 var $gotoScannerModel= "";
28 var $gotoScannerClients= "";
29 var $gotoScannerBackend= "";
30 var $goFonHardware= "automatic";
32 var $AutoSync = false;
33 var $view_logged = FALSE;
35 /* Needed values and lists */
36 var $ignore_account= TRUE;
37 var $base= "";
38 var $cn= "";
39 var $orig_dn= "";
40 var $XMethods= array();
41 var $XDrivers= array();
42 var $XResolutions= array();
43 var $XColordepths= array();
44 var $XKbModels= array ();
45 var $XKbLayouts= array ();
46 var $XKbVariants= array ();
47 var $MouseTypes= array();
48 var $MousePorts= array();
49 var $hardware_list= array();
50 var $used_hardware= array();
53 /* attribute list for save action */
54 var $attributes= array("gotoLpdEnable", "gotoXMonitor", "gotoXMethod", "gotoXdmcpServer",
55 "gotoXDriver", "gotoXResolution", "gotoXColordepth",
56 "gotoXHsync", "gotoXVsync", "gotoLpdEnable", "gotoLpdServer",
57 "gotoScannerEnable", "gotoScannerModel", "gotoScannerClients",
58 "gotoScannerBackend", "gotoXKbModel", "gotoXKbLayout", "gotoXKbVariant",
59 "gotoXMouseType", "gotoXMouseport", "goFonHardware");
60 var $objectclasses= array("GOhard");
62 var $is_ogroup = FALSE;
63 var $is_ogroup_member = FALSE;
65 var $selected_xdmcp_servers = array();
66 var $inherited_xdmcp_servers = array();
68 function termservice (&$config, $dn= NULL, $parent= NULL)
69 {
70 plugin::plugin ($config, $dn, $parent);
71 $this->orig_dn= $this->dn;
73 /* Check if we are a part of an ogroup.
74 * In this case, we have to hide all the inherit stuff.
75 */
76 if(isset($parent) && get_class($parent) == "ogroup"){
77 $this->is_ogroup = TRUE;
78 }
80 /* Check if we are member of an object group.
81 */
82 $ldap= $this->config->get_ldap_link();
83 $ldap->cd($this->config->current['BASE']);
84 $ldap->search("(&(objectClass=gotoWorkstationTemplate)(member=".LDAP::prepare4filter($this->dn)."))");
85 if($ldap->count()){
86 $this->is_ogroup_member = TRUE;
87 }
89 /* Get list of available xdrivers */
90 $this->XDrivers = $this->getListOfXDrivers();
92 /* Create a list of available resolutions.
93 */
94 $this->XResolutions= array(
95 "640x480" => "640x480",
96 "800x600" => "800x600",
97 "1024x768" => "1024x768",
98 "1152x864" => "1152x864",
99 "1280x1024" => "1280x1024",
100 "1400x1050" => "1400x1050",
101 "1600x1200" => "1600x1200");
103 if(isset($this->config->data['MAIN']['RESOLUTION_HOOK'])){
104 $file = $this->config->data['MAIN']['RESOLUTION_HOOK'];
105 if(is_readable($file)){
106 $str = file_get_contents($file);
107 $lines = split("\n",$str);
108 foreach($lines as $line){
109 $line = trim($line);
110 if(!empty($line)){
111 $this->XResolutions[$line]=$line;
112 }
113 }
114 }else{
115 print_red(sprintf(_("You have specified an external resolution hook which can't be read, please check the permission of the file '%s'."),$file));
116 }
117 }
119 /* Create a set of selectable color depths
120 */
121 $this->XColordepths= array(
122 "8" => "8 " ._("bit"),
123 "15" => "15 "._("bit"),
124 "16" => "16 "._("bit"),
125 "24" => "24 "._("bit"));
128 /* Create a set of selectable keyboard models
129 */
130 $this->XKbModels = array();
131 foreach(array ("btc9000", "chicony", "compaq", "dell", "dell101", "everex",
132 "flexpro", "geniuscomfy", "hp", "itouch", "jp106", "logicordless",
133 "logiinetnav", "logiinternet", "macintosh", "microsoft",
134 "microsoftpro", "omnikey101", "pc101", "pc102", "pc104",
135 "pc105", "rapidaccess", "rapidaccess2", "winbook") as $type){
136 $this->XKbModels[$type] = $type;
137 }
139 /* Additional values will be extracted from CONFIG_DIR.keyboardLayouts */
140 $this->XKbLayouts = array("de"=> "de","intl" =>"intl","us" =>"us");
141 $this->XKbVariants= array("nodeadkeys"=>"nodeadkeys", "basic"=>"basic");
142 $this->MouseTypes = array("ImPS/2"=>"ImPS/2","PS/2"=>"PS/2", "explorerps/2"=>"explorerps/2",
143 "Microsoft"=>"Microsoft","Logitech"=>"Logitech");
144 $this->MousePorts = array("/dev/ttyS0"=>"/dev/ttyS0",
145 "/dev/ttyS1"=>"/dev/ttyS1","/dev/psaux"=>"/dev/psaux",
146 "/dev/input/mice"=>"/dev/input/mice");
149 /* Try to read additional keyboard layouts
150 */
151 if(file_exists(CONFIG_DIR."/keyboardLayouts")){
152 if(is_readable(CONFIG_DIR."/keyboardLayouts")){
153 $str = file_get_contents(CONFIG_DIR."/keyboardLayouts");
154 $tmp = split("\n",$str);
155 foreach($tmp as $entry){
156 if((!empty($entry)) && (!preg_match("/^#/",$entry))){
157 $entry = trim($entry);
158 $tmp2 = split ("\:",$entry);
159 $la = trim($tmp2[0]); // What would be saved to ldap
160 $da = trim($tmp2[1]); // This wis displayed in the listbox
161 $this->XKbLayouts [ $la] = $da;
162 }
163 }
164 }
165 }
167 /* Terminal server methods
168 */
169 if($this->is_ogroup_member){
170 $this->XMethods["default"]= _("inherited");
171 }
172 $this->XMethods["xdmcp"] = _("XDMCP");
173 $this->XMethods["ldm"] = _("LDM");
174 $this->XMethods["rdp"] = _("Windows RDP");
175 $this->XMethods["citrix"] = _("ICA client");
177 /* Get selected gotoXdmcpServer
178 */
179 $this->selected_xdmcp_servers = array();
180 if(isset($this->attrs['gotoXdmcpServer'])){
181 for($i = 0 ; $i < $this->attrs['gotoXdmcpServer']['count'] ; $i++){
182 $this->selected_xdmcp_servers[] = $this->attrs['gotoXdmcpServer'][$i];
183 }
184 }
186 /* Load phone hardware list
187 */
188 $tmp = get_sub_list("(objectClass=goFonHardware)","",array(get_ou("phoneou")),
189 $this->config->current['BASE'],array("cn","description"), GL_NO_ACL_CHECK);
190 foreach($tmp as $attrs){
191 $cn= $attrs['cn'][0];
192 $description= "";
193 if (isset($attrs['description'])){
194 $description= " - ".$attrs['description'][0];
195 }
196 $this->hardware_list[$cn]= "$cn$description";
197 }
198 $this->hardware_list["automatic"]= _("automatic");
199 ksort($this->hardware_list);
201 /* These departments may contain objects that have
202 goFonHardware set.
203 */
204 $deps_a = array(
205 get_people_ou(),
206 get_ou("ogroupou"),
207 get_ou("serverou"),
208 get_ou("terminalou"),
209 get_ou("workstationou"),
210 get_ou("printerou"),
211 get_ou("componentou"),
212 get_ou("phoneou"));
214 $tmp = get_sub_list("(goFonHardware=*)","",$deps_a,$this->config->current['BASE'],
215 array('cn','dn','goFonHardware'),GL_NO_ACL_CHECK);
216 foreach($tmp as $attrs){
217 $cn = $attrs['goFonHardware'][0];
218 if(isset($this->hardware_list[$cn])){
219 $this->used_hardware[$cn]= $cn;
220 }
221 }
223 /* Convert gotoLpdEnable
224 */
225 $this->gotoLpdEnable= preg_match("/yes/i",$this->gotoLpdEnable);
227 /* Load hardware list */
228 $ldap= $this->config->get_ldap_link();
229 $ldap->cd($this->config->current['BASE']);
230 $map= array(
231 "gotoXResolution",
232 "gotoXColordepth",
233 "gotoXKbModel",
234 "gotoXKbLayout",
235 # "gotoXDriver",
236 "gotoXdmcpServer",
237 "gotoXKbVariant",
238 "gotoXMouseType",
239 "gotoXMethod",
240 "gotoXMouseport");
241 $ldap->search("(&(objectClass=gotoWorkstationTemplate)(member=".LDAP::prepare4filter($this->dn)."))",$map);
242 if ($ldap->count() == 1){
243 $attrs= $ldap->fetch();
244 foreach ($map as $name){
245 if (!isset($attrs[$name][0])){
246 continue;
247 }
249 switch ($name){
250 # case 'gotoXDriver':
251 # $this->XDrivers = array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XDrivers;
252 # break;
253 case 'gotoXMethod':
254 $this->XMethods = array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XMethods;
255 if(isset($attrs['gotoXdmcpServer'])){
256 for($i = 0 ; $i < $attrs['gotoXdmcpServer']['count'] ; $i++){
257 $this->inherited_xdmcp_servers[] = $attrs['gotoXdmcpServer'][$i];
258 }
259 }
260 break;
261 case 'gotoXResolution':
262 $this->XResolutions= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XResolutions;
263 break;
264 case 'gotoXColordepth':
265 $this->XColordepths= array('default' => _("inherited").' ['.$attrs[$name][0].' '._('Bit').']') + $this->XColordepths;
266 break;
267 case 'gotoXKbModel':
268 $this->XKbModels= array('default' => _("inherited").' ['.$attrs[$name][0].']') + $this->XKbModels;
269 break;
270 case 'gotoXKbLayout':
271 $this->XKbLayouts= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XKbLayouts;
272 break;
273 case 'gotoXKbVariant':
274 $this->XKbVariants= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XKbVariants;
275 break;
276 case 'gotoXMouseType':
277 $this->MouseTypes= array('AUTO' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->MouseTypes;
278 break;
279 case 'gotoXMouseport':
280 $this->MousePorts= array('AUTO' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->MousePorts;
281 break;
282 }
283 }
284 }
286 if(preg_match("/\+/",$this->gotoXHsync)){
287 $this->AutoSync = true;
288 $this->gotoXHsync = preg_replace("/\+/","-",$this->gotoXHsync);
289 $this->gotoXVsync = preg_replace("/\+/","-",$this->gotoXVsync);
290 }
291 }
294 function execute()
295 {
296 /* Call parent execute */
297 plugin::execute();
299 if($this->is_account && !$this->view_logged){
300 $this->view_logged = TRUE;
301 new log("view","terminal/".get_class($this),$this->dn);
302 }
304 /* Do we need to flip is_account state? */
305 if (isset($_POST['modify_state'])){
306 $this->is_account= !$this->is_account;
307 }
309 /* Do we represent a valid terminal? */
310 if (!$this->is_account && $this->parent === NULL){
311 $display= "<img alt=\"\" src=\"images/stop.png\" align=\"middle\"> <b>".
312 _("This 'dn' has no terminal features.")."</b>";
313 return ($display);
314 }
316 /* Show main page */
317 $smarty= get_smarty();
319 /* Assign acls */
320 $tmp= $this->plInfo();
321 foreach($tmp['plProvidedAcls'] as $name => $translation){
322 $smarty->assign($name."ACL",$this->getacl($name));
323 }
325 if(isset($_POST['gotoXdmcpServer_add']) && isset($_POST['XdmcpAddServer'])){
326 if(!in_array($_POST['gotoXdmcpServer_add'],$this->selected_xdmcp_servers)){
327 $this->selected_xdmcp_servers[] = $_POST['gotoXdmcpServer_add'];
328 }
329 }
331 if(isset($_POST['selected_xdmcp_servers']) && isset($_POST['XdmcpDelServer'])){
332 $tmp = array();
333 foreach($this->selected_xdmcp_servers as $name){
334 if(!in_array($name,$_POST['selected_xdmcp_servers'])){
335 $tmp[] = $name;
336 }
337 }
338 $this->selected_xdmcp_servers = $tmp;
339 }
341 /* Arrays */
342 foreach(array("XMethods", "XDrivers", "XResolutions", "XColordepths",
343 "XKbModels","XKbVariants","MouseTypes", "MousePorts") as $val){
344 $smarty->assign("$val", $this->$val);
345 }
346 $smarty->assign("XKbLayouts", $this->XKbLayouts);
347 $smarty->assign("XKbLayoutKeys",array_flip($this->XKbLayouts));
348 $smarty->assign("nfsservers", $this->config->data['SERVERS']['NFS']);
351 /* Create a list of useable servers for the currently selected
352 * connection type.
353 */
354 $xdmcp_types = $this->config->data['SERVERS']['TERMINAL_SESSION_TYPES'];
355 $available_servers = array();
356 foreach($xdmcp_types as $servername =>$supported_types){
357 if(in_array(strtoupper($this->gotoXMethod),$supported_types)){
358 $available_servers[] = $servername;
359 }
360 }
362 /* Append additional information to invalid server selections.
363 */
364 $tmp = array();
365 foreach($this->selected_xdmcp_servers as $server){
366 if(in_array($server,$available_servers)){
367 $tmp[$server] = $server;
368 }else{
369 $tmp[$server] = $server." - "._("Unsupported");
370 }
371 }
373 /* Remove already selected servers from available list.
374 */
375 foreach($available_servers as $key => $server){
376 if(isset($tmp[$server])){
377 unset($available_servers[$key]);
378 }
379 }
381 $smarty->assign("selected_xdmcp_servers", $tmp);
382 $smarty->assign("inherited_xdmcp_servers", $this->inherited_xdmcp_servers);
383 $smarty->assign("available_xdmcp_servers", $available_servers);
385 /* Variables - select */
386 foreach(array("gotoXMethod","gotoXDriver", "gotoXResolution", "gotoXColordepth",
387 "gotoLpdServer", "gotoXKbModel", "gotoXKbLayout",
388 "gotoXKbVariant", "gotoXMouseType", "gotoXMouseport") as $val){
390 $smarty->assign($val."_select", $this->$val);
391 }
393 /* Variables */
394 foreach(array("gotoXHsync", "gotoXVsync") as $val){
395 $smarty->assign($val, $this->$val);
396 }
397 $smarty->assign("staticAddress", "");
399 /* Checkboxes */
400 foreach(array("gotoLpdEnable", "gotoScannerEnable") as $val){
401 if ($this->$val == TRUE) {
402 $smarty->assign("$val", "checked");
403 } else {
404 $smarty->assign("$val", "");
405 }
406 }
408 /* Phone stuff */
409 $smarty->assign ("goFonHardware", $this->goFonHardware);
410 $hl= "<select size=\"1\" name=\"goFonHardware\" title=\"".
411 _("Choose the phone located at the current terminal")."\" >\n";
412 foreach ($this->hardware_list as $cn => $description){
413 if ($cn == $this->goFonHardware){
414 $selected= "selected";
415 } else {
416 $selected= "";
417 }
418 if (isset($this->used_hardware[$cn])){
419 $color= "style=\"color:#A0A0A0\"";
420 } else {
421 $color= "";
422 }
423 $hl.= " <option $color label=\"$cn\" value=\"$cn\" $selected>$description</option>\n";
424 }
425 $hl.= "</select>\n";
426 $smarty->assign ("hardware_list", $hl);
427 $smarty->assign ("gotoXMonitor", $this->gotoXMonitor);
429 $smarty->assign("AutoSyncACL",$this->getacl("AutoSync"));
431 $smarty->assign("AutoSyncCHK"," ");
432 if($this->AutoSync){
433 $smarty->assign("AutoSyncCHK"," checked ");
434 $smarty->assign("gotoXVsyncACL", preg_replace("/w/","",$this->getacl("gotoXVsync")));
435 $smarty->assign("gotoXHsyncACL", preg_replace("/w/","",$this->getacl("gotoXHsync")));
436 }
438 /* Show main page */
439 return($smarty->fetch (get_template_path('terminalService.tpl', TRUE,dirname(__FILE__))));
440 }
442 function remove_from_parent()
443 {
444 new log("remove","terminal/".get_class($this),$this->dn,array_keys($this->attrs));
445 $this->handle_post_events("remove");
447 plugin::remove_from_parent();
448 $ldap = $this->config->get_ldap_link();
449 $ldap->cd($this->dn);
450 $ldap->modify($this->attrs);
451 show_ldap_error($ldap->get_error(),_("Could not remove terminal service."));
452 }
455 /* Save data to object */
456 function save_object()
457 {
458 plugin::save_object();
460 /* Save checkbox state */
461 if (isset ($_POST['gotoXMethod'])){
462 foreach (array("gotoLpdEnable", "gotoScannerEnable") as $val){
464 if($this->acl_is_writeable($val)){
465 if (!isset ($_POST["$val"])){
466 $this->$val= FALSE;
467 } else {
468 $this->$val= TRUE;
469 }
470 }
471 }
472 }
474 if(isset($_POST['gotoXDriver'])){
475 if(isset($_POST['AutoSync'])){
476 $this->AutoSync = true;
477 }else{
478 $this->AutoSync = false;
479 }
480 }
482 /* Default entries can use blank hsync/vsync entries */
483 if ($this->dn != "" && $this->cn != "default" && $this->cn != "default"){
485 /* But only if no auto sync is enabled... */
486 if (!$this->AutoSync){
488 /* Check vsync for correct usage */
489 $val= preg_replace ("/\s/", "", $this->gotoXVsync);
490 if (!preg_match ("/^\d+(\.\d+)?([-]\d+(\.\d+)?)?$/", $val) && $this->acl_is_writeable("gotoXVsync")){
492 $message[]= _("Please specify a valid VSync range.");
493 } elseif ($this->acl_is_writeable("gotoXVsync")){
494 list($v1,$v2)= preg_split ("/[-+]/", $val);
495 if ($v2 != ""){
496 if ($v1 > $v2){
497 $message[]= _("Please specify a valid VSync range.");
498 }
499 }
500 }
502 /* Check hsync for correct usage */
503 $val= preg_replace ("/\s/", "", $this->gotoXHsync);
504 if (!preg_match ("/^\d+(\.\d+)?([-]\d+(\.\d+)?)?$/", $val) && $this->acl_is_writeable("gotoXHsync")){
506 $message[]= _("Please specify a valid HSync range.");
507 } elseif ($this->acl_is_writeable("gotoXHsync")){
508 list($v1,$v2)= preg_split ("/[-+]/", $val);
509 if ($v2 != ""){
510 if ($v1 > $v2){
511 $message[]= _("Please specify a valid HSync range.");
512 }
513 }
514 }
515 }
516 }
517 }
520 /* Check supplied data */
521 function check()
522 {
523 /* Call common method to give check the hook */
524 $message= plugin::check();
526 if($this->gotoXMethod != "default"){
527 $xdmcp_types = $this->config->data['SERVERS']['TERMINAL_SESSION_TYPES'];
528 $available_servers = array();
529 foreach($xdmcp_types as $servername =>$supported_types){
530 if(in_array(strtoupper($this->gotoXMethod),$supported_types)){
531 $available_servers[] = $servername;
532 }
533 }
534 foreach($this->selected_xdmcp_servers as $server){
535 if(!in_array($server,$available_servers)){
536 $message[] = _("Remote desktop settings contains servers that do not support the selected connection method.");
537 break;
538 }
539 }
540 }
542 return ($message);
543 }
546 /* Save to LDAP */
547 function save()
548 {
549 /* Convert to string */
550 $this->gotoLpdEnable= $this->gotoLpdEnable?"Yes":"No";
552 if($this->is_ogroup){
553 $this->objectclasses = array("gotoWorkstationTemplate");
554 }else{
555 $this->objectclasses = array("GOhard");
556 }
558 plugin::save();
560 /* Strip out 'default' values */
561 foreach(array("gotoXMethod","gotoXDriver", "gotoXResolution", "gotoXColordepth",
562 "gotoLpdServer", "gotoXKbModel", "gotoXKbLayout",
563 "gotoXKbVariant", "gotoXMouseType", "gotoXMouseport") as $val){
565 if ($this->attrs[$val] == "default"){
566 $this->attrs[$val]= array();
567 }
568 }
570 if($this->gotoXMethod == "default"){
571 $this->attrs['gotoXdmcpServer'] = array();
572 $this->attrs['gotoXMethod'] = array();
573 }else{
574 $this->attrs['gotoXdmcpServer'] = array_values($this->selected_xdmcp_servers);
575 }
578 if($this->AutoSync){
579 $this->attrs['gotoXHsync'] = "30+55";
580 $this->attrs['gotoXVsync'] = "50+70";
581 }
583 /* Write back to ldap */
584 $ldap= $this->config->get_ldap_link();
585 $ldap->cd($this->dn);
586 $this->cleanup();
587 $ldap->modify ($this->attrs);
588 new log("modify","terminal/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
590 show_ldap_error($ldap->get_error(), sprintf(_("Saving of object system terminal/service with dn '%s' failed."),$this->dn));
591 $this->handle_post_events("modify");
592 }
595 function getListOfXDrivers()
596 {
597 $drivers = array("default" => "["._("unknown")."]");
599 /* Generate a list of xdrivers from CONFIG_DIR/xdrivers */
600 if (file_exists(CONFIG_DIR.'/xdrivers')){
601 $xdrivers = file (CONFIG_DIR.'/xdrivers');
602 foreach ($xdrivers as $line){
603 if (!preg_match ("/^#/", $line)){
604 $drivers[]= trim($line);
605 }
606 }
607 } else {
608 foreach( array(
609 "ati", "atimisc", "chips", "cirrus", "cyrix", "fbdev", "fglrx",
610 "i128", "i740", "i810", "imstt", "mga", "neomagic", "newport", "nsc", "nv", "nvidia",
611 "r128", "radeon", "rendition", "s3", "s3virge", "savage", "siliconmotion",
612 "sis", "tdfx", "tga", "trident", "tseng", "vesa", "vga", "vmware") as $driver){
613 $drivers[] = $driver;
614 }
615 }
616 return($drivers);
617 }
620 /* Return plugin informations for acl handling */
621 static function plInfo()
622 {
623 return (array(
624 "plShortName" => _("Service"),
625 "plDescription" => _("Terminal service"),
626 "plSelfModify" => FALSE,
627 "plDepends" => array(),
628 "plPriority" => 3,
629 "plSection" => array("administration"),
630 "plCategory" => array("terminal"),
632 "plProvidedAcls"=> array(
633 "gotoXMonitor" => _("Monitor"),
634 "gotoXMethod" => _("Method"),
635 "gotoXdmcpServer" => _("Remote desktop"),
636 "gotoXDriver" => _("Gfx driver"),
637 "gotoXResolution" => _("Gfx resolution"),
638 "gotoXColordepth" => _("Gfx color depth"),
639 "gotoXHsync" => _("Hsync"),
640 "gotoXVsync" => _("Vsync"),
641 "AutoSync" => _("Auto-Sync"),
642 "gotoLpdEnable" => _("Printer service enabled"),
643 "gotoLpdServer" => _("Spool server"),
644 "gotoScannerEnable" => _("Scanner enabled"),
645 "gotoXKbModel" => _("Keyboard model"),
646 "gotoXKbLayout" => _("Keyboard layout"),
647 "gotoXKbVariant" => _("Keyboard variant"),
648 "gotoXMouseType" => _("Mouse type"),
649 "gotoXMouseport" => _("Mouse port"),
650 "goFonHardware" => _("Telephone hardware"))
651 ));
652 }
653 }
655 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
656 ?>