source: trunk/www/admin/roles/edit_role.jsp @ 5921

Last change on this file since 5921 was 5921, checked in by Nicklas Nordborg, 10 years ago

References #1655: GUI improvements

Edit dialogs for all items in the first level under the Administrate menu.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.6 KB
Line 
1<%-- $Id: edit_role.jsp 5921 2012-01-10 12:30:57Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2005 Nicklas Nordborg
4  Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg, Martin Svensson
5  Copyright (C) 2007 Nicklas Nordborg
6
7  This file is part of BASE - BioArray Software Environment.
8  Available at http://base.thep.lu.se/
9
10  BASE is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License
12  as published by the Free Software Foundation; either version 3
13  of the License, or (at your option) any later version.
14
15  BASE is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with BASE. If not, see <http://www.gnu.org/licenses/>.
22  ------------------------------------------------------------------
23
24
25  @author Nicklas
26  @version 2.0
27--%>
28<%@ page pageEncoding="UTF-8" session="false"
29  import="net.sf.basedb.core.SessionControl"
30  import="net.sf.basedb.core.DbControl"
31  import="net.sf.basedb.core.SystemItems"
32  import="net.sf.basedb.core.Item"
33  import="net.sf.basedb.core.ItemContext"
34  import="net.sf.basedb.core.Include"
35  import="net.sf.basedb.core.Permission"
36  import="net.sf.basedb.core.User"
37  import="net.sf.basedb.core.Role"
38  import="net.sf.basedb.core.RoleKey"
39  import="net.sf.basedb.core.ItemQuery"
40  import="net.sf.basedb.core.ItemResultList"
41  import="net.sf.basedb.core.BaseException"
42  import="net.sf.basedb.core.PermissionDeniedException"
43  import="net.sf.basedb.core.query.Orders"
44  import="net.sf.basedb.core.query.Hql"
45  import="net.sf.basedb.clients.web.Base"
46  import="net.sf.basedb.clients.web.PermissionUtil"
47  import="net.sf.basedb.clients.web.util.HTML"
48  import="net.sf.basedb.util.Values"
49  import="net.sf.basedb.core.plugin.GuiContext"
50  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
51  import="net.sf.basedb.clients.web.extensions.JspContext"
52  import="net.sf.basedb.clients.web.extensions.edit.EditUtil"
53  import="net.sf.basedb.util.extensions.ExtensionsInvoker"
54  import="java.util.EnumSet"
55  import="java.util.Set"
56  import="java.util.Map"
57  import="java.util.List"
58%>
59<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
60<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
61<%!
62private static final int DENY_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.DENIED));
63private static final int CREATE_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.CREATE));
64private static final int READ_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.READ));
65private static final int USE_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.USE));
66private static final int WRITE_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.WRITE));
67private static final int DELETE_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.DELETE));
68private static final int SET_OWNER_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.SET_OWNER));
69private static final int SET_PERMISSION_CODE = PermissionUtil.getPermissionCode(EnumSet.of(Permission.SET_PERMISSION));
70
71private String getOption(DbControl dc, Role role, Item itemType)
72  throws BaseException
73{
74  int keyId = SystemItems.getRoleKeyId(itemType);
75  if (keyId == 0) return "";
76
77  RoleKey key = RoleKey.getById(dc, keyId);
78  Set<Permission> permissions = role == null ? EnumSet.noneOf(Permission.class) : key.getPermissions(role);
79  StringBuilder sb = new StringBuilder();
80  sb.append("<option value=\"").append(key.getItemType().name()).append("\">");
81  sb.append(HTML.encodeTags(key.getName()));
82  sb.append(" [");
83  if (permissions.contains(Permission.DENIED)) 
84  {
85    sb.append("DENIED");
86  }
87  else
88  {
89    Set<Permission> defined = itemType.getDefinedPermissions();
90    if (defined != null)
91    {
92      if (defined.contains(Permission.CREATE)) sb.append(permissions.contains(Permission.CREATE) ? "C" : "-");
93      if (defined.contains(Permission.READ)) sb.append(permissions.contains(Permission.READ) ? "R" : "-");
94      if (defined.contains(Permission.USE)) sb.append(permissions.contains(Permission.USE) ? "U" : "-");
95      if (defined.contains(Permission.WRITE)) sb.append(permissions.contains(Permission.WRITE) ? "W" : "-");
96      if (defined.contains(Permission.DELETE)) sb.append(permissions.contains(Permission.DELETE) ? "D" : "-");
97      if (defined.contains(Permission.SET_OWNER)) sb.append(permissions.contains(Permission.SET_OWNER) ? "O" : "-");
98      if (defined.contains(Permission.SET_PERMISSION)) sb.append(permissions.contains(Permission.SET_PERMISSION) ? "P" : "-");
99    }
100  }
101  sb.append("]");
102  return sb.toString();
103}
104%>
105<%
106final Item itemType = Item.ROLE;
107final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
108final ItemContext cc = Base.getAndSetCurrentContext(sc, itemType, null, null);
109final int itemId = cc.getId();
110final String ID = sc.getId();
111final float scale = Base.getScale(sc);
112final DbControl dc = sc.newDbControl();
113try
114{
115  String title = null;
116  Role role = null;
117  boolean isDefault = false;
118
119  if (itemId == 0)
120  {
121    title = "Create role";
122    cc.removeObject("item");
123    isDefault = Values.getBoolean(cc.getPropertyValue("default"), false);
124  }
125  else
126  {
127    role = Role.getById(dc, itemId);
128    cc.setObject("item", role);
129    isDefault = role.isDefault();
130    title = "Edit role -- " + HTML.encodeTags(role.getName());
131   
132  }
133  if (role != null && !role.hasPermission(Permission.WRITE))
134  {
135    throw new PermissionDeniedException(Permission.WRITE, itemType.toString());
136  }
137 
138  final boolean useUsers = sc.hasPermission(Permission.WRITE, Item.USER);
139  RoleKey system = RoleKey.getById(dc, SystemItems.getRoleKeyId(Item.SYSTEM));
140  final boolean hasShareToEveryone = role == null ? false : system.getPermissions(role).contains(Permission.SHARE_TO_EVERYONE);
141  final boolean hasActAsAnotherUser = role == null ? false : system.getPermissions(role).contains(Permission.ACT_AS_ANOTHER_USER);
142  final boolean hasSelectJobagent = role == null ? false : system.getPermissions(role).contains(Permission.SELECT_JOBAGENT);
143 
144  // Query to retrieve role keys
145  final ItemQuery<RoleKey> roleKeyQuery = RoleKey.getQuery();
146  roleKeyQuery.order(Orders.asc(Hql.property("name")));
147
148  // Query to retrieve user members
149  ItemQuery<User> userQuery = null;
150  if (role != null)
151  {
152    userQuery = role.getUsers();
153    userQuery.include(Include.ALL);
154    userQuery.order(Orders.asc(Hql.property("name")));
155  }
156
157  final String clazz = "class=\"text\"";
158  final String requiredClazz = "class=\"text required\"";
159  JspContext jspContext = ExtensionsControl.createContext(dc, pageContext, GuiContext.item(itemType), role);
160  ExtensionsInvoker invoker = EditUtil.useEditExtensions(jspContext);
161  %>
162  <base:page type="popup" title="<%=title%>">
163  <base:head scripts="tabcontrol.js,linkitems.js" styles="tabcontrol.css">
164    <ext:scripts context="<%=jspContext%>" />
165    <ext:stylesheets context="<%=jspContext%>" />
166    <script language="JavaScript">
167    // Validate the "Role" tab
168    function validateRole()
169    {
170      var frm = document.forms['role'];
171      if (Main.trimString(frm.name.value) == '')
172      {
173        alert("You must enter a name");
174        frm.name.focus();
175        return false;
176      }
177      return true;
178    }
179    // Validate the "Members" tab
180    function validateMembers()
181    {
182      return true;
183    }
184
185    // Submit the form
186    function saveSettings()
187    {
188      var frm = document.forms['role'];
189      if (TabControl.validateActiveTab('settings'))
190      {
191        frm.addUsers.value = Link.getActionIds(1, 'U').join(',');
192        frm.removeUsers.value = Link.getActionIds(-1, 'U').join(',');
193        var systemPermission = 0;
194        if (frm.share_to_everyone.checked) systemPermission += <%=PermissionUtil.getPermissionCode(EnumSet.of(Permission.SHARE_TO_EVERYONE))%>;
195        if (frm.act_as_another_user.checked) systemPermission += <%=PermissionUtil.getPermissionCode(EnumSet.of(Permission.ACT_AS_ANOTHER_USER))%>;
196        if (frm.select_jobagent.checked) systemPermission += <%=PermissionUtil.getPermissionCode(EnumSet.of(Permission.SELECT_JOBAGENT))%>;
197        frm['<%=Item.SYSTEM.name()%>'].value = systemPermission;
198        frm.submit();
199      }
200    }
201   
202    function init()
203    {
204      <%
205      if (role == null)
206      {
207        %>
208        var frm = document.forms['role'];
209        frm.name.focus();
210        frm.name.select();
211        <%
212      }
213      %>
214      initMembers();
215    }
216    function initMembers()
217    {
218      var members = document.forms['role'].members;
219      <%
220      if (userQuery != null)
221      {
222        ItemResultList<User> users = userQuery.list(dc);
223        for (User user : users)
224        {
225          %>
226          Link.addNewItem(members, new Item('U', <%=user.getId()%>, '<%=HTML.javaScriptEncode(user.getName())%>'));
227          <%
228        }
229      }
230      %>
231    }
232    function addUsersOnClick()
233    {
234      var users = Link.getListIds(document.forms['role'].members, 'U');
235      var url = '../users/index.jsp?ID=<%=ID%>&cmd=UpdateContext&mode=selectmultiple&callback=addUserCallback';
236      url += '&exclude='+users.join(',');
237      Main.openPopup(url, 'AddUsers', 1000, 700);
238    }
239    function addUserCallback(userId, name)
240    {
241      var item = Link.getItem('U', userId);
242      if (!item) item = new Item('U', userId, name);
243      Link.addItem(document.forms['role'].members, item);
244    }
245    function removeOnClick()
246    {
247      Link.removeSelected(document.forms['role'].members);
248    }
249    function showPermissions(itemType)
250    {
251      var frm = document.forms['role'];
252      if (itemType)
253      {
254        var permissionCode = frm[itemType].value;
255        var definedPermissions = parseInt(frm[itemType+'_defined'].value);
256        frm['deny'].checked = (permissionCode & <%=DENY_CODE%>);
257        frm['create'].checked = (permissionCode & <%=CREATE_CODE%>);
258        frm['create'].disabled = !(definedPermissions & <%=CREATE_CODE%>);
259        frm['read'].checked = (permissionCode & <%=READ_CODE%>);
260        frm['read'].disabled = !(definedPermissions & <%=READ_CODE%>);
261        frm['use'].checked = (permissionCode & <%=USE_CODE%>);
262        frm['use'].disabled = !(definedPermissions & <%=USE_CODE%>);
263        frm['write'].checked = (permissionCode & <%=WRITE_CODE%>);
264        frm['write'].disabled = !(definedPermissions & <%=WRITE_CODE%>);
265        frm['delete'].checked = (permissionCode & <%=DELETE_CODE%>);
266        frm['delete'].disabled = !(definedPermissions & <%=DELETE_CODE%>);
267        frm['set_owner'].checked = (permissionCode & <%=SET_OWNER_CODE%>);
268        frm['set_owner'].disabled = !(definedPermissions & <%=SET_OWNER_CODE%>);
269        frm['set_permission'].checked = (permissionCode & <%=SET_PERMISSION_CODE%>);
270        frm['set_permission'].disabled = !(definedPermissions & <%=SET_PERMISSION_CODE%>);
271      }
272    }
273    function getPermissionCode()
274    {
275      var permissionCode = 0;
276      var frm = document.forms['role'];
277      permissionCode += frm['deny'].checked ? <%=DENY_CODE%>: 0;
278      permissionCode += frm['create'].checked ? <%=CREATE_CODE%>: 0;
279      permissionCode += frm['read'].checked ? <%=READ_CODE%>: 0;
280      permissionCode += frm['use'].checked ? <%=USE_CODE%>: 0;
281      permissionCode += frm['write'].checked ? <%=WRITE_CODE%>: 0;
282      permissionCode += frm['delete'].checked ? <%=DELETE_CODE%>: 0;
283      permissionCode += frm['set_owner'].checked ? <%=SET_OWNER_CODE%>: 0;
284      permissionCode += frm['set_permission'].checked ? <%=SET_PERMISSION_CODE%>: 0;
285      return permissionCode;
286    }
287   
288    function correctPermissions(checked, forceDeny)
289    {
290      var frm = document.forms['role'];
291      if (checked)
292      {
293        frm['deny'].checked = frm['deny'].checked && forceDeny;
294        frm['set_permission'].checked = frm['set_permission'].checked && !frm['deny'].checked;
295        frm['set_owner'].checked = frm['set_owner'].checked && !frm['deny'].checked;
296        frm['delete'].checked = frm['delete'].checked && !frm['deny'].checked;
297        frm['write'].checked = (frm['write'].checked || frm['delete'].checked || frm['set_owner'].checked || frm['set_permission'].checked) && !frm['deny'].checked;
298        frm['use'].checked = (frm['use'].checked || frm['write'].checked) && !frm['deny'].checked;
299        frm['read'].checked = (frm['read'].checked || frm['use'].checked) && !frm['deny'].checked;
300        frm['create'].checked = frm['create'].checked && !frm['deny'].checked;
301      }
302      else
303      {
304        frm['deny'].checked = frm['deny'].checked && !frm['create'].checked && !frm['read'].checked && !frm['use'].checked && !frm['write'].checked && !frm['delete'].checked && !frm['set_owner'].checked && !frm['set_permission'].checked;
305        frm['create'].checked = frm['create'].checked && !frm['deny'].checked;
306        frm['read'].checked = frm['read'].checked && !frm['deny'].checked;
307        frm['use'].checked = (frm['use'].checked && frm['read'].checked) && !frm['deny'].checked;
308        frm['write'].checked = (frm['write'].checked && frm['use'].checked) && !frm['deny'].checked;
309        frm['delete'].checked = (frm['delete'].checked && frm['write'].checked) && !frm['deny'].checked;
310        frm['set_owner'].checked = (frm['set_owner'].checked && frm['write'].checked) && !frm['deny'].checked;
311        frm['set_permission'].checked = (frm['set_permission'].checked && frm['write'].checked) && !frm['deny'].checked;
312      }
313    }
314
315    function setPermissions(checked, forceDeny)
316    {
317      var frm = document.forms['role'];
318      correctPermissions(checked, forceDeny);
319      var permissionCode = getPermissionCode();
320
321      for (var i = 0; i < frm.items.length; i++)  // >
322      {
323        var item = frm.items[i];
324        var itemType = item.value;
325        if (item.selected && itemType)
326        {
327          frm[itemType].value = permissionCode;
328          var definedPermissions = parseInt(frm[itemType+'_defined'].value);
329          var status = '';
330          if (frm['deny'].checked)
331          {
332            status = "DENIED";
333          }
334          else
335          {
336            if (definedPermissions & <%=CREATE_CODE%>) status += frm['create'].checked ? "C" : "-";
337            if (definedPermissions & <%=READ_CODE%>) status += frm['read'].checked ? "R" : "-";
338            if (definedPermissions & <%=USE_CODE%>) status += frm['use'].checked ? "U" : "-";
339            if (definedPermissions & <%=WRITE_CODE%>) status += frm['write'].checked ? "W" : "-";
340            if (definedPermissions & <%=DELETE_CODE%>) status += frm['delete'].checked ? "D" : "-";
341            if (definedPermissions & <%=SET_OWNER_CODE%>) status += frm['set_owner'].checked ? "O" : "-";
342            if (definedPermissions & <%=SET_PERMISSION_CODE%>) status += frm['set_permission'].checked ? "P" : "-";
343          }
344          var text = item.text.replace(/\[.*\]/, '['+status+']');
345          item.text = text;
346        }
347      }
348    }
349
350    </script>
351  </base:head>
352  <base:body onload="init()">
353    <h1><%=title%> <base:help tabcontrol="settings" /></h1>
354    <form action="index.jsp?ID=<%=ID%>" method="post" name="role" onsubmit="return false;">
355    <input type="hidden" name="cmd" value="UpdateItem">
356
357    <t:tabcontrol id="settings" 
358      subclass="content dialogtabcontrol"
359      position="bottom" remember="<%=role != null%>"
360      extensions="<%=invoker%>">
361    <t:tab id="info" title="Role" validate="validateRole()" helpid="role.edit">
362      <table class="fullform input100">
363      <tr>
364        <th>Name</th>
365        <td><input <%=requiredClazz%> type="text" name="name" 
366          value="<%=HTML.encodeTags(role == null ? Values.getString(cc.getPropertyValue("name"), "New role") : role.getName())%>" 
367          maxlength="<%=Role.MAX_NAME_LENGTH%>"></td>
368        <td></td>
369      </tr>
370      <tr class="big">
371        <th>System-level<br>permissions</th>
372        <td>
373          <input type="checkbox" value="1" name="share_to_everyone" id="share_to_everyone"
374            <%=hasShareToEveryone ? "checked" : ""%>
375            ><label for="share_to_everyone">Share to Everyone</label><br>
376          <input type="checkbox" value="1" name="act_as_another_user" id="act_as_another_user"
377            <%=hasActAsAnotherUser ? "checked" : ""%>
378            ><label for="act_as_another_user">Act as another user</label><br>
379          <input type="checkbox" value="1" name="select_jobagent" id="select_jobagent"
380            <%=hasSelectJobagent ? "checked" : ""%>
381            ><label for="select_jobagent">Select job agent for jobs</label><br>
382        </td>
383        <td></td>
384      </tr>
385      <tr>
386        <th>Default</th>
387        <td>
388          <input type="radio" name="is_default" id="defaultNo" value="0" 
389            <%=!isDefault ? "checked" : ""%>><label for="defaultNo">no</label>
390          <input type="radio" name="is_default" id="defaultYes" value="1" 
391            <%=isDefault ? "checked" : ""%>><label for="defaultYes">yes</label>
392        </td>
393        <td></td>
394      </tr> 
395
396      <tr class="dynamic">
397        <th>Description</th>
398        <td nowrap>
399          <textarea <%=clazz%> rows="6" name="description" 
400            ><%=HTML.encodeTags(role == null ? cc.getPropertyValue("description") : role.getDescription())%></textarea>
401        </td>
402        <td style="width: 20px;">
403          <base:icon image="zoom.png" 
404            onclick="Main.zoom('Description', 'role', 'description')"
405            tooltip="Edit in larger window"
406          />
407        </td>
408      </tr>
409      </table>
410    </t:tab>
411   
412    <t:tab id="permissions" title="Permissions" 
413      tooltip="Set permissions for this role" helpid="role.edit.permissions">
414      <table class="fullform">
415      <tr class="dynamic">
416      <th>Item types</th>
417      <td>
418        <table>
419        <tr>
420        <td>
421          <select name="items" size="15" onChange="showPermissions(this[this.selectedIndex].value);" multiple>
422          <%
423          Map<String, List<Item>> permissionGroups = PermissionUtil.getPermissionGroups();
424          for (Map.Entry<String, List<Item>> entry : permissionGroups.entrySet())
425          {
426            String name = entry.getKey();
427            List<Item> items = entry.getValue();
428            %>
429            <option class="selectoptionheader" value="">-- <%=name%>
430            <%
431            for (Item item : items)
432            {
433              %>
434              <%=getOption(dc, role, item)%>
435              <%
436            }
437          }
438          %>
439          </select>
440        </td>
441        <td style="vertical-align: top; padding-left: 2px;">
442          <b>Permissions</b><br>
443          <input type="checkbox" name="deny" id="deny" onClick="setPermissions(this.checked, true)"><label for="deny">Deny</label><br>
444          <input type="checkbox" name="create" id="create" onClick="setPermissions(this.checked)"><label for="create">Create</label><br>
445          <input type="checkbox" name="read" id="read" onClick="setPermissions(this.checked)"><label for="read">Read</label><br>
446          <input type="checkbox" name="use" id="use" onClick="setPermissions(this.checked)"><label for="use">Use</label><br>
447          <input type="checkbox" name="write" id="write" onClick="setPermissions(this.checked)"><label for="write">Write</label><br>
448          <input type="checkbox" name="delete" id="delete" onClick="setPermissions(this.checked)"><label for="delete">Delete</label><br>
449          <input type="checkbox" name="set_owner" id="set_owner" onClick="setPermissions(this.checked)"><label for="set_owner">Set owner</label><br>
450          <input type="checkbox" name="set_permission" id="set_permission" onClick="setPermissions(this.checked)"><label for="set_permission">Set permission</label><br>
451          </td>
452        </tr>
453        </table>
454      </td>
455      </tr>
456      </table>
457    </t:tab>
458   
459    <t:tab id="members" title="Members" tooltip="Add/remove members of this role" 
460      validate="validateMembers()" helpid="role.edit.members">
461      <table class="fullform">
462      <tr class="dynamic">
463      <th>Members</th>
464      <td>
465          <div class="selectionlist">
466          <table>
467          <tr>
468            <td>
469            <select name="members" size="15" multiple <%=!useUsers ? "disabled readonly class=\"disabled\"" : ""%>>
470            </select>
471          </td>
472          <td style="vertical-align: top;">
473            <base:buttongroup vertical="true">
474              <base:button 
475                subclass="leftaligned"
476                style="width: 12em;"
477                onclick="addUsersOnClick()" 
478                title="Add&nbsp;users&hellip;" 
479                tooltip="Add users to this role"
480                disabled="<%=!useUsers %>" 
481              />
482              <base:button 
483                subclass="leftaligned"
484                style="width: 12em;"
485                onclick="removeOnClick()" 
486                title="Remove" 
487                tooltip="Remove the selected items from this role"
488                disabled="<%=!useUsers%>" 
489              />
490            </base:buttongroup>
491            <input type="hidden" name="removeUsers" value="">
492            <input type="hidden" name="addUsers" value="">
493          </td>
494          </tr>
495          </table>
496          </div>
497      </td>
498      </tr>
499      </table>
500    </t:tab>
501    </t:tabcontrol>
502    <%
503    ItemResultList<RoleKey> roleKeys = roleKeyQuery.list(dc);
504    for (RoleKey key : roleKeys)
505    {
506      int permissionCode = role == null ? 0 : PermissionUtil.getPermissionCode(key.getPermissions(role));
507      int definedCode = key.getItemType().getDefinedPermissions() == null ? 0 : PermissionUtil.getPermissionCode(key.getItemType().getDefinedPermissions());
508      String name = key.getItemType().name();
509      %>
510      <input type="hidden" name="<%=name%>" value="<%=permissionCode%>">
511      <input type="hidden" name="<%=name%>_defined" value="<%=definedCode%>">
512      <%
513    }
514    %>
515    </form>
516   
517    <div class="legend">
518      <base:icon image="required.gif" /> = required information
519    </div>
520
521    <base:buttongroup subclass="dialogbuttons">
522      <base:button onclick="saveSettings()" title="Save" />
523      <base:button onclick="window.close()" title="Cancel" />
524    </base:buttongroup>
525
526    <table align="center">
527    <tr>
528      <td width="50%"><base:button onclick="saveSettings()" title="Save" /></td>
529      <td width="50%"><base:button onclick="window.close()" title="Cancel" /></td>
530    </tr>
531    </table>
532
533  </base:body>
534  </base:page>
535  <%
536}
537finally
538{
539  if (dc != null) dc.close();
540}
541%>
Note: See TracBrowser for help on using the repository browser.