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_ou("ogroupou"),
206 get_ou("serverou"),
207 get_ou("terminalou"),
208 get_ou("workstationou"),
209 get_ou("printerou"),
210 get_ou("componentou"),
211 get_ou("phoneou"));
213 $tmp = get_sub_list("(goFonHardware=*)","",$deps_a,$this->config->current['BASE'],
214 array('cn','dn','goFonHardware'),GL_NO_ACL_CHECK);
215 foreach($tmp as $attrs){
216 $cn = $attrs['goFonHardware'][0];
217 if(isset($this->hardware_list[$cn])){
218 $this->used_hardware[$cn]= $cn;
219 }
220 }
222 /* Convert gotoLpdEnable
223 */
224 $this->gotoLpdEnable= preg_match("/yes/i",$this->gotoLpdEnable);
226 /* Load hardware list */
227 $ldap= $this->config->get_ldap_link();
228 $ldap->cd($this->config->current['BASE']);
229 $map= array(
230 "gotoXResolution",
231 "gotoXColordepth",
232 "gotoXKbModel",
233 "gotoXKbLayout",
234 # "gotoXDriver",
235 "gotoXdmcpServer",
236 "gotoXKbVariant",
237 "gotoXMouseType",
238 "gotoXMethod",
239 "gotoXMouseport");
240 $ldap->search("(&(objectClass=gotoWorkstationTemplate)(member=".LDAP::prepare4filter($this->dn)."))",$map);
241 if ($ldap->count() == 1){
242 $attrs= $ldap->fetch();
243 foreach ($map as $name){
244 if (!isset($attrs[$name][0])){
245 continue;
246 }
248 switch ($name){
249 # case 'gotoXDriver':
250 # $this->XDrivers = array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XDrivers;
251 # break;
252 case 'gotoXMethod':
253 $this->XMethods = array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XMethods;
254 if(isset($attrs['gotoXdmcpServer'])){
255 for($i = 0 ; $i < $attrs['gotoXdmcpServer']['count'] ; $i++){
256 $this->inherited_xdmcp_servers[] = $attrs['gotoXdmcpServer'][$i];
257 }
258 }
259 break;
260 case 'gotoXResolution':
261 $this->XResolutions= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XResolutions;
262 break;
263 case 'gotoXColordepth':
264 $this->XColordepths= array('default' => _("inherited").' ['.$attrs[$name][0].' '._('Bit').']') + $this->XColordepths;
265 break;
266 case 'gotoXKbModel':
267 $this->XKbModels= array('default' => _("inherited").' ['.$attrs[$name][0].']') + $this->XKbModels;
268 break;
269 case 'gotoXKbLayout':
270 $this->XKbLayouts= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XKbLayouts;
271 break;
272 case 'gotoXKbVariant':
273 $this->XKbVariants= array('default' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->XKbVariants;
274 break;
275 case 'gotoXMouseType':
276 $this->MouseTypes= array('AUTO' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->MouseTypes;
277 break;
278 case 'gotoXMouseport':
279 $this->MousePorts= array('AUTO' => _("inherited").' ['.$attrs[$name][0].']' ) + $this->MousePorts;
280 break;
281 }
282 }
283 }
285 if(preg_match("/\+/",$this->gotoXHsync)){
286 $this->AutoSync = true;
287 $this->gotoXHsync = preg_replace("/\+/","-",$this->gotoXHsync);
288 $this->gotoXVsync = preg_replace("/\+/","-",$this->gotoXVsync);
289 }
290 }
293 function execute()
294 {
295 /* Call parent execute */
296 plugin::execute();
298 if($this->is_account && !$this->view_logged){
299 $this->view_logged = TRUE;
300 new log("view","terminal/".get_class($this),$this->dn);
301 }
303 /* Do we need to flip is_account state? */
304 if (isset($_POST['modify_state'])){
305 $this->is_account= !$this->is_account;
306 }
308 /* Do we represent a valid terminal? */
309 if (!$this->is_account && $this->parent === NULL){
310 $display= "<img alt=\"\" src=\"images/stop.png\" align=\"middle\"> <b>".
311 _("This 'dn' has no terminal features.")."</b>";
312 return ($display);
313 }
315 /* Show main page */
316 $smarty= get_smarty();
318 /* Assign acls */
319 $tmp= $this->plInfo();
320 foreach($tmp['plProvidedAcls'] as $name => $translation){
321 $smarty->assign($name."ACL",$this->getacl($name));
322 }
324 if(isset($_POST['gotoXdmcpServer_add']) && isset($_POST['XdmcpAddServer'])){
325 if(!in_array($_POST['gotoXdmcpServer_add'],$this->selected_xdmcp_servers)){
326 $this->selected_xdmcp_servers[] = $_POST['gotoXdmcpServer_add'];
327 }
328 }
330 if(isset($_POST['selected_xdmcp_servers']) && isset($_POST['XdmcpDelServer'])){
331 $tmp = array();
332 foreach($this->selected_xdmcp_servers as $name){
333 if(!in_array($name,$_POST['selected_xdmcp_servers'])){
334 $tmp[] = $name;
335 }
336 }
337 $this->selected_xdmcp_servers = $tmp;
338 }
340 /* Arrays */
341 foreach(array("XMethods", "XDrivers", "XResolutions", "XColordepths",
342 "XKbModels","XKbVariants","MouseTypes", "MousePorts") as $val){
343 $smarty->assign("$val", $this->$val);
344 }
345 $smarty->assign("XKbLayouts", $this->XKbLayouts);
346 $smarty->assign("XKbLayoutKeys",array_flip($this->XKbLayouts));
347 $smarty->assign("nfsservers", $this->config->data['SERVERS']['NFS']);
350 /* Create a list of useable servers for the currently selected
351 * connection type.
352 */
353 $xdmcp_types = $this->config->data['SERVERS']['TERMINAL_SESSION_TYPES'];
354 $available_servers = array();
355 foreach($xdmcp_types as $servername =>$supported_types){
356 if(in_array(strtoupper($this->gotoXMethod),$supported_types)){
357 $available_servers[] = $servername;
358 }
359 }
361 /* Append additional information to invalid server selections.
362 */
363 $tmp = array();
364 foreach($this->selected_xdmcp_servers as $server){
365 if(in_array($server,$available_servers)){
366 $tmp[$server] = $server;
367 }else{
368 $tmp[$server] = $server." - "._("Unsupported");
369 }
370 }
372 /* Remove already selected servers from available list.
373 */
374 foreach($available_servers as $key => $server){
375 if(isset($tmp[$server])){
376 unset($available_servers[$key]);
377 }
378 }
380 $smarty->assign("selected_xdmcp_servers", $tmp);
381 $smarty->assign("inherited_xdmcp_servers", $this->inherited_xdmcp_servers);
382 $smarty->assign("available_xdmcp_servers", $available_servers);
384 /* Variables - select */
385 foreach(array("gotoXMethod","gotoXDriver", "gotoXResolution", "gotoXColordepth",
386 "gotoLpdServer", "gotoXKbModel", "gotoXKbLayout",
387 "gotoXKbVariant", "gotoXMouseType", "gotoXMouseport") as $val){
389 $smarty->assign($val."_select", $this->$val);
390 }
392 /* Variables */
393 foreach(array("gotoXHsync", "gotoXVsync") as $val){
394 $smarty->assign($val, $this->$val);
395 }
396 $smarty->assign("staticAddress", "");
398 /* Checkboxes */
399 foreach(array("gotoLpdEnable", "gotoScannerEnable") as $val){
400 if ($this->$val == TRUE) {
401 $smarty->assign("$val", "checked");
402 } else {
403 $smarty->assign("$val", "");
404 }
405 }
407 /* Phone stuff */
408 $smarty->assign ("goFonHardware", $this->goFonHardware);
409 $hl= "<select size=\"1\" name=\"goFonHardware\" title=\"".
410 _("Choose the phone located at the current terminal")."\" >\n";
411 foreach ($this->hardware_list as $cn => $description){
412 if ($cn == $this->goFonHardware){
413 $selected= "selected";
414 } else {
415 $selected= "";
416 }
417 if (isset($this->used_hardware[$cn])){
418 $color= "style=\"color:#A0A0A0\"";
419 } else {
420 $color= "";
421 }
422 $hl.= " <option $color label=\"$cn\" value=\"$cn\" $selected>$description</option>\n";
423 }
424 $hl.= "</select>\n";
425 $smarty->assign ("hardware_list", $hl);
426 $smarty->assign ("gotoXMonitor", $this->gotoXMonitor);
428 $smarty->assign("AutoSyncACL",$this->getacl("AutoSync"));
430 $smarty->assign("AutoSyncCHK"," ");
431 if($this->AutoSync){
432 $smarty->assign("AutoSyncCHK"," checked ");
433 $smarty->assign("gotoXVsyncACL", preg_replace("/w/","",$this->getacl("gotoXVsync")));
434 $smarty->assign("gotoXHsyncACL", preg_replace("/w/","",$this->getacl("gotoXHsync")));
435 }
437 /* Show main page */
438 return($smarty->fetch (get_template_path('terminalService.tpl', TRUE,dirname(__FILE__))));
439 }
441 function remove_from_parent()
442 {
443 new log("remove","terminal/".get_class($this),$this->dn,array_keys($this->attrs));
444 $this->handle_post_events("remove");
446 plugin::remove_from_parent();
447 $ldap = $this->config->get_ldap_link();
448 $ldap->cd($this->dn);
449 $ldap->modify($this->attrs);
450 show_ldap_error($ldap->get_error(),_("Could not remove terminal service."));
451 }
454 /* Save data to object */
455 function save_object()
456 {
457 plugin::save_object();
459 /* Save checkbox state */
460 if (isset ($_POST['gotoXMethod'])){
461 foreach (array("gotoLpdEnable", "gotoScannerEnable") as $val){
463 if($this->acl_is_writeable($val)){
464 if (!isset ($_POST["$val"])){
465 $this->$val= FALSE;
466 } else {
467 $this->$val= TRUE;
468 }
469 }
470 }
471 }
473 if(isset($_POST['gotoXDriver'])){
474 if(isset($_POST['AutoSync'])){
475 $this->AutoSync = true;
476 }else{
477 $this->AutoSync = false;
478 }
479 }
481 /* Default entries can use blank hsync/vsync entries */
482 if ($this->dn != "" && $this->cn != "default" && $this->cn != "default"){
484 /* But only if no auto sync is enabled... */
485 if (!$this->AutoSync){
487 /* Check vsync for correct usage */
488 $val= preg_replace ("/\s/", "", $this->gotoXVsync);
489 if (!preg_match ("/^\d+(\.\d+)?([-]\d+(\.\d+)?)?$/", $val) && $this->acl_is_writeable("gotoXVsync")){
491 $message[]= _("Please specify a valid VSync range.");
492 } elseif ($this->acl_is_writeable("gotoXVsync")){
493 list($v1,$v2)= preg_split ("/[-+]/", $val);
494 if ($v2 != ""){
495 if ($v1 > $v2){
496 $message[]= _("Please specify a valid VSync range.");
497 }
498 }
499 }
501 /* Check hsync for correct usage */
502 $val= preg_replace ("/\s/", "", $this->gotoXHsync);
503 if (!preg_match ("/^\d+(\.\d+)?([-]\d+(\.\d+)?)?$/", $val) && $this->acl_is_writeable("gotoXHsync")){
505 $message[]= _("Please specify a valid HSync range.");
506 } elseif ($this->acl_is_writeable("gotoXHsync")){
507 list($v1,$v2)= preg_split ("/[-+]/", $val);
508 if ($v2 != ""){
509 if ($v1 > $v2){
510 $message[]= _("Please specify a valid HSync range.");
511 }
512 }
513 }
514 }
515 }
516 }
519 /* Check supplied data */
520 function check()
521 {
522 /* Call common method to give check the hook */
523 $message= plugin::check();
525 if($this->gotoXMethod != "default"){
526 $xdmcp_types = $this->config->data['SERVERS']['TERMINAL_SESSION_TYPES'];
527 $available_servers = array();
528 foreach($xdmcp_types as $servername =>$supported_types){
529 if(in_array(strtoupper($this->gotoXMethod),$supported_types)){
530 $available_servers[] = $servername;
531 }
532 }
533 foreach($this->selected_xdmcp_servers as $server){
534 if(!in_array($server,$available_servers)){
535 $message[] = _("Remote desktop settings contains servers that do not support the selected connection method.");
536 break;
537 }
538 }
539 }
541 return ($message);
542 }
545 /* Save to LDAP */
546 function save()
547 {
548 /* Convert to string */
549 $this->gotoLpdEnable= $this->gotoLpdEnable?"Yes":"No";
551 if($this->is_ogroup){
552 $this->objectclasses = array("gotoWorkstationTemplate");
553 }else{
554 $this->objectclasses = array("GOhard");
555 }
557 plugin::save();
559 /* Strip out 'default' values */
560 foreach(array("gotoXMethod","gotoXDriver", "gotoXResolution", "gotoXColordepth",
561 "gotoLpdServer", "gotoXKbModel", "gotoXKbLayout",
562 "gotoXKbVariant", "gotoXMouseType", "gotoXMouseport") as $val){
564 if ($this->attrs[$val] == "default"){
565 $this->attrs[$val]= array();
566 }
567 }
569 if($this->gotoXMethod == "default"){
570 $this->attrs['gotoXdmcpServer'] = array();
571 $this->attrs['gotoXMethod'] = array();
572 }else{
573 $this->attrs['gotoXdmcpServer'] = array_values($this->selected_xdmcp_servers);
574 }
577 if($this->AutoSync){
578 $this->attrs['gotoXHsync'] = "30+55";
579 $this->attrs['gotoXVsync'] = "50+70";
580 }
582 /* Write back to ldap */
583 $ldap= $this->config->get_ldap_link();
584 $ldap->cd($this->dn);
585 $this->cleanup();
586 $ldap->modify ($this->attrs);
587 new log("modify","terminal/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
589 show_ldap_error($ldap->get_error(), sprintf(_("Saving of object system terminal/service with dn '%s' failed."),$this->dn));
590 $this->handle_post_events("modify");
591 }
594 function getListOfXDrivers()
595 {
596 $drivers = array("default" => "["._("unknown")."]");
598 /* Generate a list of xdrivers from CONFIG_DIR/xdrivers */
599 if (file_exists(CONFIG_DIR.'/xdrivers')){
600 $xdrivers = file (CONFIG_DIR.'/xdrivers');
601 foreach ($xdrivers as $line){
602 if (!preg_match ("/^#/", $line)){
603 $drivers[]= trim($line);
604 }
605 }
606 } else {
607 foreach( array(
608 "ati", "atimisc", "chips", "cirrus", "cyrix", "fbdev", "fglrx",
609 "i128", "i740", "i810", "imstt", "mga", "neomagic", "newport", "nsc", "nv", "nvidia",
610 "r128", "radeon", "rendition", "s3", "s3virge", "savage", "siliconmotion",
611 "sis", "tdfx", "tga", "trident", "tseng", "vesa", "vga", "vmware") as $driver){
612 $drivers[] = $driver;
613 }
614 }
615 return($drivers);
616 }
619 /* Return plugin informations for acl handling */
620 static function plInfo()
621 {
622 return (array(
623 "plShortName" => _("Service"),
624 "plDescription" => _("Terminal service"),
625 "plSelfModify" => FALSE,
626 "plDepends" => array(),
627 "plPriority" => 3,
628 "plSection" => array("administration"),
629 "plCategory" => array("terminal"),
631 "plProvidedAcls"=> array(
632 "gotoXMonitor" => _("Monitor"),
633 "gotoXMethod" => _("Method"),
634 "gotoXdmcpServer" => _("Remote desktop"),
635 "gotoXDriver" => _("Gfx driver"),
636 "gotoXResolution" => _("Gfx resolution"),
637 "gotoXColordepth" => _("Gfx color depth"),
638 "gotoXHsync" => _("Hsync"),
639 "gotoXVsync" => _("Vsync"),
640 "AutoSync" => _("Auto-Sync"),
641 "gotoLpdEnable" => _("Printer service enabled"),
642 "gotoLpdServer" => _("Spool server"),
643 "gotoScannerEnable" => _("Scanner enabled"),
644 "gotoXKbModel" => _("Keyboard model"),
645 "gotoXKbLayout" => _("Keyboard layout"),
646 "gotoXKbVariant" => _("Keyboard variant"),
647 "gotoXMouseType" => _("Mouse type"),
648 "gotoXMouseport" => _("Mouse port"),
649 "goFonHardware" => _("Telephone hardware"))
650 ));
651 }
652 }
654 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
655 ?>