/** * Transfer netpoint * * @param $netpoints_id netpoint ID * * @return new netpoint ID **/ function transferDropdownNetpoint($netpoints_id) { global $DB; if ($netpoints_id > 0) { if (isset($this->already_transfer['netpoints_id'][$netpoints_id])) { return $this->already_transfer['netpoints_id'][$netpoints_id]; } else { // Not already transfer // Search init item $query = "SELECT *\n FROM `glpi_netpoints`\n WHERE `id` = '{$netpoints_id}'"; if ($result = $DB->query($query)) { if ($DB->numrows($result)) { $data = $DB->fetch_array($result); $data = addslashes_deep($data); $locID = $this->transferDropdownLocation($data['locations_id']); // Search if the locations_id already exists in the destination entity $query = "SELECT `id`\n FROM `glpi_netpoints`\n WHERE `entities_id` = '" . $this->to . "'\n AND `name` = '" . $data['name'] . "'\n AND `locations_id` = '{$locID}'"; if ($result_search = $DB->query($query)) { // Found : -> use it if ($DB->numrows($result_search) > 0) { $newID = $DB->result($result_search, 0, 'id'); $this->addToAlreadyTransfer('netpoints_id', $netpoints_id, $newID); return $newID; } } // Not found : // add item $netpoint = new Netpoint(); $newID = $netpoint->add(array('name' => $data['name'], 'comment' => $data['comment'], 'entities_id' => $this->to, 'locations_id' => $locID)); $this->addToAlreadyTransfer('netpoints_id', $netpoints_id, $newID); return $newID; } } } } return 0; }
/** * Display the Netpoint field. Used by Ethernet, and Migration * * @param $netport NetworkPort object :the port that owns this instantiation * (usefull, for instance to get network port attributs * @param $options array of options given to NetworkPort::showForm * @param $recursiveItems list of the items on which this port is attached **/ function showNetpointField(NetworkPort $netport, $options = array(), $recursiveItems) { echo "<td>" . __('Network outlet') . "</td>\n"; echo "<td>"; if (count($recursiveItems) > 0) { $lastItem = $recursiveItems[count($recursiveItems) - 1]; Netpoint::dropdownNetpoint("netpoints_id", $this->fields["netpoints_id"], $lastItem->fields['locations_id'], 1, $lastItem->getEntityID(), $netport->fields["itemtype"]); } else { _e('item not linked to an object'); } echo "</td>"; }
echo "<tr class='tab_bg_1'><td width='120'>" . __('By location') . "</td>"; echo "<td>"; Location::dropdown(array('entity' => $_SESSION["glpiactive_entity"])); echo "</td><td class='center' width='120'>"; echo "<input type='submit' value=\"" . __s('Display report') . "\" class='submit'>"; echo "</td></tr>"; echo "</table>"; Html::closeForm(); echo "<form name='form2' method='post' action='report.switch.list.php'>"; echo "<table class='tab_cadre' width='500'>"; echo "<tr class='tab_bg_1'><td width='120'>" . __('By hardware') . "</td>"; echo "<td>"; NetworkEquipment::dropdown(array('name' => 'switch')); echo "</td><td class='center' width='120'>"; echo "<input type='submit' value=\"" . __s('Display report') . "\" class='submit'>"; echo "</td></tr>"; echo "</table>"; Html::closeForm(); if (countElementsInTableForMyEntities("glpi_netpoints") > 0) { echo "<form name='form3' method='post' action='report.netpoint.list.php'>"; echo "<table class='tab_cadre' width='500'>"; echo "<tr class='tab_bg_1'><td width='120'>" . __('By network outlet') . "</td>"; echo "<td>"; Netpoint::dropdownNetpoint("prise", 0, -1, 1, $_SESSION["glpiactive_entity"]); echo "</td><td class='center' width='120'>"; echo "<input type='submit' value=\"" . __s('Display report') . "\" class='submit'>"; echo "</td></tr>"; echo "</table>"; Html::closeForm(); } Html::footer();
/** * @see NetworkPortInstantiation::getPeerInstantiationHTMLTable() **/ protected function getPeerInstantiationHTMLTable(NetworkPort $netport, HTMLTableRow $row, HTMLTableCell $father = NULL, array $options = array()) { DeviceNetworkCard::getHTMLTableCellsForItem($row, $this, $father, $options); if (!empty($this->fields['speed'])) { $row->addCell($row->getHeaderByName('Instantiation', 'speed'), self::getPortSpeed($this->fields["speed"]), $father); } if (!empty($this->fields['type'])) { $row->addCell($row->getHeaderByName('Instantiation', 'type'), self::getPortTypeName($this->fields["type"]), $father); } parent::getInstantiationHTMLTable($netport, $row, $father, $options); Netpoint::getHTMLTableCellsForItem($row, $this, $father, $options); }
GLPI is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GLPI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GLPI. If not, see <http://www.gnu.org/licenses/>. -------------------------------------------------------------------------- */ /** @file * @brief */ include '../inc/includes.php'; Session::checkRight("reports", READ); if (isset($_POST["locations_id"]) && $_POST["locations_id"]) { Html::header(Report::getTypeName(Session::getPluralNumber()), $_SERVER['PHP_SELF'], "tools", "report"); Report::title(); // Titre $name = Dropdown::getDropdownName("glpi_locations", $_POST["locations_id"]); echo "<div class='center spaced'><h2>" . sprintf(__('Network report by location: %s'), $name) . "</h2></div>"; Report::reportForNetworkInformations("`glpi_locations`\n INNER JOIN `glpi_netpoints`\n ON (`glpi_netpoints`.`locations_id`\n = `glpi_locations`.`id`)\n INNER JOIN `glpi_networkportethernets`\n ON (`glpi_networkportethernets`.`netpoints_id`\n = `glpi_netpoints`.`id`)", "PORT_1.`id` = `glpi_networkportethernets`.`networkports_id`", getRealQueryForTreeItem("glpi_locations", $_POST["locations_id"]), "`glpi_locations`.`completename`, PORT_1.`name`", "`glpi_netpoints`.`name` AS extra, ", Netpoint::getTypeName()); Html::footer(); } else { Html::redirect($CFG_GLPI['root_doc'] . "/front/report.networking.php"); }
/** * Get netwok ports for an object * for an authenticated user * * @param $protocol the commonication protocol used * @param $item_type : type of the item * @param $item_id : ID of the item * @param $id2name : translate id of dropdown to name * **/ static function getItemNetworkports($protocol, $item_type, $item_id, $id2name = false) { global $DB; $item = new $item_type(); $resp = array(); if ($item->getFromDB($item_id) && $item->canView()) { //Get all ports for the object $ports = getAllDatasFromTable('glpi_networkports', "`itemtype`='{$item_type}' AND `items_id`='{$item_id}'"); foreach ($ports as $port) { if ($id2name) { if ($port['networkinterfaces_id'] > 0) { $port['networkinterfaces_name'] = Html::clean(Dropdown::getDropdownName('glpi_networkinterfaces', $port['networkinterfaces_id'])); } } if ($port['netpoints_id'] > 0) { //Get netpoint informations $netpoint = new Netpoint(); $netpoint->getFromDB($port['netpoints_id']); if ($id2name) { $netpoint->fields['location_name'] = Html::clean(Dropdown::getDropdownName('glpi_locations', $netpoint->fields['locations_id'])); } $port['netpoints'][$netpoint->fields['id']] = $netpoint->fields; } //Get VLANS $vlan = new NetworkPort_Vlan(); $tmp = new Vlan(); foreach ($vlan->getVlansForNetworkPort($port['id']) as $vlans_id) { $tmp->getFromDB($vlans_id); $port['vlans'][$tmp->fields['id']] = $tmp->fields; } $resp[$port['id']] = $port; } } return $resp; }
function showForm($ID, $options = array()) { global $CFG_GLPI, $LANG; if (!isset($options['several'])) { $options['several'] = false; } if (!haveRight("networking", "r")) { return false; } if ($ID > 0) { $this->check($ID, 'r'); } else { $input = array('itemtype' => $options["itemtype"], 'items_id' => $options["items_id"]); // Create item $this->check(-1, 'w', $input); } $type = $this->fields['itemtype']; $link = NOT_AVAILABLE; if (class_exists($this->fields['itemtype'])) { $item = new $this->fields['itemtype'](); $type = $item->getTypeName(); if ($item->getFromDB($this->fields["items_id"])) { $link = $item->getLink(); } else { return false; } } else { // item is mandatory (for entity) return false; } // Ajout des infos deja remplies if (isset($_POST) && !empty($_POST)) { foreach ($netport->fields as $key => $val) { if ($key != 'id' && isset($_POST[$key])) { $netport->fields[$key] = $_POST[$key]; } } } $this->showTabs($ID); $options['entities_id'] = $item->getField('entities_id'); $this->showFormHeader($options); $show_computer_mac = false; if ((!empty($this->fields['itemtype']) || !$options['several']) && $this->fields['itemtype'] == 'Computer') { $show_computer_mac = true; } echo "<tr class='tab_bg_1'><td>{$type} :</td>\n<td>"; if (!($ID > 0)) { echo "<input type='hidden' name='items_id' value='" . $this->fields["items_id"] . "'>\n"; echo "<input type='hidden' name='itemtype' value='" . $this->fields["itemtype"] . "'>\n"; } echo $link . "</td>\n"; $colspan = 9; if ($show_computer_mac) { $colspan += 2; } if (!$options['several']) { $colspan++; } echo "<td rowspan='{$colspan}'>" . $LANG['common'][25] . " :</td>"; echo "<td rowspan='{$colspan}' class='middle'>"; echo "<textarea cols='45' rows='11' name='comment' >" . $this->fields["comment"] . "</textarea>"; echo "</td></tr>\n"; if (!$options['several']) { echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][21] . " :</td>\n"; echo "<td>"; autocompletionTextField($this, "logical_number", array('size' => 5)); echo "</td></tr>\n"; } else { echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][21] . " :</td>\n"; echo "<td>"; echo "<input type='hidden' name='several' value='yes'>"; echo "<input type='hidden' name='logical_number' value=''>\n"; echo $LANG['networking'][47] . " : "; Dropdown::showInteger('from_logical_number', 0, 0, 100); echo " " . $LANG['networking'][48] . " : "; Dropdown::showInteger('to_logical_number', 0, 0, 100); echo "</td></tr>\n"; } echo "<tr class='tab_bg_1'><td>" . $LANG['common'][16] . " :</td>\n"; echo "<td>"; autocompletionTextField($this, "name"); echo "</td></tr>\n"; echo "<tr class='tab_bg_1'><td>" . $LANG['common'][65] . " :</td>\n<td>"; Dropdown::show('NetworkInterface', array('value' => $this->fields["networkinterfaces_id"])); echo "</td></tr>\n"; echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][14] . " :</td>\n<td>"; autocompletionTextField($this, "ip"); echo "</td></tr>\n"; // Show device MAC adresses if ($show_computer_mac) { $comp = new Computer(); $comp->getFromDB($this->fields['items_id']); $macs = Computer_Device::getMacAddr($comp); if (count($macs) > 0) { echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][15] . " :</td>\n<td>"; echo "<select name='pre_mac'>\n"; echo "<option value=''>" . DROPDOWN_EMPTY_VALUE . "</option>\n"; foreach ($macs as $key => $val) { echo "<option value='" . $val . "' >{$val}</option>\n"; } echo "</select></td></tr>\n"; echo "<tr class='tab_bg_2'>"; echo "<td colspan='2' class='center'>" . $LANG['networking'][57]; echo "</td></tr>\n"; } } echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][15] . " :</td>\n<td>"; autocompletionTextField($this, "mac"); echo "</td></tr>\n"; echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][60] . " :</td>\n<td>"; autocompletionTextField($this, "netmask"); echo "</td></tr>\n"; echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][59] . " :</td>\n<td>"; autocompletionTextField($this, "gateway"); echo "</td></tr>\n"; echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][61] . " :</td>\n<td>"; autocompletionTextField($this, "subnet"); echo "</td></tr>\n"; if (!$options['several']) { echo "<tr class='tab_bg_1'><td>" . $LANG['networking'][51] . " :</td>\n"; echo "<td>"; Netpoint::dropdownNetpoint("netpoints_id", $this->fields["netpoints_id"], $item->fields['locations_id'], 1, $item->getEntityID(), $this->fields["itemtype"]); echo "</td></tr>\n"; } $this->showFormButtons($options); $this->addDivForTabs(); }
static function pdfForItem(PluginPdfSimplePDF $pdf, CommonDBTM $item) { global $DB; $ID = $item->getField('id'); $type = get_class($item); $query = "SELECT `glpi_networkports`.`id`\n FROM `glpi_networkports`\n WHERE `items_id` = '" . $ID . "'\n AND `itemtype` = '" . $type . "'\n ORDER BY `name`, `logical_number`"; $pdf->setColumnsSize(100); if ($result = $DB->query($query)) { $nb_connect = $DB->numrows($result); if (!$nb_connect) { $pdf->displayTitle('<b>0 ' . __('No network port found') . '</b>'); } else { $pdf->displayTitle('<b>' . sprintf(__('%1$s: %2$d'), _n('Network port', 'Network ports', $nb_connect), $nb_connect . "</b>")); while ($devid = $DB->fetch_row($result)) { $netport = new NetworkPort(); $netport->getfromDB(current($devid)); $instantiation_type = $netport->fields["instantiation_type"]; $instname = call_user_func(array($instantiation_type, 'getTypeName')); $pdf->displayTitle('<b>' . $instname . '</b>'); $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), '#</b>', $netport->fields["logical_number"])); $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Name') . '</b>', $netport->fields["name"])); $contact = new NetworkPort(); $netport2 = new NetworkPort(); $add = __('Not connected.'); if ($cid = $contact->getContact($netport->fields["id"])) { if ($netport2->getFromDB($cid) && ($device2 = getItemForItemtype($netport2->fields["itemtype"]))) { if ($device2->getFromDB($netport2->fields["items_id"])) { $add = $netport2->getName() . ' ' . __('on') . ' ' . $device2->getName() . ' (' . $device2->getTypeName() . ')'; } } } if ($instantiation_type == 'NetworkPortEthernet') { $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Connected to') . '</b>', $add)); $netportethernet = new NetworkPortEthernet(); $speed = $type = ''; if ($netportethernet->getFromDB($netport->fields['id'])) { $speed = NetworkPortEthernet::getPortSpeed($netportethernet->fields['speed']); $type = NetworkPortEthernet::getPortTypeName($netportethernet->fields['type']); } $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Ethernet port speed') . '</b>', $speed)); $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Ethernet port type') . '</b>', $type)); $netpoint = new Netpoint(); $outlet = ''; if ($netpoint->getFromDB($netportethernet->fields['netpoints_id'])) { $outlet = $netpoint->fields['name']; } $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Network outlet') . '</b>', $outlet)); } $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('MAC') . '</b>', $netport->fields["mac"])); $sqlip = "LEFT JOIN `glpi_networknames`\n ON (`glpi_ipaddresses`.`items_id` = `glpi_networknames`.`id`\n AND `glpi_ipaddresses`.`entities_id`\n = '" . $_SESSION['glpiactive_entity'] . "')\n WHERE `glpi_networknames`.`items_id` = '" . $netport->fields["id"] . "'"; $ipname = ''; $ip = new IPAddress(); if ($ip->getFromDBByQuery($sqlip)) { $ipname = $ip->fields['name']; $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('ip') . '</b>', $ipname)); $sql = "SELECT `glpi_ipaddresses_ipnetworks`.`ipnetworks_id`\n FROM `glpi_ipaddresses_ipnetworks`\n LEFT JOIN `glpi_ipnetworks`\n ON (`glpi_ipaddresses_ipnetworks`.`ipnetworks_id` = `glpi_ipnetworks`.`id`)\n WHERE `glpi_ipaddresses_ipnetworks`.`ipaddresses_id` = '" . $ip->getID() . "'"; $res = $DB->query($sql); if ($res) { while ($row = $DB->fetch_assoc($res)) { $ipnetwork = new IPNetwork(); if ($ipnetwork->getFromDB($row['ipnetworks_id'])) { $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('IP network') . '</b>', $ipnetwork->fields['address'])); $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Subnet mask') . '</b>', $ipnetwork->fields['netmask'])); $pdf->displayLine('<b>' . sprintf(__('%1$s: %2$s'), __('Gateway') . '</b>', $ipnetwork->fields['gateway'])); } } } } } // each port } // Found } // Query $pdf->displaySpace(); }
/** * Print the HTML array of the Netpoint associated to a Location * *@param $ID of the Location * *@return Nothing (display) **/ function showNetpoints($ID) { global $DB, $CFG_GLPI, $LANG; $netpoint = new Netpoint(); $this->check($ID, 'r'); $canedit = $this->can($ID, 'w'); if (isset($_REQUEST["start"])) { $start = $_REQUEST["start"]; } else { $start = 0; } $number = countElementsInTable('glpi_netpoints', "`locations_id`='{$ID}'"); echo "<br><div class='center'>"; if ($number < 1) { echo "<table class='tab_cadre_fixe'>"; echo "<tr><th colspan>" . $LANG['networking'][51] . " - " . $LANG['search'][15] . "</th></tr>"; echo "</table>\n"; } else { printAjaxPager($this->getTreeLink() . " - " . $LANG['networking'][51], $start, $number); if ($canedit) { echo "<form method='post' name='massiveaction_form' id='massiveaction_form' action='" . $CFG_GLPI["root_doc"] . "/front/massiveaction.php'>"; } echo "<table class='tab_cadre_fixe'><tr>"; if ($canedit) { echo "<th width='10'> </th>"; } echo "<th>" . $LANG['common'][16] . "</th>"; // Name echo "<th>" . $LANG['common'][25] . "</th>"; // Comment echo "</tr>\n"; $crit = array('locations_id' => $ID, 'ORDER' => 'name', 'START' => $start, 'LIMIT' => $_SESSION['glpilist_limit']); initNavigateListItems('Netpoint', $this->getTypeName() . "= " . $this->fields['name']); foreach ($DB->request('glpi_netpoints', $crit) as $data) { addToNavigateListItems('Netpoint', $data["id"]); echo "<tr class='tab_bg_1'>"; if ($canedit) { echo "<td><input type='checkbox' name='item[" . $data["id"] . "]' value='1'></td>"; } echo "<td><a href='" . $netpoint->getFormURL(); echo '?id=' . $data['id'] . "'>" . $data['name'] . "</a></td>"; echo "<td>" . $data['comment'] . "</td>"; echo "</tr>\n"; } echo "</table>\n"; if ($canedit) { openArrowMassive("massiveaction_form", true); echo "<input type='hidden' name='itemtype' value='Netpoint'>"; echo "<input type='hidden' name='action' value='delete'>"; closeArrowMassive('massiveaction', $LANG['buttons'][6]); echo "</form>\n"; } } if ($canedit) { // Minimal form for quick input. echo "<form action='" . $netpoint->getFormURL() . "' method='post'>"; echo "<br><table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_2 center'><td class='b'>" . $LANG['common'][87] . "</td>"; echo "<td>" . $LANG['common'][16] . " : "; autocompletionTextField($this, "name", array('value' => '')); echo "<input type='hidden' name='entities_id' value='" . $_SESSION['glpiactive_entity'] . "'>"; echo "<input type='hidden' name='locations_id' value='{$ID}'></td>"; echo "<td><input type='submit' name='add' value=\"" . $LANG['buttons'][8] . "\" class='submit'>"; echo "</td></tr>\n"; echo "</table></form>\n"; // Minimal form for massive input. echo "<form action='" . $netpoint->getFormURL() . "' method='post'>"; echo "<table class='tab_cadre_fixe'>"; echo "<tr class='tab_bg_2 center'><td class='b'>" . $LANG['common'][87] . "</td>"; echo "<td>" . $LANG['common'][16] . " : "; echo "<input type='text' maxlength='100' size='10' name='_before'> "; Dropdown::showInteger('_from', 0, 0, 400); echo " --> "; Dropdown::showInteger('_to', 0, 0, 400); echo " <input type='text' maxlength='100' size='10' name='_after'><br>"; echo "<input type='hidden' name='entities_id' value='" . $_SESSION['glpiactive_entity'] . "'>"; echo "<input type='hidden' name='locations_id' value='{$ID}'></td>"; echo "<input type='hidden' name='_method' value='addMulti'></td>"; echo "<td><input type='submit' name='execute' value=\"" . $LANG['buttons'][8] . "\"\n class='submit'>"; echo "</td></tr>\n"; echo "</table></form>\n"; } echo "</div>\n"; }
/** * Print out an HTML "<select>" for a dropdown with preselected value * * * @param $myname the name of the HTML select * @param $value the preselected value we want * @param $locations_id default location ID for search * @param $display_comment display the comment near the dropdown * @param $entity_restrict Restrict to a defined entity * @param $devtype * @return nothing (display the select box) * */ static function dropdownNetpoint($myname, $value = 0, $locations_id = -1, $display_comment = 1, $entity_restrict = -1, $devtype = -1) { global $CFG_GLPI, $LANG; $rand = mt_rand(); $name = "------"; $comment = ""; $limit_length = $_SESSION["glpidropdown_chars_limit"]; if (empty($value)) { $value = 0; } if ($value > 0) { $tmpname = Dropdown::getDropdownName("glpi_netpoints", $value, 1); if ($tmpname["name"] != " ") { $name = $tmpname["name"]; $comment = $tmpname["comment"]; $limit_length = max(utf8_strlen($name), $_SESSION["glpidropdown_chars_limit"]); } } $use_ajax = false; if ($CFG_GLPI["use_ajax"]) { if ($locations_id < 0 || $devtype == 'NetworkEquipment') { $nb = countElementsInTableForEntity("glpi_netpoints", $entity_restrict); } else { if ($locations_id > 0) { $nb = countElementsInTable("glpi_netpoints", "locations_id={$locations_id} "); } else { $nb = countElementsInTable("glpi_netpoints", "locations_id=0 " . getEntitiesRestrictRequest(" AND ", "glpi_netpoints", '', $entity_restrict)); } } if ($nb > $CFG_GLPI["ajax_limit_count"]) { $use_ajax = true; } } $params = array('searchText' => '__VALUE__', 'value' => $value, 'locations_id' => $locations_id, 'myname' => $myname, 'limit' => $limit_length, 'comment' => $display_comment, 'rand' => $rand, 'entity_restrict' => $entity_restrict, 'devtype' => $devtype); $default = "<select name='{$myname}'><option value='{$value}'>{$name}</option></select>"; ajaxDropdown($use_ajax, "/ajax/dropdownNetpoint.php", $params, $default, $rand); // Display comment if ($display_comment) { showToolTip($comment); $item = new Netpoint(); if ($item->canCreate()) { echo "<img alt='' title=\"" . $LANG['buttons'][8] . "\" src='" . $CFG_GLPI["root_doc"] . "/pics/add_dropdown.png' style='cursor:pointer; margin-left:2px;' " . "onClick=\"var w = window.open('" . $item->getFormURL() . "?popup=1&rand={$rand}' ,'glpipopup', 'height=400, " . "width=1000, top=100, left=100, scrollbars=yes' );w.focus();\">"; } } return $rand; }