]> git.llucax.com Git - mecon/samurai.git/blob - lib/SAMURAI/HTML/Perfil.php
f447971e24430a2e23b90cb98fa89f6e5d7e4f1f
[mecon/samurai.git] / lib / SAMURAI / HTML / Perfil.php
1 <?php 
2 // vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4 foldmethod=marker textwidth=80:
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2003 The PHP Group                                |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license,      |
9 // | that is bundled with this package in the file LICENSE, and is        |
10 // | available at through the world-wide-web at                           |
11 // | http://www.php.net/license/2_02.txt.                                 |
12 // | If you did not receive a copy of the PHP license and are unable to   |
13 // | obtain it through the world-wide-web, please send a note to          |
14 // | license@php.net so we can mail you a copy immediately.               |
15 // +----------------------------------------------------------------------+
16 // | Created: mar ago 26 13:18:26 ART 2003
17 // | Author:  Martin Marrese <mmarre@mecon.gov.ar>
18 // +----------------------------------------------------------------------+
19 //
20 // $Id$
21 //
22
23 /** \page page_samurai_html_perfil Perfil Embebido
24
25 \section page_samurai_html_perfil_descripcion Descripcion
26     Funcion que sirve para embeber la funcionalidad de los perfiles dentro de
27     los sistemas que asi lo requieran (Es una copia de la funcionalidad de la
28     seccion).
29     Necesita para funcionar que se le pase como parametro la referencia al
30     objeto MECON_Marco que se este utilizando, ademas del identificador del
31     sistema del sistema en el cual se esta trabajando.
32     El funcionamiento es completamente independiente del sistema en el cual se
33     trabaje, no es necesario que se ingrese como seccion o subseccion. De hecho
34     como se ve en el ejemplo solo se embebe una tabla o formulario pero se
35     pueden agregar cosas particulares antes y despues de el.
36     
37     \note Trabaja con variables de sesion asi que es necesario que antes de llamar a
38     esta funcion se haya realizado un session_start() (Por ejemplo en el prepend).
39
40 \section page_samurai_html_perfil_funcionamiento Funcionamiento
41     Al ser una copia de la seccion de Samurai, los permisos y validaciones que
42     se realizan en esta funcion son las mismas que se realizan en Samurai.
43
44     \subsection page_samurai_html_perfil_funcionamiento_validaciones Validaciones
45         Se realizan las siguientes validaciones:
46             - Los nombres de los perfiles nuevos deben ser distintos. 
47             - Los espacios entre las palabras que componen el nombre de un
48               perfil son eliminados. Ej: Agregar&nbsp;&nbsp;&nbsp;&nbsp;Usuario
49               se cambia por Agregar Usuario.
50             - Es obligatorio que los perfiles contengan al menos un permiso.
51             - No puede haber dos perfiles con los mismos permisos.
52             - No se pueden borrar perfiles que esten asociados a usuarios.
53
54 \section page_samurai_html_perfil_ejemplo Ejemplo
55     La utilizacion de perfiles embebido no genera condiciones, queda a criterio
56     del desarrollador incluir esta funcionalidad en el lugar que quiera.
57
58     De esta manera se agrega la funcionalidad:
59     \code
60     include 'SAMURAI/HTML/Perfil.php';
61
62     SAMURAI_HTML_Perfil($MARCO, $ID_SISTEMA);
63     \endcode
64     
65     En donde $MARCO es el objeto MECON_Marco que utiliza el sistema y
66     $ID_SISTEMA es el identificador numerico del sistema en el cual se esta
67     trabajando.
68
69     Antes o despues de esto se pueden agregar componentes pertenecientes al
70     sistema.
71
72     \note Es necesario para ver el contenido de la pagina hacer 
73     $MARCO->display() al final de la misma.
74 */
75
76 //REQUIRE ONCE {{{
77 require_once 'SAMURAI/DB.php';
78 require_once 'SAMURAI/Perm.php';
79 require_once 'SAMURAI/constantes.php';
80 require_once 'SAMURAI/Perfil.php';
81 require_once 'SAMURAI/Sistema.php';
82 require_once 'SAMURAI/Permiso.php';
83 require_once 'MECON/HTML/Tabla.php';
84 require_once 'MECON/HTML/QuickForm.php';
85 require_once 'MECON/HTML/Error.php';
86 require_once 'MECON/HTML/Image.php';
87 require_once 'PEAR.php';
88 // }}}
89
90 /** Funcion que se encarga agregar los componentes necesarios al sistema para
91  * que se pueda realizar un abm de perfiles.  Sin los parametros no funciona
92  *
93  * @param MECON_Marco &$MARCO      Referencia al objeto MECON_Marco que se este utilizando en la pagina
94  * @param int          $id_sistema Identificador del sistema en el cual se esta trabajando
95  *
96  * @return void
97  */
98 //SAMURAI_HTML_Perfil {{{
99 function SAMURAI_HTML_Perfil(&$MARCO, $id_sistema) {
100
101     $_SESSION['samurai']['id_sistema'] = $id_sistema;
102     $_SESSION['samurai']['login'] = $_SESSION['usuario'];
103     
104     //INICIALIZO OBJETOS GENERALES {{{
105     //REALIZO CONEXION
106     $tmp = new SAMURAI_DB();
107     $DB  =& $tmp->connect();
108     //CREAR EL OBJETO SAMURAI_Perm
109     $SAMURAI_PERM = new SAMURAI_Perm ($_SESSION['usuario'], $id_sistema, $DB);
110     //}}}
111
112     
113     if (@$_POST['samurai_accion'] == 'abm' || @$_GET['samurai_perfiles'] == 'abm') {
114         $OPCION = 'abm';
115     }
116     elseif (@$_POST['samurai_accion'] == 'nuevo' || @$_GET['samurai_perfiles'] == 'nuevo') {
117         $OPCION = 'nuevo';
118     }
119     else {
120         $OPCION = 'listado';
121     }
122     
123     //POSIBLES ACCIONES
124     // listado -> Listado de los perfiles ya creados en el sistema.
125     // nuevo   -> Pantalla de seleccion o de ingreso de un nuevo nombre.
126     // abm     -> Formulario para la carga de la info del perfil.
127
128     //LISTADO {{{
129     if ($OPCION == 'listado') {
130         //VEO SI PUEDE ACCEDER{{{
131         $SAMURAI_PERM->chequear(SAMURAI_ALTA_PERFIL,SAMURAI_BAJA_PERFIL,SAMURAI_MODI_PERFIL);
132         //}}}
133         //LINKS {{{
134             $aHref      = '<a href="'.$_SERVER['PHP_SELF'].'?accion=##ACCION##&id_perfil=##NUEVO##&samurai_perfiles=abm">';
135             $aHrefModif = $aHref.'<img src="/MECON/images/general_modificar.gif" border="0" alt="Modificar Perfil"></a>';
136             $aHrefElim  = $aHref.'<img src="/MECON/images/general_eliminar.gif"  border="0" alt="Eliminar Perfil" ></a>';
137         // }}}
138         //CREO LOS OBJETOS NECESARIOS {{{
139             $TABLA2  =& new MECON_HTML_Tabla ('cellspacing=0');
140             $TABLA   =& new MECON_HTML_Tabla ('cellpadding=2');
141             $TABLA3  =& new MECON_HTML_Tabla ('cellspacing=0');
142             $SISTEMA =& new SAMURAI_Sistema($DB, $id_sistema);
143         // }}}
144         //OBTENGO LA INFORMACION DE LA BASE {{{
145             $perfiles = SAMURAI_Perfil::getPerfiles($DB, null, $id_sistema);
146         // }}}
147         //AGREGO LOS DATOS A LAS TABLAS {{{
148             $imagen = new MECON_HTML_Image('/MECON/images/vinetas_flecha_doble.gif');
149             $row    = array ($imagen->toHtml().'&nbsp;<b>SISTEMA: '.$SISTEMA->getNombre().'</b>');
150             $TABLA3->addRow($row,'align=left'); 
151
152             //Agrego el link a nuevo
153             if ($SAMURAI_PERM->tiene(SAMURAI_ALTA_PERFIL)) {
154                 $row   = array ('<a href="'.$_SERVER['PHP_SELF'].'?samurai_perfiles=nuevo"><img src="/MECON/images/general_nuevo.gif" border="0">Ingresar&nbsp;Nuevo&nbsp;Perfil</a>');
155                 $TABLA2->addRow($row,'align=right');    
156             }
157
158             //Genero la cabecera de la tabla
159             $row   = array ('Id','Descripcion');
160             if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
161                 $row[] = 'Tipo';
162             }    
163             if ($SAMURAI_PERM->tiene(SAMURAI_MODI_PERFIL)) {
164                 $row[] = 'Modif.';
165             }    
166             if ($SAMURAI_PERM->tiene(SAMURAI_BAJA_PERFIL)) {
167                 $row[] = 'Elim.';
168             }    
169             
170             $TABLA->addRow($row,'cabecera');
171             foreach ($perfiles as $perfil) {
172                 $Modif = ereg_replace('##NUEVO##' , $perfil->getId(), $aHrefModif);
173                 $Elim  = ereg_replace('##NUEVO##' , $perfil->getId(), $aHrefElim );
174                 $Modif = ereg_replace('##ACCION##', 'm'             , $Modif     );
175                 $Elim  = ereg_replace('##ACCION##', 'e'             , $Elim      );
176                 $row = array ($perfil->getId(), $perfil->getDescripcion());
177                 
178                 if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
179                     $row[] = $perfil->getTipo();
180                 }    
181                 if ($SAMURAI_PERM->tiene(SAMURAI_MODI_PERFIL)) {
182                     $row[] = $Modif;
183                 }    
184                 if ($SAMURAI_PERM->tiene(SAMURAI_BAJA_PERFIL)) {
185                     $row[] = $Elim;
186                 }    
187                 $TABLA->addRow($row);
188             }
189         // }}}
190         //AGREGO LA INFO AL MARCO {{{
191             $MARCO->addBody($TABLA3);
192             $MARCO->addBody($TABLA2->toHtml(1));
193             $MARCO->addBody($TABLA);
194         //}}}
195     }
196     //}}}
197     //NUEVO {{{
198     elseif ($OPCION == 'nuevo') {
199         //VEO SI PUEDE ACCEDER{{{
200         $SAMURAI_PERM->chequear(SAMURAI_ALTA_PERFIL);
201         //}}}
202         //CREO LOS OBJETO NECESARIOS {{{
203             $FORM    =& new MECON_HTML_QuickForm ('samurai_perfiles','post',$_SERVER['PHP_SELF']);
204             $SISTEMA =& new SAMURAI_Sistema ($DB, $id_sistema);
205         // }}}
206         //AGREGO LOS ELEMENTOS DEL FORM {{{
207             $FORM->addElement ('hidden', 'samurai_accion', 'nuevo');
208             $FORM->addElement ('header', 'cabecera'   , 'Nuevo Perfil');
209             $FORM->addElement ('select', 'perfiles'   , 'Perfiles', '', array('size' => '1'));
210             $FORM->addElement ('text'  , 'filtro'     , 'Filtrar' , array('size' => '50'));
211             $FORM->addElement ('text'  , 'descripcion', 'Nombre'  , array('size' => '50'));
212             $group[] = HTML_QuickForm::createElement('submit', 'continuar', 'Continuar');
213             $group[] = HTML_QuickForm::createElement('submit', 'filtrar'  , 'Filtrar'  );
214             $group[] = HTML_QuickForm::createElement('submit', 'cancelar' , 'Cancelar', array ('onClick' => 'javascript:window.location =\''.$_SERVER['PHP_SELF'].'\';return false;') );
215             $FORM->addGroup($group,'botones');
216         // }}}
217         //RESTRINJO EL FORMATO DEL NOMBRE DEL PERFIL{{{
218             $FORM->addRule ('descripcion', 'El nombre del perfil solo puede contener letras y/o numeros.', 'regex','/^[a-zA-Z0-9 ]+$/');
219         // }}}
220         // CARGO LA INFORMACION EN EL SELECT DE PERFILES {{{
221             $botones     = $FORM->getSubmitValue('botones');
222             $perfiles    =& $FORM->getElement('perfiles');
223             $descripcion =& $FORM->getElement('descripcion');
224             if (@$botones['cancelar']) {
225                 header('Location: '.$_SERVER['PHP_SELF'].'/');
226             }
227             if (!isset($botones['filtrar'])) {
228                 $PERFILES = SAMURAI_Perfil::getArrayPerfiles($DB);
229             }
230             elseif (@$botones['filtrar']) {
231                 $filtro   =& $FORM->getElement('filtro'); 
232                 $PERFILES = SAMURAI_Perfil::getArrayPerfiles($DB, $filtro->getValue());
233             }
234             $perfiles->addOption('--', '--');
235             $perfiles->loadArray($PERFILES);
236         // }}}
237         // VALIDO EL FORMULARIO {{{
238             if ($FORM->validate()) {
239                 if (@$botones['continuar']) { //Ya selecciono un nombre para el perfil
240                     $res = '';
241                     $tmp = $perfiles->getSelected();
242                     if ((!@$descripcion->getvalue() && $tmp['0'] == '--') || ($descripcion->getvalue() && $tmp['0'] != '--')) {
243                         $res = new PEAR_Error("Debe seleccionar un perfil del combo o ingresar un nombre en la casilla correspondiente.<br>
244                                                Solo una de las dos opciones.");
245                         @$descripcion->setValue('');
246                     }
247                     elseif ($tmp['0'] != '--') {
248                         //verificar que el sistema no tenga una asociacion con ese perfil
249                         if (SAMURAI_Perfil::existeAsociacion($DB, $tmp['0'], $id_sistema)) {
250                             $res = new PEAR_Error("El sistema ya tiene asociado el perfil seleccionado, 
251                                                    modifique sus permisos desde la seccion perfiles.");
252                         }
253                         else {
254                             header('Location: '.$_SERVER['PHP_SELF'].'?samurai_perfiles=abm&id_perfil='.$tmp['0']);
255                         }
256                     }
257                     elseif ($descripcion->getValue()) {
258                         //Verificar que no exista un perfil con la misma descripcion
259                         //Reduzco los blancos
260                         $temp = $descripcion->getValue();
261                         $tt = split (' ', $temp);
262                         $rta = ''; 
263                         foreach ($tt as $t) {
264                             if ($t != '') {
265                                 $rta.= $t.' ';
266                             }
267                         }
268                         $rta = rtrim($rta);
269                         // 
270                         if (SAMURAI_Perfil::existePerfil($DB, $rta)) {
271                             $res = new PEAR_Error("Ya existe un perfil con ese nombre, seleccionelo del combo.<br>
272                                                    Recuerde que varios espacios se reduciran a uno solo 
273                                                    (Ej: Agregar&nbsp;&nbsp;&nbsp;&nbsp; Usuario -> Agregar Usuario)");
274                         }
275                         else {
276                             $temp = ereg_replace(' ' , '%20', $rta); //Cambio los espacios por %20 para que no chille el netscape
277                             header('Location: '.$_SERVER['PHP_SELF'].'?samurai_perfiles=abm&desc_perfil='.$temp);
278                         }
279                     }
280                     if (PEAR::isError($res)) {
281                         $TABLA = new MECON_HTML_Tabla ('cellspacing=0');
282                         $row = array ('<font color="red"><b>'.$res->getMessage().'</b></font>');
283                         $TABLA->addRow($row,'align=left');
284                     }
285                 } 
286             }
287         // }}}
288         //AGREGO LA INFO AL MARCO {{{
289         //AGREGO LOS DATOS A LAS TABLAS {{{
290             $TABLA3 = new MECON_HTML_Tabla ('cellspacing=0');
291             $imagen = new MECON_HTML_Image('/MECON/images/vinetas_flecha_doble.gif');
292             $row    = array ($imagen->toHtml().'&nbsp;<b>SISTEMA: '.$SISTEMA->getNombre().'</b>');
293             $TABLA3->addRow($row,'align=left');    
294         //}}} 
295             $MARCO->addBody($TABLA3);
296             if (isset($TABLA)) {
297                 $MARCO->addBody($TABLA);
298             }
299             $MARCO->addBody($FORM);
300         //}}}
301     }
302     //}}}
303     //ABM {{{
304     elseif ($OPCION == 'abm') {
305         //VEO SI PUEDE ACCEDER{{{
306         $SAMURAI_PERM->chequear(SAMURAI_ALTA_PERFIL,SAMURAI_BAJA_PERFIL,SAMURAI_MODI_PERFIL);
307         //}}}
308         //CREO LOS OBJETO NECESARIOS {{{
309             if (@$_GET['id_perfil']) {
310                 $id_perfil = $_GET['id_perfil'];
311             }
312             elseif (@$_POST['id_perfil']) {
313                 $id_perfil = $_POST['id_perfil'];
314             }
315             else {
316                 $id_perfil = null;
317             }
318             $FORM    =& new MECON_HTML_QuickForm ('samurai_perfiles','post',$_SERVER['PHP_SELF']);
319             $SISTEMA =& new SAMURAI_Sistema ($DB, $id_sistema);
320             $PERFIL  =& new SAMURAI_Perfil ($DB, $id_perfil);
321
322             if ($PERFIL->getResponsable()) {
323                 $responsable = $PERFIL->getResponsable();
324             }
325             else {
326                 $responsable = $_SESSION['usuario'];
327             }
328             
329             if (!@$_GET['id_perfil']) {
330                 if (@$_GET['desc_perfil']) {
331                     $PERFIL->setDescripcion(@$_GET['desc_perfil']);
332                 }
333                 else {
334                     $PERFIL->setDescripcion(@$_POST['desc_ant']);
335                 }
336             }
337             $descripcion = $PERFIL->getDescripcion();
338         // }}}
339         //OBTENGO LOS PERMISOS DEL SISTEMA {{{
340             $ASOCIACIONES = $SISTEMA->getAsociaciones();
341             $PERMISOS = array ();
342             foreach ($ASOCIACIONES as $as) {
343                 $clave = $as['id'].'##'.$as['obs'];
344                 $texto = ($as['obs'] != '') ? $as['desc'].' - '.$as['obs']: $as['desc'];
345                 $PERMISOS[$clave] = $texto;
346             }
347         // }}}
348         //AGREGO LOS ELEMENTOS DEL FORM {{{
349             if (@$PERMISOS) {
350                 $FORM->addElement ('hidden', 'samurai_accion', 'abm');
351                 $FORM->addElement ('header', 'cabecera', 'ABM Perfiles');
352                 $FORM->addElement ('hidden', 'id_perfil', $id_perfil);
353                 $FORM->addElement ('hidden', 'desc_ant'   , $descripcion);
354                 $FORM->addElement ('static', 'desc_perfil', 'Descripcion', $descripcion);
355                 $FORM->addElement ('select', 'permisos'   , 'Permisos'   , $PERMISOS, array('size' => '5', 'multiple' => 'true'));
356                 if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
357                     $FORM->addElement ('select', 'tipo_perfil', 'Tipo Perfil', array('E' => 'Externo', 'I' => 'Interno', 'D' => 'Dios'), array ('size' => '1'));
358                 }
359                 $FORM->addElement ('hidden', 'responsable', $responsable);
360                 $group[] = HTML_QuickForm::createElement('submit', 'aceptar' , 'Grabar');
361                 $group[] = HTML_QuickForm::createElement('submit', 'cancelar', 'Cancelar', array ('onClick' => 'javascript:window.location=\''.$_SERVER['PHP_SELF'].'\';return false;'));
362                 $FORM->addGroup($group,'botones');
363             }
364             else {
365                 $ERROR = new MECON_HTML_Error('El sistema no posee permisos asociados.');
366             }
367         // }}}
368         //AGREGO LAS REGLAS DE VALIDACION {{{
369             $FORM->addRule ('permisos', 'Se debe seleccionar al menos un permiso', 'required');
370         // }}}
371         //CARGO LOS DATOS SI YA EXISTEN EN BASE {{{
372             if (isset($_GET['accion']) && $_GET['accion'] != '') {
373                 //MODIFICACION
374                 $id_perfil    =& $FORM->getElement  ('id_perfil'  );
375                 $desc_perfil  =& $FORM->getElement  ('desc_perfil');
376                 $permisos     =& $FORM->getElement  ('permisos'   );
377                 
378                 if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
379                     $tipo_perfil  =& $FORM->getElement  ('tipo_perfil');
380                 }
381                 $responsable  =& $FORM->getElement  ('responsable');
382                 $group        =& $FORM->getElement  ('botones'    );
383                 $group        =& $group->getElements('aceptar'    );
384                 $aceptar      =& $group[0];
385
386                 $permisos->setSelected($PERFIL->getPermisos());
387                 
388                 if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
389                     $tipo_perfil->setSelected($PERFIL->getTipo());
390                 }
391
392                 if ($PERFIL->getResponsable() != '') {
393                     $responsable->setValue($PERFIL->getResponsable());
394                 }
395
396                 //Modifico el valor del boton
397                 $aceptar->setValue('Modificar');
398                     
399                 //ELIMINACION -> modifico el valor del boton
400                 if ($_GET['accion'] == 'e') {
401                     $aceptar->setValue('Eliminar');
402                     $aceptar->updateAttributes(array ('onClick' => 'javascript:if (confirm(\'¿Esta Seguro?\')) return true;return false;'));
403                     $FORM->freeze();
404                 }
405             }
406         // }}}
407         //VALIDO EL FORMULARIO {{{
408             if ($FORM->validate()) {
409                 // VEO SI SE CANCELO {{{
410                 $botones = $FORM->getSubmitValue('botones');
411                 if (@$botones['cancelar']) {
412                     header('Location: '.$_SERVER['PHP_SELF']);
413                 }
414                 // }}}
415                 else {
416                     $samurai_accion =& $FORM->getElement('samurai_accion');
417                     $samurai_accion->setValue('listado');
418                     $id_perfil    =& $FORM->getElement  ('id_perfil'  );
419                     $desc_perfil  =& $FORM->getElement  ('desc_perfil');
420                     $permisos     =& $FORM->getElement  ('permisos'   );
421                     
422                     if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
423                         $tipo_perfil  =& $FORM->getElement  ('tipo_perfil');
424                         $tipo_perfil_tmp  =  $tipo_perfil->getSelected();
425                     }
426                     $responsable  =& $FORM->getElement  ('responsable');
427                     $group        =& $FORM->getElement  ('botones'    );
428                     $group        =& $group->getElements('aceptar'    );
429                     $aceptar      =& $group[0];
430               
431                     $PERFIL->setDescripcion($desc_perfil->_text     );
432                     $PERFIL->setResponsable($responsable->getValue());
433                     $PERFIL->setPermisos   ($permisos->getSelected()); //Le asigno al perfil los permisos seleccionados
434                     
435                     if ($SAMURAI_PERM->tiene(SAMURAI_TIPO_PERFIL)) {
436                         $PERFIL->setTipo($tipo_perfil_tmp['0']);
437                     }
438                     
439                     //Grabo y verifico si se produjo algun error
440                     $res = $PERFIL->guardarDatos($aceptar->getValue());
441
442                     if (PEAR::isError($res)) {
443                         $ERROR = new MECON_HTML_Error($res->getMessage());
444                         if ($aceptar->getValue() == 'Eliminar') {
445                             $FORM->freeze();
446                         }
447                     }
448                     else {
449                         $FORM->freeze();
450                         header('Location: '.$_SERVER ['PHP_SELF'].'/');
451                         exit;
452                     }
453                 }
454             }
455         // }}}
456         //DIBUJO LA PAGINA {{{
457             $imagen = new MECON_HTML_Image('/MECON/images/vinetas_flecha_doble.gif');
458             $row    = array ($imagen->toHtml().'&nbsp;<b>SISTEMA: '.$SISTEMA->getNombre().'</b>');
459             $TABLA3 = new MECON_HTML_Tabla ('cellspacing=0');
460             $TABLA3->addRow($row,'align=left');    
461
462             $MARCO->addBody($TABLA3);
463             if (isset($ERROR)) {
464                 $MARCO->addBody($ERROR);
465             }
466             $MARCO->addBody($FORM);
467     //}}}
468     }
469     //}}}
470 }
471 //}}}
472 ?>