2 /* vim: set expandtab sw=4 ts=4 sts=4: */
10 require_once './libraries/common.inc.php';
11 require_once './libraries/Table.class.php';
13 define('TABLE_MAY_BE_ABSENT', true);
14 require './libraries/tbl_common.php';
15 $url_query .= '&goto=tbl_tracking.php&back=tbl_tracking.php';
16 $url_params['goto'] = 'tbl_tracking.php';;
17 $url_params['back'] = 'tbl_tracking.php';
19 // Get relation settings
20 require_once './libraries/relation.lib.php';
22 // Init vars for tracking report
23 if (isset($_REQUEST['report']) ||
isset($_REQUEST['report_export'])) {
24 $data = PMA_Tracker
::getTrackedData($_REQUEST['db'], $_REQUEST['table'], $_REQUEST['version']);
26 $selection_schema = false;
27 $selection_data = false;
28 $selection_both = false;
30 if (! isset($_REQUEST['logtype'])) {
31 $_REQUEST['logtype'] = 'schema_and_data';
33 if ($_REQUEST['logtype'] == 'schema') {
34 $selection_schema = true;
35 } elseif($_REQUEST['logtype'] == 'data') {
36 $selection_data = true;
38 $selection_both = true;
40 if (! isset($_REQUEST['date_from'])) {
41 $_REQUEST['date_from'] = $data['date_from'];
43 if (! isset($_REQUEST['date_to'])) {
44 $_REQUEST['date_to'] = $data['date_to'];
46 if (! isset($_REQUEST['users'])) {
47 $_REQUEST['users'] = '*';
49 $filter_ts_from = strtotime($_REQUEST['date_from']);
50 $filter_ts_to = strtotime($_REQUEST['date_to']);
51 $filter_users = array_map('trim', explode(',', $_REQUEST['users']));
55 if (isset($_REQUEST['report_export'])) {
58 * Filters tracking entries
60 * @param array the entries to filter
61 * @param string "from" date
62 * @param string "to" date
65 * @return array filtered entries
68 function PMA_filter_tracking($data, $filter_ts_from, $filter_ts_to, $filter_users) {
69 $tmp_entries = array();
71 foreach( $data as $entry ) {
72 $timestamp = strtotime($entry['date']);
74 if ($timestamp >= $filter_ts_from && $timestamp <= $filter_ts_to &&
75 ( in_array('*', $filter_users) ||
in_array($entry['username'], $filter_users) ) ) {
76 $tmp_entries[] = array( 'id' => $id,
77 'timestamp' => $timestamp,
78 'username' => $entry['username'],
79 'statement' => $entry['statement']
88 // Filtering data definition statements
89 if ($_REQUEST['logtype'] == 'schema' ||
$_REQUEST['logtype'] == 'schema_and_data') {
90 $entries = array_merge($entries, PMA_filter_tracking($data['ddlog'], $filter_ts_from, $filter_ts_to, $filter_users));
93 // Filtering data manipulation statements
94 if ($_REQUEST['logtype'] == 'data' ||
$_REQUEST['logtype'] == 'schema_and_data') {
95 $entries = array_merge($entries, PMA_filter_tracking($data['dmlog'], $filter_ts_from, $filter_ts_to, $filter_users));
99 foreach ($entries as $key => $row) {
100 $ids[$key] = $row['id'];
101 $timestamps[$key] = $row['timestamp'];
102 $usernames[$key] = $row['username'];
103 $statements[$key] = $row['statement'];
106 array_multisort($timestamps, SORT_ASC
, $ids, SORT_ASC
, $usernames, SORT_ASC
, $statements, SORT_ASC
, $entries);
110 // Export as file download
111 if (isset($_REQUEST['report_export']) && $_REQUEST['export_type'] == 'sqldumpfile') {
112 @ini_set
('url_rewriter.tags','');
114 $dump = "# " . sprintf(__('Tracking report for table `%s`'), htmlspecialchars($_REQUEST['table'])) . "\n" .
115 "# " . date('Y-m-d H:i:s') . "\n";
116 foreach($entries as $entry) {
117 $dump .= $entry['statement'];
119 $filename = 'log_' . htmlspecialchars($_REQUEST['table']) . '.sql';
120 header('Content-Type: text/x-sql');
121 header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
122 header('Content-Disposition: attachment; filename="' . $filename . '"');
123 if (PMA_USR_BROWSER_AGENT
== 'IE') {
124 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
125 header('Pragma: public');
127 header('Pragma: no-cache');
128 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
137 * Gets tables informations
141 * Displays top menu links
143 require_once './libraries/tbl_links.inc.php';
150 // Create tracking version
151 if (isset($_REQUEST['submit_create_version'])) {
154 if ($_REQUEST['alter_table'] == true) {
155 $tracking_set .= 'ALTER TABLE,';
157 if ($_REQUEST['rename_table'] == true) {
158 $tracking_set .= 'RENAME TABLE,';
160 if ($_REQUEST['create_table'] == true) {
161 $tracking_set .= 'CREATE TABLE,';
163 if ($_REQUEST['drop_table'] == true) {
164 $tracking_set .= 'DROP TABLE,';
166 if ($_REQUEST['create_index'] == true) {
167 $tracking_set .= 'CREATE INDEX,';
169 if ($_REQUEST['drop_index'] == true) {
170 $tracking_set .= 'DROP INDEX,';
172 if ($_REQUEST['insert'] == true) {
173 $tracking_set .= 'INSERT,';
175 if ($_REQUEST['update'] == true) {
176 $tracking_set .= 'UPDATE,';
178 if ($_REQUEST['delete'] == true) {
179 $tracking_set .= 'DELETE,';
181 if ($_REQUEST['truncate'] == true) {
182 $tracking_set .= 'TRUNCATE,';
184 $tracking_set = rtrim($tracking_set, ',');
186 if (PMA_Tracker
::createVersion($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version'], $tracking_set )) {
187 $msg = PMA_Message
::success(sprintf(__('Version %s is created, tracking for %s.%s is activated.'), $_REQUEST['version'], $GLOBALS['db'], $GLOBALS['table']));
192 // Deactivate tracking
193 if (isset($_REQUEST['submit_deactivate_now'])) {
194 if (PMA_Tracker
::deactivateTracking($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version'])) {
195 $msg = PMA_Message
::success(sprintf(__('Tracking for %s.%s , version %s is deactivated.'), $GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']));
201 if (isset($_REQUEST['submit_activate_now'])) {
202 if (PMA_Tracker
::activateTracking($GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version'])) {
203 $msg = PMA_Message
::success(sprintf(__('Tracking for %s.%s , version %s is activated.'), $GLOBALS['db'], $GLOBALS['table'], $_REQUEST['version']));
208 // Export as SQL execution
209 if (isset($_REQUEST['report_export']) && $_REQUEST['export_type'] == 'execution') {
210 foreach($entries as $entry) {
211 $sql_result = PMA_DBI_query( "/*NOTRACK*/\n" . $entry['statement'] );
213 $msg = PMA_Message
::success(__('SQL statements executed.'));
217 // Export as SQL dump
218 if (isset($_REQUEST['report_export']) && $_REQUEST['export_type'] == 'sqldump')
220 $new_query = "# " . __('You can execute the dump by creating and using a temporary database. Please ensure that you have the privileges to do so.') . "\n" .
221 "# " . __('Comment out these two lines if you do not need them.') . "\n" .
223 "CREATE database IF NOT EXISTS pma_temp_db; \n" .
224 "USE pma_temp_db; \n" .
227 foreach($entries as $entry) {
228 $new_query .= $entry['statement'];
230 $msg = PMA_Message
::success(__('SQL statements exported. Please copy the dump or execute it.'));
234 $table_temp = $table;
237 $GLOBALS['js_include'][] = 'functions.js';
238 require_once './libraries/sql_query_form.lib.php';
240 PMA_sqlQueryForm($new_query, 'sql');
243 $table = $table_temp;
249 if (isset($_REQUEST['snapshot'])) {
251 <h3
><?php
echo __('Structure snapshot');?
> [<a href
="tbl_tracking.php?<?php echo $url_query;?>"><?php
echo __('Close');?
></a
>]</h3
>
253 $data = PMA_Tracker
::getTrackedData($_REQUEST['db'], $_REQUEST['table'], $_REQUEST['version']);
255 // Get first DROP TABLE and CREATE TABLE statements
256 $drop_create_statements = $data['ddlog'][0]['statement'];
258 if (strstr($data['ddlog'][0]['statement'], 'DROP TABLE')) {
259 $drop_create_statements .= $data['ddlog'][1]['statement'];
262 PMA_showMessage(sprintf(__('Version %s snapshot (SQL code)'), $_REQUEST['version']), $drop_create_statements);
264 // Unserialize snapshot
265 $temp = unserialize($data['schema_snapshot']);
266 $columns = $temp['COLUMNS'];
267 $indexes = $temp['INDEXES'];
269 <h3
><?php
echo __('Structure');?
></h3
>
270 <table id
="tablestructure" class="data">
273 <th
><?php
echo __('Column'); ?
></th
>
274 <th
><?php
echo __('Type'); ?
></th
>
275 <th
><?php
echo __('Collation'); ?
></th
>
276 <th
><?php
echo __('Null'); ?
></th
>
277 <th
><?php
echo __('Default'); ?
></th
>
278 <th
><?php
echo __('Extra'); ?
></th
>
279 <th
><?php
echo __('Comment'); ?
></th
>
285 foreach($columns as $field_index => $field) {
287 <tr
class="<?php echo $style; ?>">
289 if ($field['Key'] == 'PRI') {
290 echo '<td><b><u>' . $field['Field'] . '</u></b></td>' . "\n";
292 echo '<td><b>' . $field['Field'] . '</b></td>' . "\n";
295 <td
><?php
echo $field['Type'];?
></td
>
296 <td
><?php
echo $field['Collation'];?
></td
>
297 <td
><?php
echo $field['Null'];?
></td
>
298 <td
><?php
echo $field['Default'];?
></td
>
299 <td
><?php
echo $field['Extra'];?
></td
>
300 <td
><?php
echo $field['Comment'];?
></td
>
303 if ($style == 'even') {
314 if (count($indexes) > 0) {
316 <h3
><?php
echo __('Indexes');?
></h3
>
317 <table id
="tablestructure_indexes" class="data">
320 <th
><?php
echo __('Keyname');?
></th
>
321 <th
><?php
echo __('Type');?
></th
>
322 <th
><?php
echo __('Unique');?
></th
>
323 <th
><?php
echo __('Packed');?
></th
>
324 <th
><?php
echo __('Column');?
></th
>
325 <th
><?php
echo __('Cardinality');?
></th
>
326 <th
><?php
echo __('Collation');?
></th
>
327 <th
><?php
echo __('Null');?
></th
>
328 <th
><?php
echo __('Comment');?
></th
>
333 foreach ($indexes as $indexes_index => $index) {
334 if ($index['Non_unique'] == 0) {
335 $str_unique = __('Yes');
337 $str_unique = __('No');
339 if ($index['Packed'] != '') {
340 $str_packed = __('Yes');
342 $str_packed = __('No');
345 <tr
class="<?php echo $style; ?>">
346 <td
><b
><?php
echo $index['Key_name'];?
></b
></td
>
347 <td
><?php
echo $index['Index_type'];?
></td
>
348 <td
><?php
echo $str_unique;?
></td
>
349 <td
><?php
echo $str_packed;?
></td
>
350 <td
><?php
echo $index['Column_name'];?
></td
>
351 <td
><?php
echo $index['Cardinality'];?
></td
>
352 <td
><?php
echo $index['Collation'];?
></td
>
353 <td
><?php
echo $index['Null'];?
></td
>
354 <td
><?php
echo $index['Comment'];?
></td
>
357 if ($style == 'even') {
372 // end of snapshot report
377 if (isset($_REQUEST['report']) ||
isset($_REQUEST['report_export'])) {
379 <h3
><?php
echo __('Tracking report');?
> [<a href
="tbl_tracking.php?<?php echo $url_query;?>"><?php
echo __('Close');?
></a
>]</h3
>
381 <small
><?php
echo __('Tracking statements') . ' ' . $data['tracking']; ?
></small
><br
/>
384 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
387 $str1 = '<select name="logtype">' .
388 '<option value="schema"' . ($selection_schema ?
' selected="selected"' : '') . '>' . __('Structure only') . '</option>' .
389 '<option value="data"' . ($selection_data ?
' selected="selected"' : ''). '>' . __('Data only') . '</option>' .
390 '<option value="schema_and_data"' . ($selection_both ?
' selected="selected"' : '') . '>' . __('Structure and data') . '</option>' .
392 $str2 = '<input type="text" name="date_from" value="' . $_REQUEST['date_from'] . '" size="19" />';
393 $str3 = '<input type="text" name="date_to" value="' . $_REQUEST['date_to'] . '" size="19" />';
394 $str4 = '<input type="text" name="users" value="' . $_REQUEST['users'] . '" />';
395 $str5 = '<input type="submit" name="list_report" value="' . __('Go') . '" />';
397 printf(__('Show %s with dates from %s to %s by user %s %s'), $str1, $str2, $str3, $str4, $str5);
401 * First, list tracked data definition statements
404 if ($selection_schema ||
$selection_both ) {
406 <table id
="ddl_versions" class="data" width
="100%">
409 <th width
="18">#</th>
410 <th width
="100"><?php
echo __('Date');?
></th
>
411 <th width
="60"><?php
echo __('Username');?
></th
>
412 <th
><?php
echo __('Data definition statement');?
></th
>
418 foreach ($data['ddlog'] as $entry) {
419 if (strlen($entry['statement']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
420 $statement = substr($entry['statement'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
422 $statement = PMA_formatSql(PMA_SQP_parse($entry['statement']));
424 $timestamp = strtotime($entry['date']);
426 if ($timestamp >= $filter_ts_from && $timestamp <= $filter_ts_to &&
427 ( in_array('*', $filter_users) ||
in_array($entry['username'], $filter_users) ) ) {
429 <tr
class="<?php echo $style; ?>">
430 <td
><small
><?php
echo $i;?
></small
></td
>
431 <td
><small
><?php
echo $entry['date'];?
></small
></td
>
432 <td
><small
><?php
echo $entry['username']; ?
></small
></td
>
433 <td
><?php
echo $statement; ?
></td
>
436 if ($style == 'even') {
452 * Secondly, list tracked data manipulation statements
455 if (($selection_data ||
$selection_both) && count($data['dmlog']) > 0) {
457 <table id
="dml_versions" class="data" width
="100%">
460 <th width
="18">#</th>
461 <th width
="100"><?php
echo __('Date');?
></th
>
462 <th width
="60"><?php
echo __('Username');?
></th
>
463 <th
><?php
echo __('Data manipulation statement');?
></th
>
469 foreach ($data['dmlog'] as $entry) {
470 if (strlen($entry['statement']) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
471 $statement = substr($entry['statement'], 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
473 $statement = PMA_formatSql(PMA_SQP_parse($entry['statement']));
475 $timestamp = strtotime($entry['date']);
477 if ($timestamp >= $filter_ts_from && $timestamp <= $filter_ts_to &&
478 ( in_array('*', $filter_users) ||
in_array($entry['username'], $filter_users) ) ) {
480 <tr
class="<?php echo $style; ?>">
481 <td
><small
><?php
echo $i; ?
></small
></td
>
482 <td
><small
><?php
echo $entry['date']; ?
></small
></td
>
483 <td
><small
><?php
echo $entry['username']; ?
></small
></td
>
484 <td
><?php
echo $statement; ?
></td
>
487 if ($style == 'even') {
502 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
504 printf(__('Show %s with dates from %s to %s by user %s %s'), $str1, $str2, $str3, $str4, $str5);
506 $str_export1 = '<select name="export_type">' .
507 '<option value="sqldumpfile">' . __('SQL dump (file download)') . '</option>' .
508 '<option value="sqldump">' . __('SQL dump') . '</option>' .
509 '<option value="execution" onclick="alert(\'' . PMA_escapeJsString(__('This option will replace your table and contained data.')) .'\')">' . __('SQL execution') . '</option>' .
512 $str_export2 = '<input type="submit" name="report_export" value="' . __('Go') .'" />';
515 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>&report=true&version=<?php echo $_REQUEST['version'];?>">
516 <input type
="hidden" name
="logtype" value
="<?php echo $_REQUEST['logtype'];?>" />
517 <input type
="hidden" name
="date_from" value
="<?php echo $_REQUEST['date_from'];?>" />
518 <input type
="hidden" name
="date_to" value
="<?php echo $_REQUEST['date_to'];?>" />
519 <input type
="hidden" name
="users" value
="<?php echo $_REQUEST['users'];?>" />
521 echo "<br/>" . sprintf(__('Export as %s'), $str_export1) . $str_export2 . "<br/>";
525 echo "<br/><br/><hr/><br/>\n";
530 * List selectable tables
533 $sql_query = " SELECT DISTINCT db_name, table_name FROM " .
534 PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) . "." .
535 PMA_backquote($GLOBALS['cfg']['Server']['tracking']) .
536 " WHERE " . PMA_backquote('db_name') . " = '" . PMA_sqlAddslashes($GLOBALS['db']) . "' " .
537 " ORDER BY ". PMA_backquote('db_name') . ", " . PMA_backquote('table_name');
539 $sql_result = PMA_query_as_controluser($sql_query);
541 if (PMA_DBI_num_rows($sql_result) > 0) {
543 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query;?>">
544 <select name
="table">
546 while ($entries = PMA_DBI_fetch_array($sql_result)) {
547 if (PMA_Tracker
::isTracked($entries['db_name'], $entries['table_name'])) {
548 $status = ' (' . __('active') . ')';
550 $status = ' (' . __('not active') . ')';
552 if ($entries['table_name'] == $_REQUEST['table']) {
553 $s = ' selected="selected"';
557 echo '<option value="' . htmlspecialchars($entries['table_name']) . '"' . $s . '>' . htmlspecialchars($entries['db_name']) . ' . ' . htmlspecialchars($entries['table_name']) . $status . '</option>' . "\n";
561 <input type
="submit" name
="show_versions_submit" value
="<?php echo __('Show versions');?>" />
570 * List versions of current table
573 $sql_query = " SELECT * FROM " .
574 PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) . "." .
575 PMA_backquote($GLOBALS['cfg']['Server']['tracking']) .
576 " WHERE " . PMA_backquote('db_name') . " = '" . PMA_sqlAddslashes($_REQUEST['db']) . "' ".
577 " AND " . PMA_backquote('table_name') . " = '" . PMA_sqlAddslashes($_REQUEST['table']) ."' ".
578 " ORDER BY ". PMA_backquote('version') . " DESC ";
580 $sql_result = PMA_query_as_controluser($sql_query);
583 $maxversion = PMA_DBI_fetch_array($sql_result);
584 $last_version = $maxversion['version'];
586 if ($last_version > 0) {
588 <table id
="versions" class="data">
591 <th
><?php
echo __('Database');?
></th
>
592 <th
><?php
echo __('Table');?
></th
>
593 <th
><?php
echo __('Version');?
></th
>
594 <th
><?php
echo __('Created');?
></th
>
595 <th
><?php
echo __('Updated');?
></th
>
596 <th
><?php
echo __('Status');?
></th
>
597 <th
><?php
echo __('Show');?
></th
>
603 PMA_DBI_data_seek($sql_result, 0);
604 while($version = PMA_DBI_fetch_array($sql_result)) {
605 if ($version['tracking_active'] == 1) {
606 $version_status = __('active');
608 $version_status = __('not active');
610 if (($version['version'] == $last_version) && ($version_status == __('not active'))) {
611 $tracking_active = false;
613 if (($version['version'] == $last_version) && ($version_status == __('active'))) {
614 $tracking_active = true;
617 <tr
class="<?php echo $style;?>">
618 <td
><?php
echo htmlspecialchars($version['db_name']);?
></td
>
619 <td
><?php
echo htmlspecialchars($version['table_name']);?
></td
>
620 <td
><?php
echo $version['version'];?
></td
>
621 <td
><?php
echo $version['date_created'];?
></td
>
622 <td
><?php
echo $version['date_updated'];?
></td
>
623 <td
><?php
echo $version_status;?
></td
>
624 <td
> <a href
="tbl_tracking.php?<?php echo $url_query;?>&report=true&version=<?php echo $version['version'];?>"><?php
echo __('Tracking report');?
></a
> |
<a href
="tbl_tracking.php?<?php echo $url_query;?>&snapshot=true&version=<?php echo $version['version'];?>"><?php
echo __('Structure snapshot');?
></a
></td
>
627 if ($style == 'even') {
636 <?php
if ($tracking_active == true) {?
>
637 <div id
="div_deactivate_tracking">
638 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
640 <legend
><?php
printf(__('Deactivate tracking for %s.%s'), $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
641 <input type
="hidden" name
="version" value
="<?php echo $last_version; ?>" />
642 <input type
="submit" name
="submit_deactivate_now" value
="<?php echo __('Deactivate now'); ?>" />
649 <?php
if ($tracking_active == false) {?
>
650 <div id
="div_activate_tracking">
651 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
653 <legend
><?php
printf(__('Activate tracking for %s.%s'), $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
654 <input type
="hidden" name
="version" value
="<?php echo $last_version; ?>" />
655 <input type
="submit" name
="submit_activate_now" value
="<?php echo __('Activate now'); ?>" />
664 <div id
="div_create_version">
665 <form method
="post" action
="tbl_tracking.php?<?php echo $url_query; ?>">
666 <?php
echo PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']); ?
>
668 <legend
><?php
printf(__('Create version %s of %s.%s'), ($last_version +
1), $GLOBALS['db'], $GLOBALS['table']); ?
></legend
>
670 <input type
="hidden" name
="version" value
="<?php echo ($last_version + 1); ?>" />
672 <p
><?php
echo __('Track these data definition statements:');?
></p
>
673 <input type
="checkbox" name
="alter_table" value
="true" checked
="checked" /> ALTER TABLE
<br
/>
674 <input type
="checkbox" name
="rename_table" value
="true" checked
="checked" /> RENAME TABLE
<br
/>
675 <input type
="checkbox" name
="create_table" value
="true" checked
="checked" /> CREATE TABLE
<br
/>
676 <input type
="checkbox" name
="drop_table" value
="true" checked
="checked" /> DROP TABLE
<br
/>
678 <input type
="checkbox" name
="create_index" value
="true" checked
="checked" /> CREATE INDEX
<br
/>
679 <input type
="checkbox" name
="drop_index" value
="true" checked
="checked" /> DROP INDEX
<br
/>
680 <p
><?php
echo __('Track these data manipulation statements:');?
></p
>
681 <input type
="checkbox" name
="insert" value
="true" checked
="checked" /> INSERT
<br
/>
682 <input type
="checkbox" name
="update" value
="true" checked
="checked" /> UPDATE
<br
/>
683 <input type
="checkbox" name
="delete" value
="true" checked
="checked" /> DELETE
<br
/>
684 <input type
="checkbox" name
="truncate" value
="true" checked
="checked" /> TRUNCATE
<br
/>
687 <fieldset
class="tblFooters">
688 <input type
="submit" name
="submit_create_version" value
="<?php echo __('Create version'); ?>" />
693 <br
class="clearfloat"/>
697 * Displays the footer
699 require_once './libraries/footer.inc.php';