summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchriskl2005-05-02 15:47:23 +0000
committerchriskl2005-05-02 15:47:23 +0000
commit23b05fc8823bbab2f79480968c2783266df3d971 (patch)
treed5aeb31dff8a4622a01e0f6855984ebb8addf28b
parent08a01fa1ac80ed21f0cdae5db2d562e414db4509 (diff)
Merge DEV_TREE into HEAD. May as well get this ball rolling.
-rw-r--r--CREDITS2
-rw-r--r--HISTORY5
-rw-r--r--TRANSLATORS8
-rw-r--r--aggregates.php24
-rw-r--r--all_db.php47
-rw-r--r--bottombar.php16
-rw-r--r--browser.php355
-rw-r--r--classes/ArrayRecordSet.php32
-rw-r--r--classes/Misc.php659
-rw-r--r--classes/Reports.php15
-rwxr-xr-xclasses/database/Postgres.php18
-rw-r--r--classes/database/Postgres71.php12
-rw-r--r--classes/database/Postgres72.php6
-rw-r--r--classes/database/Postgres73.php6
-rw-r--r--classes/database/Postgres80.php12
-rw-r--r--constraints.php10
-rw-r--r--conversions.php24
-rwxr-xr-xdatabase.php101
-rw-r--r--dataexport.php61
-rw-r--r--dbexport.php46
-rw-r--r--display.php8
-rw-r--r--domains.php31
-rw-r--r--functions.php56
-rw-r--r--groups.php11
-rw-r--r--images/themes/default/I.pngbin0 -> 105 bytes
-rw-r--r--images/themes/default/L.pngbin0 -> 110 bytes
-rw-r--r--images/themes/default/Lminus.pngbin0 -> 125 bytes
-rw-r--r--images/themes/default/Lplus.pngbin0 -> 130 bytes
-rw-r--r--images/themes/default/T.pngbin0 -> 109 bytes
-rw-r--r--images/themes/default/Tminus.pngbin0 -> 126 bytes
-rw-r--r--images/themes/default/Tplus.pngbin0 -> 131 bytes
-rw-r--r--images/themes/default/blank.pngbin0 -> 100 bytes
-rw-r--r--images/themes/default/file.pngbin0 -> 209 bytes
-rw-r--r--images/themes/default/folder.pngbin0 -> 185 bytes
-rw-r--r--images/themes/default/folderOpen.pngbin0 -> 205 bytes
-rw-r--r--images/themes/default/loading.gifbin0 -> 834 bytes
-rw-r--r--images/themes/default/root.pngbin0 -> 185 bytes
-rw-r--r--images/themes/default/title.pngbin3726 -> 3679 bytes
-rwxr-xr-xindex.php35
-rw-r--r--indexes.php4
-rwxr-xr-xintro.php39
-rwxr-xr-xlang/english.php14
-rw-r--r--lang/translations.php73
-rw-r--r--libraries/decorator.inc.php206
-rw-r--r--libraries/errorhandler.inc.php4
-rw-r--r--libraries/lib.inc.php152
-rwxr-xr-xlogin.php196
-rw-r--r--opclasses.php27
-rw-r--r--operators.php38
-rw-r--r--redirect.php7
-rw-r--r--reports.php27
-rw-r--r--sequences.php31
-rw-r--r--servers.php133
-rw-r--r--sqledit.php118
-rw-r--r--tables.php35
-rwxr-xr-xtablespaces.php20
-rw-r--r--tblproperties.php21
-rw-r--r--themes/default/global.css57
-rwxr-xr-xtopbar.php56
-rw-r--r--triggers.php4
-rw-r--r--types.php47
-rw-r--r--users.php29
-rwxr-xr-xviewproperties.php13
-rw-r--r--views.php36
-rw-r--r--xloadtree/xloadtree2.js534
-rw-r--r--xloadtree/xmlextras.js232
-rw-r--r--xloadtree/xtree2.js1664
67 files changed, 4385 insertions, 1032 deletions
diff --git a/CREDITS b/CREDITS
index 6d4f23d2..45caa9e0 100644
--- a/CREDITS
+++ b/CREDITS
@@ -57,4 +57,4 @@ Contributors
Third Party Libraries
- Highlight.php (Jacob D. Cohen of rafb.net)
-
+- XLoadTree2 (Erik Arvidsson & Emil A Eklund of webfx.eae.net)
diff --git a/HISTORY b/HISTORY
index 9c4f1d42..bc6c3c8c 100644
--- a/HISTORY
+++ b/HISTORY
@@ -15,6 +15,11 @@ Features
* primary key and unique key at table creation (Andreas Huber)
* Add row|statement level options to create trigger for >= 7.4 (Robert Treat)
* Allow altering name (for >= 7.4) and owner (for >= 8.0) of a database (Bryan Encina)
+* Allow login to several servers simultaneously
+* Rearrange frame layout to suit multi-server support
+* New browser tree with dynamically loading branches
+ (Using XLoadTree from http://webfx.eae.net/)
+* Allow language change on the fly
Bugs
* Tree Icons are displayed middle instead of top
diff --git a/TRANSLATORS b/TRANSLATORS
index ba0aad6f..f4bffe6b 100644
--- a/TRANSLATORS
+++ b/TRANSLATORS
@@ -54,11 +54,11 @@ find the rest of these steps too difficult.
language's characters as well as the characters of the language in your
database.
-8. To add your language to phpPgAdmin's login screen, edit the
- libraries/lib.inc.php file and add your language to the $appLangFiles array.
+8. To add your language to phpPgAdmin, edit the lang/translations.php file
+ and add your language to the $appLangFiles array.
You must include the HTML encoded version of your language's name. You can
- get this from the recoded version of your translated strings file. Also,
- edit the login.php and add your language to the list of languages for
+ get this from the recoded version of your translated strings file.
+ Also, add your language to the $availableLanguages array for
browser auto detection.
9. Send your contribution to us. We need the lib.inc.php entry as well as the
diff --git a/aggregates.php b/aggregates.php
index e7ab25a1..81a6d21e 100644
--- a/aggregates.php
+++ b/aggregates.php
@@ -3,7 +3,7 @@
/**
* Manage aggregates in a database
*
- * $Id: aggregates.php,v 1.10 2004/09/20 14:41:38 jollytoad Exp $
+ * $Id: aggregates.php,v 1.11 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -46,6 +46,28 @@
$misc->printTable($aggregates, $columns, $actions, $lang['strnoaggregates']);
}
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $aggregates = &$data->getAggregates();
+
+ $proto = concat(field('proname'), ' (', field('proargtypes'), ')');
+
+ $attrs = array(
+ 'text' => $proto,
+ 'icon' => 'functions',
+ 'toolTip'=> field('aggcomment'),
+ );
+
+ $misc->printTreeXML($aggregates, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['straggregates']);
$misc->printBody();
diff --git a/all_db.php b/all_db.php
index fe763240..28eb728d 100644
--- a/all_db.php
+++ b/all_db.php
@@ -3,7 +3,7 @@
/**
* Manage databases within a server
*
- * $Id: all_db.php,v 1.37 2005/04/30 18:01:58 soranzo Exp $
+ * $Id: all_db.php,v 1.38 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -82,8 +82,8 @@
echo "<p>", sprintf($lang['strconfdropdatabase'], $misc->printVal($_REQUEST['dropdatabase'])), "</p>\n";
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
- echo "<input type=\"hidden\" name=\"dropdatabase\" value=\"",
- htmlspecialchars($_REQUEST['dropdatabase']), "\" />\n";
+ echo "<input type=\"hidden\" name=\"server\" value=\"", htmlspecialchars($_REQUEST['server']), "\" />\n";
+ echo "<input type=\"hidden\" name=\"dropdatabase\" value=\"", htmlspecialchars($_REQUEST['dropdatabase']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
echo "</form>\n";
@@ -159,6 +159,7 @@
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
+ echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
@@ -229,7 +230,7 @@
echo "<br/><input type=\"radio\" name=\"output\" value=\"download\" />{$lang['strdownload']}</p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
- echo "<p><input type=\"hidden\" name=\"mode\" value=\"cluster\" />\n";
+ echo "<p><input type=\"hidden\" name=\"subject\" value=\"server\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
@@ -277,17 +278,17 @@
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => 'redirect.php?section=database&amp;',
+ 'url' => "redirect.php?subject=database&amp;{$misc->href}&amp;",
'vars' => array('database' => 'datname'),
),
'drop' => array(
'title' => $lang['strdrop'],
- 'url' => "{$PHP_SELF}?action=confirm_drop&amp;subject=database&amp;",
+ 'url' => "{$PHP_SELF}?action=confirm_drop&amp;subject=database&amp;{$misc->href}&amp;",
'vars' => array('dropdatabase' => 'datname'),
),
'privileges' => array(
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?subject=database&amp;",
+ 'url' => "privileges.php?subject=database&amp;{$misc->href}&amp;",
'vars' => array('database' => 'datname'),
)
);
@@ -304,10 +305,40 @@
$misc->printTable($databases, $columns, $actions, $lang['strnodatabases']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create\">{$lang['strcreatedatabase']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$misc->href}\">{$lang['strcreatedatabase']}</a></p>\n";
}
+
+ function doTree() {
+ global $misc, $data, $lang;
+
+ $databases = &$data->getDatabases();
+
+ $reqvars = $misc->getRequestVars('database');
+
+ $attrs = array(
+ 'text' => field('datname'),
+ 'icon' => 'database',
+ 'toolTip'=> field('datcomment'),
+ 'action' => url('redirect.php',
+ $reqvars,
+ array('database' => field('datname'))
+ ),
+ 'branch' => url('database.php',
+ $reqvars,
+ array(
+ 'action' => 'tree',
+ 'database' => field('datname')
+ )
+ ),
+ );
+
+ $misc->printTreeXML($databases, $attrs);
+ exit;
+ }
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strdatabases']);
$misc->printBody();
diff --git a/bottombar.php b/bottombar.php
deleted file mode 100644
index 10191c7f..00000000
--- a/bottombar.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
- /**
- * Bottom bar
- *
- * $Id: bottombar.php,v 1.3 2003/12/17 09:11:32 chriskl Exp $
- */
-
- // Include application functions (no db conn)
- $_no_db_connection = true;
- include_once('./libraries/lib.inc.php');
-
- $misc->printHeader();
- $misc->printBody('bottombar');
- $misc->printFooter();
-?>
diff --git a/browser.php b/browser.php
index 6b7d1d8d..df42006f 100644
--- a/browser.php
+++ b/browser.php
@@ -5,316 +5,71 @@
* if you click on a database it shows a list of database objects in that
* database.
*
- * $Id: browser.php,v 1.45 2005/03/11 04:32:10 chriskl Exp $
+ * $Id: browser.php,v 1.46 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
+ $_no_db_connection = true;
include_once('./libraries/lib.inc.php');
- // Include tree classe
- include_once('./classes/HTML_TreeMenu/TreeMenu.php');
-
// Output header
- $misc->printHeader('', "<script src=\"classes/HTML_TreeMenu/TreeMenu.js\" type=\"text/javascript\"></script>\n<script src=\"links.js\" type=\"text/javascript\"></script>");
+ $misc->printHeader('', "<script src=\"xloadtree/xmlextras.js\" type=\"text/javascript\"></script>\n<script src=\"xloadtree/xtree2.js\" type=\"text/javascript\"></script>\n<script src=\"xloadtree/xloadtree2.js\" type=\"text/javascript\"></script>");
$misc->printBody('browser');
echo "<div dir=\"ltr\">\n";
-
- // Construct expanding tree
- $menu = new HTML_TreeMenu(null, array('usePersistence' => false));
- $root = new HTML_TreeNode(array(
- 'text' => $misc->printVal(($conf['servers'][$_SESSION['webdbServerID']]['desc'])),
- 'link' => addslashes('redirect.php?section=server&amp;' . SID),
- 'icon' => 'folder.gif',
- 'expandedIcon' => 'folder-expanded.gif',
- 'expanded' => true,
- 'linkTarget' => 'detail'));
-
- // Add root node to menu
- $menu->addItem($root);
-
- /**
- * Helper function for adding nodes
- * @param $schemanode Node onto which to add
- */
- function addNodes(&$schemanode, $querystr) {
- global $data, $misc, $lang, $conf;
-
- // Tables
- $table_node = &new HTML_TreeNode(array(
- 'text' => $lang['strtables'],
- 'link' => addslashes(htmlspecialchars("tables.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/tables.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/tables.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add table folder to schema
- $schemanode->addItem($table_node);
-
- $tables = &$data->getTables();
- while (!$tables->EOF) {
- $return_url = urlencode("tblproperties.php?table=" . urlencode($tables->f['relname']) . "&{$querystr}");
- $item_node = &new HTML_TreeNode(array(
- 'text' => $misc->printVal($tables->f['relname']),
- 'link' => addslashes(htmlspecialchars("redirect.php?section=table&{$querystr}&table=" . urlencode($tables->f['relname']))),
- 'icon' => "../../../images/themes/{$conf['theme']}/tables.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/tables.png",
- 'expanded' => false,
- 'linkTarget' => 'detail',
- 'iconLink' => addslashes(htmlspecialchars('display.php?table=' . urlencode($tables->f['relname']) . '&subject=table&' . $querystr . "&return_url={$return_url}&return_desc=" . urlencode($lang['strback'])))
- ));
- // Add table folder to schema
- $table_node->addItem($item_node);
-
- $tables->moveNext();
- }
-
- // Views
- $view_node = &new HTML_TreeNode(array(
- 'text' => $lang['strviews'],
- 'link' => addslashes(htmlspecialchars("views.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/views.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/views.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add view folder to schema
- $schemanode->addItem($view_node);
-
- $views = &$data->getViews();
- while (!$views->EOF) {
- $return_url = urlencode("viewproperties.php?view=" . urlencode($views->f['relname']) . "&{$querystr}");
- $item_node = &new HTML_TreeNode(array(
- 'text' => $misc->printVal($views->f['relname']),
- 'link' => addslashes(htmlspecialchars("redirect.php?section=view&{$querystr}&view=" .
- urlencode($views->f['relname']))),
- 'icon' => "../../../images/themes/{$conf['theme']}/views.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/views.png",
- 'expanded' => false,
- 'linkTarget' => 'detail',
- // XXX: FIX BROWSE
- 'iconLink' => addslashes(htmlspecialchars('display.php?view='.urlencode($views->f['relname']).'&subject=view&'.$querystr.
- "&return_url={$return_url}&return_desc=" . urlencode($lang['strback'])))
- ));
- // Add view folder to schema
- $view_node->addItem($item_node);
-
- $views->moveNext();
- }
-
- // Sequences
- $seq_node = &new HTML_TreeNode(array(
- 'text' => $lang['strsequences'],
- 'link' => addslashes(htmlspecialchars("sequences.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/sequences.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/sequences.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $schemanode->addItem($seq_node);
-
- // Functions
- $func_node = &new HTML_TreeNode(array(
- 'text' => $lang['strfunctions'],
- 'link' => addslashes(htmlspecialchars("functions.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/functions.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/functions.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $schemanode->addItem($func_node);
-
- // Domains
- if ($data->hasDomains()) {
- $dom_node = &new HTML_TreeNode(array(
- 'text' => $lang['strdomains'],
- 'link' => addslashes(htmlspecialchars("domains.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/domains.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/domains.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
-
- // Add folder to schema
- $schemanode->addItem($dom_node);
- }
-
- // Advanced
- if ($conf['show_advanced']) {
- $adv_node = &new HTML_TreeNode(array(
- 'text' => $lang['stradvanced'],
-# 'link' => ($data->hasSchemas()) ? addslashes(htmlspecialchars("schema.php?{$querystr}&" . SID)) : null,
- 'icon' => 'folder.gif',
- 'expandedIcon' => 'folder-expanded.gif',
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $schemanode->addItem($adv_node);
-
- // Aggregates
- $agg_node = &new HTML_TreeNode(array(
- 'text' => $lang['straggregates'],
- 'link' => addslashes(htmlspecialchars("aggregates.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $adv_node->addItem($agg_node);
-
- // Types
- $type_node = &new HTML_TreeNode(array(
- 'text' => $lang['strtypes'],
- 'link' => addslashes(htmlspecialchars("types.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $adv_node->addItem($type_node);
-
- // Operators
- $opr_node = &new HTML_TreeNode(array(
- 'text' => $lang['stroperators'],
- 'link' => addslashes(htmlspecialchars("operators.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/operators.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/operators.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $adv_node->addItem($opr_node);
-
- // Operator Classes
- $opc_node = &new HTML_TreeNode(array(
- 'text' => $lang['stropclasses'],
- 'link' => addslashes(htmlspecialchars("opclasses.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/operators.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/operators.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to schema
- $adv_node->addItem($opc_node);
-
- // Conversions
- if ($data->hasConversions()) {
- $con_node = &new HTML_TreeNode(array(
- 'text' => $lang['strconversions'],
- 'link' => addslashes(htmlspecialchars("conversions.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
-
- // Add folder to schema
- $adv_node->addItem($con_node);
- }
- }
- }
-
- $databases = &$data->getDatabases(isset($_REQUEST['database']) ? $_REQUEST['database'] : NULL);
- while (!$databases->EOF) {
- // If database is selected, show folder, otherwise show document
- if (isset($_REQUEST['database']) && $_REQUEST['database'] == $databases->f['datname']) {
- // Very ugly hack to work around the fact that the PEAR HTML_Tree can't have links with embedded
- // apostrophes create the get string we need to append
- $querystr = 'database=' . urlencode($databases->f['datname']) . '&' . SID;
- $db_node = &new HTML_TreeNode(array(
- 'text' => $misc->printVal($databases->f['datname']),
- 'link' => addslashes(htmlspecialchars("redirect.php?section=database&{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/database.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/database.png",
- 'expanded' => true,
- 'linkTarget' => 'detail'));
-
- // If database supports schemas, add the extra level of hierarchy
- if ($data->hasSchemas()) {
- $schemas = &$data->getSchemas();
- while (!$schemas->EOF) {
- $data->setSchema($schemas->f['nspname']);
- // Construct database & schema query string
- $querystr = 'database=' . urlencode($databases->f['datname']). '&schema=' .
- urlencode($schemas->f['nspname']) . '&' . SID;
- $schemanode = &new HTML_TreeNode(array(
- 'text' => $misc->printVal($schemas->f['nspname']),
- 'link' => addslashes(htmlspecialchars("redirect.php?section=schema&{$querystr}")),
- 'icon' => 'folder.gif',
- 'expandedIcon' => 'folder-expanded.gif',
- // Auto-expand your personal schema, if it exists. Also expand schema if there is
- // only one schema in the database.
- 'expanded' => ($schemas->f['nspname'] == $_SESSION['webdbUsername']
- || $schemas->recordCount() == 1),
- 'linkTarget' => 'detail'));
-
- addNodes($schemanode, $querystr);
-
- // Add schema to database
- $db_node->addItem($schemanode);
-
- $schemas->moveNext();
- }
- }
- // Database doesn't support schemas
- else {
- // Construct database query string
- $querystr = 'database=' . urlencode($databases->f['datname']) . '&' . SID;
-
- addNodes($db_node, $querystr);
- }
-
- // Reset database query string
- $querystr = 'database=' . urlencode($databases->f['datname']) . '&' . SID;
-
- // Languages
- if ($conf['show_advanced']) {
- $lang_node = &new HTML_TreeNode(array(
- 'text' => $lang['strlanguages'],
- 'link' => addslashes(htmlspecialchars("languages.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
- // Add folder to database
- $db_node->addItem($lang_node);
-
- // Casts
- if ($data->hasCasts()) {
- $cast_node = &new HTML_TreeNode(array(
- 'text' => $lang['strcasts'],
- 'link' => addslashes(htmlspecialchars("casts.php?{$querystr}")),
- 'icon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/types.png",
- 'expanded' => false,
- 'linkTarget' => 'detail'));
-
- // Add folder to database
- $db_node->addItem($cast_node);
- }
- }
-
- // Add node to menu
- $root->addItem($db_node);
+?>
- } else {
- // Very ugly hack to work around the fact that the PEAR HTML_Tree can't have links with embedded
- // apostrophes create the get string we need to append
- $jsLink = '?database=' . addslashes(htmlspecialchars(urlencode($databases->f['datname']) . '&' . SID));
- $jsLink = "javascript:updateLinks(' + \"'{$jsLink}'\" + ')";
- $db_node = &new HTML_TreeNode(array(
- 'text' => $misc->printVal($databases->f['datname']),
- 'link' => $jsLink,
- 'icon' => "../../../images/themes/{$conf['theme']}/database.png",
- 'expandedIcon' => "../../../images/themes/{$conf['theme']}/database.png",
- 'expanded' => false,
- 'linkTarget' => '_self'));
-
- // Add node to menu
- $root->addItem($db_node);
- }
-
- $databases->moveNext();
- }
- // Create the presentation class
- $treeMenu = &new HTML_TreeMenu_DHTML($menu, array('images' => 'classes/HTML_TreeMenu/images', 'defaultClass' => 'treeMenuDefault'));
-
- // Actually display the menu
- $treeMenu->printMenu();
+ <div class="logo"><a href="intro.php" target="detail"><img src="<?php echo $misc->icon('title') ?>" width="200" height="50" alt="<?php echo htmlspecialchars($appName) ?>" title="<?php echo htmlspecialchars($appName) ?>" /></a></div>
+
+<style type="text/css">
+.webfx-tree-children {
+ background-image: url("<?php echo $misc->icon('I') ?>");
+}
+</style>
+<script type="text/javascript">
+
+webFXTreeConfig.rootIcon = "<?php echo $misc->icon('root') ?>";
+webFXTreeConfig.openRootIcon = "<?php echo $misc->icon('root') ?>";
+webFXTreeConfig.folderIcon = "<?php echo $misc->icon('folder') ?>";
+webFXTreeConfig.openFolderIcon = "<?php echo $misc->icon('folderOpen') ?>";
+webFXTreeConfig.fileIcon = "<?php echo $misc->icon('file') ?>";
+webFXTreeConfig.iIcon = "<?php echo $misc->icon('I') ?>";
+webFXTreeConfig.lIcon = "<?php echo $misc->icon('L') ?>";
+webFXTreeConfig.lMinusIcon = "<?php echo $misc->icon('Lminus') ?>";
+webFXTreeConfig.lPlusIcon = "<?php echo $misc->icon('Lplus') ?>";
+webFXTreeConfig.tIcon = "<?php echo $misc->icon('T') ?>";
+webFXTreeConfig.tMinusIcon = "<?php echo $misc->icon('Tminus') ?>";
+webFXTreeConfig.tPlusIcon = "<?php echo $misc->icon('Tplus') ?>";
+webFXTreeConfig.blankIcon = "<?php echo $misc->icon('blank') ?>";
+webFXTreeConfig.loadingIcon = "<?php echo $misc->icon('loading') ?>";
+webFXTreeConfig.loadingText = "<?php echo $lang['strloading'] ?>";
+webFXTreeConfig.errorIcon = "<?php echo $misc->icon('error') ?>";
+webFXTreeConfig.errorLoadingText = "<?php echo $lang['strerrorloading'] ?>";
+webFXTreeConfig.reloadText = "<?php echo $lang['strclicktoreload'] ?>";
+
+// Set default target frame:
+WebFXTreeAbstractNode.prototype.target = 'detail';
+
+// Disable double click:
+WebFXTreeAbstractNode.prototype._onDblClick = function(){}
+
+// Show tree XML on double click - for debugging purposes only
+// TODO: REMOVE THIS BEFORE RELEASE
+WebFXTreeAbstractNode.prototype._onDblClick = function(e){
+ var el = e.target || e.srcElement;
+
+ if (this.src != null)
+ window.open(this.src, this.target || "_self");
+ return false;
+};
+
+var tree = new WebFXLoadTree("<?php echo $lang['strservers']; ?>", "servers.php?action=tree", "servers.php");
+
+tree.write();
+tree.setExpanded(true);
+
+</script>
+<?php
// Output footer
echo "</div>\n";
$misc->printFooter();
diff --git a/classes/ArrayRecordSet.php b/classes/ArrayRecordSet.php
new file mode 100644
index 00000000..f05e0dbd
--- /dev/null
+++ b/classes/ArrayRecordSet.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Really simple RecordSet to allow printTable of arrays.
+ *
+ * $Id: ArrayRecordSet.php,v 1.2 2005/05/02 15:47:25 chriskl Exp $
+ */
+class ArrayRecordSet {
+
+ var $_array;
+ var $_count;
+ var $EOF = false;
+ var $f;
+
+ function ArrayRecordSet($data) {
+ $this->_array = $data;
+ $this->_count = count($this->_array);
+ $this->f = reset($this->_array);
+ if ($this->f === false) $this->EOF = true;
+ }
+
+ function recordCount() {
+ return $this->_count;
+ }
+
+ function moveNext() {
+ $this->f = next($this->_array);
+ if ($this->f === false) $this->EOF = true;
+ }
+}
+
+?>
diff --git a/classes/Misc.php b/classes/Misc.php
index 5c604992..1cd892f7 100644
--- a/classes/Misc.php
+++ b/classes/Misc.php
@@ -2,7 +2,7 @@
/**
* Class to hold various commonly used functions
*
- * $Id: Misc.php,v 1.99 2005/04/11 15:15:44 chriskl Exp $
+ * $Id: Misc.php,v 1.100 2005/05/02 15:47:25 chriskl Exp $
*/
class Misc {
@@ -21,45 +21,32 @@
* @return True, dumps are set up, false otherwise
*/
function isDumpEnabled($all = false) {
- global $conf;
-
- if ($all)
- return ($conf['servers'][$_SESSION['webdbServerID']]['pg_dumpall_path'] !== null
- && $conf['servers'][$_SESSION['webdbServerID']]['pg_dumpall_path'] != '');
- else
- return ($conf['servers'][$_SESSION['webdbServerID']]['pg_dump_path'] !== null
- && $conf['servers'][$_SESSION['webdbServerID']]['pg_dump_path'] != '');
+ $info = $this->getServerInfo();
+ return !empty($info[$all ? 'pg_dumpall_path' : 'pg_dump_path']);
}
/**
- * Checks whether a login is allowed
- * @return True if login is allowed to be used
+ * Sets the href tracking variable
*/
- function checkExtraSecurity() {
- global $conf;
-
- // Disallowed logins if extra_login_security is enabled. These must be lowercase.
- $bad_usernames = array('pgsql', 'postgres', 'root', 'administrator');
-
- // If extra security is off, return true
- if (!$conf['extra_login_security']) return true;
- elseif ($_SESSION['webdbPassword'] == '') return false;
- else {
- $username = strtolower($_SESSION['webdbUsername']);
- return !in_array($username, $bad_usernames);
- }
+ function setHREF() {
+ $this->href = $this->getHREF();
}
-
+
/**
- * Sets the href tracking variable
+ * Get a href query string, excluding objects below the given object type (inclusive)
*/
- function setHREF() {
- $this->href = '';
- if (isset($_REQUEST['database'])) {
- $this->href .= 'database=' . urlencode($_REQUEST['database']);
- if (isset($_REQUEST['schema']))
- $this->href .= '&amp;schema=' . urlencode($_REQUEST['schema']);
+ function getHREF($exclude_from = null) {
+ $href = '';
+ if (isset($_REQUEST['server']) && $exclude_from != 'server') {
+ $href .= 'server=' . urlencode($_REQUEST['server']);
+ if (isset($_REQUEST['database']) && $exclude_from != 'database') {
+ $href .= '&amp;database=' . urlencode($_REQUEST['database']);
+ if (isset($_REQUEST['schema']) && $exclude_from != 'schema') {
+ $href .= '&amp;schema=' . urlencode($_REQUEST['schema']);
+ }
+ }
}
+ return $href;
}
/**
@@ -67,10 +54,14 @@
*/
function setForm() {
$this->form = '';
- if (isset($_REQUEST['database'])) {
- $this->form .= "<input type=\"hidden\" name=\"database\" value=\"" . htmlspecialchars($_REQUEST['database']) . "\" />\n";
- if (isset($_REQUEST['schema']))
- $this->form .= "<input type=\"hidden\" name=\"schema\" value=\"" . htmlspecialchars($_REQUEST['schema']) . "\" />\n";
+ if (isset($_REQUEST['server'])) {
+ $this->form .= "<input type=\"hidden\" name=\"server\" value=\"" . htmlspecialchars($_REQUEST['server']) . "\" />\n";
+ if (isset($_REQUEST['database'])) {
+ $this->form .= "<input type=\"hidden\" name=\"database\" value=\"" . htmlspecialchars($_REQUEST['database']) . "\" />\n";
+ if (isset($_REQUEST['schema'])) {
+ $this->form .= "<input type=\"hidden\" name=\"schema\" value=\"" . htmlspecialchars($_REQUEST['schema']) . "\" />\n";
+ }
+ }
}
}
@@ -264,27 +255,50 @@
/**
* Creates a database accessor
*/
- function &getDatabaseAccessor($database) {
- global $conf;
+ function &getDatabaseAccessor($database, $server_id = null) {
+ global $lang, $conf, $misc;
+
+ $server_info = $this->getServerInfo($server_id);
+ // Perform extra security checks if this config option is set
+ if ($conf['extra_login_security']) {
+ // Disallowed logins if extra_login_security is enabled.
+ // These must be lowercase.
+ $bad_usernames = array('pgsql', 'postgres', 'root', 'administrator');
+
+ $username = strtolower($server_info['username']);
+
+ if ($server_info['password'] == '' || in_array($username, $bad_usernames)) {
+ unset($_SESSION['webdbLogin'][$_REQUEST['server']]);
+ $msg = $lang['strlogindisallowed'];
+ include('./login.php');
+ exit;
+ }
+ }
+
// Create the connection object and make the connection
$_connection = new Connection(
- $conf['servers'][$_SESSION['webdbServerID']]['host'],
- $conf['servers'][$_SESSION['webdbServerID']]['port'],
- $_SESSION['webdbUsername'],
- $_SESSION['webdbPassword'],
+ $server_info['host'],
+ $server_info['port'],
+ $server_info['username'],
+ $server_info['password'],
$database
);
- // Get the name of the database driver we need to use. The description
- // of the server is returned and placed into the conf array.
- $_type = $_connection->getDriver($desc);
- // XXX: NEED TO CHECK RETURN STATUS HERE
-
+ // Get the name of the database driver we need to use.
+ // The description of the server is returned in $platform.
+ $_type = $_connection->getDriver($platform);
+ if ($_type === null) {
+ printf($lang['strpostgresqlversionnotsupported'], $postgresqlMinVer);
+ exit;
+ }
+ $this->setServerInfo('platform', $platform, $server_id);
+
// Create a database wrapper class for easy manipulation of the
// connection.
include_once('./classes/database/' . $_type . '.php');
- $data = &new $_type($_connection->conn);
+ $data =& new $_type($_connection->conn);
+ $data->platform = $_connection->platform;
return $data;
}
@@ -405,7 +419,7 @@
$active = ($tab_id == $activetab) ? ' active' : '';
if (!isset($tab['hide']) || $tab['hide'] !== true) {
- $tablink = "<a href=\"" . $this->printVal($tab['url'], 'nbsp') . "\">{$tab['title']}</a>";
+ $tablink = "<a" . $this->printActionUrl($tab, $_REQUEST, 'href') . ">{$tab['title']}</a>";
echo "<td width=\"{$width}\" class=\"tab{$active}\">";
@@ -428,271 +442,362 @@
function getNavTabs($section) {
global $data, $lang, $conf;
- $databasevar = isset($_REQUEST['database']) ? 'database=' . urlencode($_REQUEST['database']) : '';
- $schemavar = isset($_REQUEST['schema']) ? '&schema=' . urlencode($_REQUEST['schema']) : '';
+# $servervar = isset($_REQUEST['server']) ? 'server=' . urlencode($_REQUEST['server']) : '';
+# $databasevar = isset($_REQUEST['database']) ? '&database=' . urlencode($_REQUEST['database']) : '';
+# $schemavar = isset($_REQUEST['schema']) ? '&schema=' . urlencode($_REQUEST['schema']) : '';
$hide_advanced = ($conf['show_advanced'] === false);
switch ($section) {
+ case 'root':
+ return array (
+ 'intro' => array (
+ 'title' => $lang['strintroduction'],
+ 'url' => "intro.php",
+ ),
+ 'servers' => array (
+ 'title' => $lang['strservers'],
+ 'url' => "servers.php",
+ ),
+ );
+
case 'server':
- $hide_users = !$data->isSuperUser($_SESSION['webdbUsername']);
+# $vars = $servervar . $databasevar . '&subject=server';
+ $server_info = $this->getServerInfo();
+ $hide_users = !$data->isSuperUser($server_info['username']);
+ #$hide_users = false;
return array (
'databases' => array (
'title' => $lang['strdatabases'],
- 'url' => "all_db.php",
+ 'url' => 'all_db.php',
+ 'urlvars' => array('subject' => 'server'),
'help' => 'pg.database',
),
'users' => array (
'title' => $lang['strusers'],
- 'url' => "users.php",
+ 'url' => 'users.php',
+ 'urlvars' => array('subject' => 'server'),
'hide' => $hide_users,
'help' => 'pg.user',
),
'groups' => array (
'title' => $lang['strgroups'],
- 'url' => "groups.php",
+ 'url' => 'groups.php',
+ 'urlvars' => array('subject' => 'server'),
'hide' => $hide_users,
'help' => 'pg.group',
),
+ 'account' => array (
+ 'title' => $lang['straccount'],
+ 'url' => 'users.php',
+ 'urlvars' => array('subject' => 'server', 'action' => 'action'),
+ 'hide' => !$hide_users,
+ 'help' => 'pg.user',
+ ),
'tablespaces' => array (
'title' => $lang['strtablespaces'],
- 'url' => "tablespaces.php",
+ 'url' => 'tablespaces.php',
+ 'urlvars' => array('subject' => 'server'),
'hide' => (!$data->hasTablespaces()),
'help' => 'pg.tablespace',
),
'export' => array (
'title' => $lang['strexport'],
- 'url' => "all_db.php?action=export",
+ 'url' => 'all_db.php',
+ 'urlvars' => array('subject' => 'server', 'action' => 'export'),
'hide' => (!$this->isDumpEnabled()),
),
+ 'reports' => array (
+ 'title' => $lang['strreports'],
+ 'url' => 'reports.php',
+ 'urlvars' => array('subject' => 'server'),
+ ),
);
case 'database':
- $vars = $databasevar . '&subject=database';
+# $vars = $servervar . $databasevar . '&subject=database';
return array (
'schemas' => array (
'title' => $lang['strschemas'],
- 'url' => "database.php?{$vars}",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database'),
'hide' => (!$data->hasSchemas()),
'help' => 'pg.schema',
),
'sql' => array (
'title' => $lang['strsql'],
- 'url' => "database.php?{$vars}&action=sql",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'sql'),
'help' => 'pg.sql',
),
'find' => array (
'title' => $lang['strfind'],
- 'url' => "database.php?{$vars}&action=find",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'find'),
),
'variables' => array (
'title' => $lang['strvariables'],
- 'url' => "database.php?{$vars}&action=variables",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'variables'),
'hide' => (!$data->hasVariables()),
'help' => 'pg.variable',
),
'processes' => array (
'title' => $lang['strprocesses'],
- 'url' => "database.php?{$vars}&action=processes",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'processes'),
'hide' => (!$data->hasProcesses()),
'help' => 'pg.process',
),
'admin' => array (
'title' => $lang['stradmin'],
- 'url' => "database.php?{$vars}&action=admin",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'admin'),
),
'privileges' => array (
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?{$vars}",
+ 'url' => 'privileges.php',
+ 'urlvars' => array('subject' => 'database'),
'hide' => (!isset($data->privlist['database'])),
'help' => 'pg.privilege',
),
'languages' => array (
'title' => $lang['strlanguages'],
- 'url' => "languages.php?{$vars}",
+ 'url' => 'languages.php',
+ 'urlvars' => array('subject' => 'database'),
'hide' => $hide_advanced,
'help' => 'pg.language',
),
'casts' => array (
'title' => $lang['strcasts'],
- 'url' => "casts.php?{$vars}",
+ 'url' => 'casts.php',
+ 'urlvars' => array('subject' => 'database'),
'hide' => ($hide_advanced || !$data->hasCasts()),
'help' => 'pg.cast',
),
'export' => array (
'title' => $lang['strexport'],
- 'url' => "database.php?{$vars}&action=export",
+ 'url' => 'database.php',
+ 'urlvars' => array('subject' => 'database', 'action' => 'export'),
'hide' => (!$this->isDumpEnabled()),
),
);
case 'schema':
- $vars = $databasevar . $schemavar . '&subject=schema';
+# $vars = $servervar . $databasevar . $schemavar . '&subject=schema';
return array (
'tables' => array (
'title' => $lang['strtables'],
- 'url' => "tables.php?{$vars}",
+ 'url' => 'tables.php',
+ 'urlvars' => array('subject' => 'schema'),
'help' => 'pg.table',
+ 'icon' => 'tables',
),
'views' => array (
'title' => $lang['strviews'],
- 'url' => "views.php?{$vars}",
+ 'url' => 'views.php',
+ 'urlvars' => array('subject' => 'schema'),
'help' => 'pg.view',
+ 'icon' => 'views',
),
'sequences' => array (
'title' => $lang['strsequences'],
- 'url' => "sequences.php?{$vars}",
+ 'url' => 'sequences.php',
+ 'urlvars' => array('subject' => 'schema'),
'help' => 'pg.sequence',
+ 'icon' => 'sequences',
),
'functions' => array (
'title' => $lang['strfunctions'],
- 'url' => "functions.php?{$vars}",
+ 'url' => 'functions.php',
+ 'urlvars' => array('subject' => 'schema'),
'help' => 'pg.function',
+ 'icon' => 'functions',
),
'domains' => array (
'title' => $lang['strdomains'],
- 'url' => "domains.php?{$vars}",
+ 'url' => 'domains.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => (!$data->hasDomains()),
'help' => 'pg.domain',
+ 'icon' => 'domains',
),
'aggregates' => array (
'title' => $lang['straggregates'],
- 'url' => "aggregates.php?{$vars}",
+ 'url' => 'aggregates.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => $hide_advanced,
'help' => 'pg.aggregate',
+ 'icon' => 'functions',
),
'types' => array (
'title' => $lang['strtypes'],
- 'url' => "types.php?{$vars}",
+ 'url' => 'types.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => $hide_advanced,
'help' => 'pg.type',
+ 'icon' => 'types',
),
'operators' => array (
'title' => $lang['stroperators'],
- 'url' => "operators.php?{$vars}",
+ 'url' => 'operators.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => $hide_advanced,
'help' => 'pg.operator',
+ 'icon' => 'operators',
),
'opclasses' => array (
'title' => $lang['stropclasses'],
- 'url' => "opclasses.php?{$vars}",
+ 'url' => 'opclasses.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => $hide_advanced,
'help' => 'pg.opclass',
+ 'icon' => 'operators',
),
'conversions' => array (
'title' => $lang['strconversions'],
- 'url' => "conversions.php?{$vars}",
+ 'url' => 'conversions.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => ($hide_advanced || !$data->hasConversions()),
'help' => 'pg.conversion',
+ 'icon' => 'types',
),
'privileges' => array (
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?{$vars}",
+ 'url' => 'privileges.php',
+ 'urlvars' => array('subject' => 'schema'),
'hide' => (!$data->hasSchemas()),
'help' => 'pg.privilege',
),
);
case 'table':
- $table = urlencode($_REQUEST['table']);
- $vars = $databasevar . $schemavar . "&table={$table}&subject=table";
+# $table = urlencode($_REQUEST['table']);
+# $vars = $servervar . $databasevar . $schemavar . "&table={$table}&subject=table";
return array (
'columns' => array (
'title' => $lang['strcolumns'],
- 'url' => "tblproperties.php?{$vars}",
+ 'url' => 'tblproperties.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
),
'indexes' => array (
'title' => $lang['strindexes'],
- 'url' => "indexes.php?{$vars}",
+ 'url' => 'indexes.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
'help' => 'pg.index',
),
'constraints' => array (
'title' => $lang['strconstraints'],
- 'url' => "constraints.php?{$vars}",
+ 'url' => 'constraints.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
'help' => 'pg.constraint',
),
'triggers' => array (
'title' => $lang['strtriggers'],
- 'url' => "triggers.php?{$vars}",
+ 'url' => 'triggers.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
'help' => 'pg.trigger',
),
'rules' => array (
'title' => $lang['strrules'],
- 'url' => "rules.php?{$vars}",
+ 'url' => 'rules.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
'help' => 'pg.rule',
),
'info' => array (
'title' => $lang['strinfo'],
- 'url' => "info.php?{$vars}",
+ 'url' => 'info.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
),
'privileges' => array (
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?{$vars}",
+ 'url' => 'privileges.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table')),
'help' => 'pg.privilege',
),
'import' => array (
'title' => $lang['strimport'],
- 'url' => "tblproperties.php?{$vars}&action=import",
+ 'url' => 'tblproperties.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table'), 'action' => 'import'),
),
'export' => array (
'title' => $lang['strexport'],
- 'url' => "tblproperties.php?{$vars}&action=export",
+ 'url' => 'tblproperties.php',
+ 'urlvars' => array('subject' => 'table', 'table' => field('table'), 'action' => 'export'),
),
);
case 'view':
- $view = urlencode($_REQUEST['view']);
- $vars = $databasevar . $schemavar . "&view={$view}&subject=view";
+# $view = urlencode($_REQUEST['view']);
+# $vars = $servervar . $databasevar . $schemavar . "&view={$view}&subject=view";
return array (
'columns' => array (
'title' => $lang['strcolumns'],
- 'url' => "viewproperties.php?{$vars}",
+ 'url' => 'viewproperties.php',
+ 'urlvars' => array('subject' => 'view', 'view' => field('view')),
),
'definition' => array (
'title' => $lang['strdefinition'],
- 'url' => "viewproperties.php?{$vars}&action=definition",
+ 'url' => 'viewproperties.php',
+ 'urlvars' => array('subject' => 'view', 'view' => field('view'), 'action' => 'definition'),
),
'rules' => array (
'title' => $lang['strrules'],
- 'url' => "rules.php?{$vars}",
+ 'url' => 'rules.php',
+ 'urlvars' => array('subject' => 'view', 'view' => field('view')),
'help' => 'pg.rule',
),
'privileges' => array (
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?{$vars}",
+ 'url' => 'privileges.php',
+ 'urlvars' => array('subject' => 'view', 'view' => field('view')),
'help' => 'pg.privilege',
),
'export' => array (
'title' => $lang['strexport'],
- 'url' => "viewproperties.php?{$vars}&action=export",
+ 'url' => 'viewproperties.php',
+ 'urlvars' => array('subject' => 'view', 'view' => field('view'), 'action' => 'export'),
),
);
case 'function':
- $funcnam = urlencode($_REQUEST['function']);
- $funcoid = urlencode($_REQUEST['function_oid']);
- $vars = $databasevar . $schemavar . "&function={$funcnam}&function_oid={$funcoid}&subject=function";
+# $funcnam = urlencode($_REQUEST['function']);
+# $funcoid = urlencode($_REQUEST['function_oid']);
+# $vars = $servervar . $databasevar . $schemavar . "&function={$funcnam}&function_oid={$funcoid}&subject=function";
return array (
'definition' => array (
'title' => $lang['strdefinition'],
- 'url' => "functions.php?{$vars}&action=properties",
+ 'url' => 'functions.php',
+ 'urlvars' => array(
+ 'subject' => 'function',
+ 'function' => field('function'),
+ 'function_oid' => field('function_oid'),
+ 'action' => 'properties',
+ ),
),
'privileges' => array (
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?{$vars}",
+ 'url' => 'privileges.php',
+ 'urlvars' => array(
+ 'subject' => 'function',
+ 'function' => field('function'),
+ 'function_oid' => field('function_oid'),
+ ),
),
);
case 'popup':
- $vars = $databasevar;
+# $vars = $servervar . $databasevar;
return array (
'sql' => array (
'title' => $lang['strsql'],
- 'url' => "sqledit.php?{$vars}&action=sql",
+ 'url' => 'sqledit.php',
+ 'urlvars' => array('subject' => 'schema', 'action' => 'sql'),
'help' => 'pg.sql',
),
'find' => array (
'title' => $lang['strfind'],
- 'url' => "sqledit.php?{$vars}&action=find",
+ 'url' => 'sqledit.php',
+ 'urlvars' => array('subject' => 'schema', 'action' => 'find'),
),
);
@@ -727,12 +832,70 @@
return isset($tab['url']) ? $tab['url'] : null;
}
+ function printTopbar() {
+ global $lang, $conf, $appName, $appVersion, $appLangFiles;
+
+ $server_info = $this->getServerInfo();
+
+ echo "<div class=\"topbar\"><table width=\"100%\"><tr><td>";
+
+ if ($server_info && isset($server_info['platform']) && isset($server_info['username'])) {
+ echo sprintf($lang['strtopbar'],
+ '<span class="platform">'.htmlspecialchars($server_info['platform']).'</span>',
+ '<span class="host">'.htmlspecialchars($server_info['host']).'</span>',
+ '<span class="port">'.htmlspecialchars($server_info['port']).'</span>',
+ '<span class="username">'.htmlspecialchars($server_info['username']).'</span>',
+ '<span class="date">'.date($lang['strtimefmt']).'</span>');
+ } else {
+ echo "<span class=\"appname\">$appName</span> <span class=\"version\">$appVersion</span>";
+ }
+
+ echo "</td>";
+
+ if (isset($_REQUEST['server'])) {
+ $url = "sqledit.php?{$this->href}&amp;action=";
+
+ $window_id = htmlspecialchars('sqledit:'.$_REQUEST['server']);
+
+ echo "<td align=\"right\">";
+
+ echo "<a class=\"toplink\" href=\"{$url}sql\" target=\"sqledit\" onclick=\"window.open('{$url}sql','{$window_id}','toolbar=no,width=600,height=400,resizable=yes,scrollbars=no').focus(); return false;\">{$lang['strsql']}</a> | ";
+
+ echo "<a class=\"toplink\" href=\"{$url}find\" target=\"sqledit\" onclick=\"window.open('{$url}find','{$window_id}','toolbar=no,width=600,height=400,resizable=yes,scrollbars=no').focus(); return false;\">{$lang['strfind']}</a>";
+
+ echo "</td>";
+ }
+/*
+ echo "<td align=\"right\" width=\"1%\">";
+
+ echo "<form method=\"get\"><select name=\"language\" onchange=\"this.form.submit()\">\n";
+ $language = isset($_SESSION['webdbLanguage']) ? $_SESSION['webdbLanguage'] : 'english';
+ foreach ($appLangFiles as $k => $v) {
+ echo "<option value=\"{$k}\"",
+ ($k == $language) ? ' selected="selected"' : '',
+ ">{$v}</option>\n";
+ }
+ echo "</select>\n";
+ echo "<noscript><input type=\"submit\" value=\"Set Language\"></noscript>\n";
+ foreach ($_GET as $key => $val) {
+ if ($key == 'language') continue;
+ echo "<input type=\"hidden\" name=\"$key\" value=\"", htmlspecialchars($val), "\" />\n";
+ }
+ echo "</form>\n";
+
+ echo "</td>";
+*/
+ echo "</tr></table></div>\n";
+ }
+
/**
* Display a bread crumb trail.
*/
function printTrail($trail = array()) {
global $lang;
+ $this->printTopbar();
+
if (is_string($trail)) {
$trail = $this->getTrail($trail);
}
@@ -768,26 +931,37 @@
* @param $object The type of object at the end of the trail.
*/
function getTrail($subject = null) {
- global $lang, $conf;
+ global $lang, $conf, $data, $appName;
$trail = array();
$vars = '';
$done = false;
- $trail['server'] = array(
- 'title' => $lang['strserver'],
- 'text' => $conf['servers'][$_SESSION['webdbServerID']]['desc'],
- 'url' => 'redirect.php?section=server',
- 'help' => 'pg.server'
+ $trail['root'] = array(
+ 'text' => $appName,
+ 'url' => 'redirect.php?subject=root',
);
+
+ if ($subject == 'root') $done = true;
+
+ if (!$done) {
+ $vars = 'server='.urlencode($_REQUEST['server']).'&';
+ $server_info = $this->getServerInfo();
+ $trail['server'] = array(
+ 'title' => $lang['strserver'],
+ 'text' => $server_info['desc'],
+ 'url' => "redirect.php?subject=server&{$vars}",
+ 'help' => 'pg.server'
+ );
+ }
if ($subject == 'server') $done = true;
if (isset($_REQUEST['database']) && !$done) {
- $vars = 'database='.urlencode($_REQUEST['database']).'&';
+ $vars .= 'database='.urlencode($_REQUEST['database']).'&';
$trail['database'] = array(
'title' => $lang['strdatabase'],
'text' => $_REQUEST['database'],
- 'url' => "redirect.php?section=database&{$vars}",
+ 'url' => "redirect.php?subject=database&{$vars}",
'help' => 'pg.database'
);
}
@@ -798,14 +972,14 @@
$trail['schema'] = array(
'title' => $lang['strschema'],
'text' => $_REQUEST['schema'],
- 'url' => "redirect.php?section=schema&{$vars}",
+ 'url' => "redirect.php?subject=schema&{$vars}",
'help' => 'pg.schema'
);
}
if ($subject == 'schema') $done = true;
if (isset($_REQUEST['table']) && !$done) {
- $vars .= "section=table&table=".urlencode($_REQUEST['table']);
+ $vars .= "subject=table&table=".urlencode($_REQUEST['table']);
$trail['table'] = array(
'title' => $lang['strtable'],
'text' => $_REQUEST['table'],
@@ -813,7 +987,7 @@
'help' => 'pg.table'
);
} elseif (isset($_REQUEST['view']) && !$done) {
- $vars .= "section=view&view=".urlencode($_REQUEST['view']);
+ $vars .= "subject=view&view=".urlencode($_REQUEST['view']);
$trail['view'] = array(
'title' => $lang['strview'],
'text' => $_REQUEST['view'],
@@ -827,7 +1001,7 @@
switch ($subject) {
case 'function':
$vars .= "{$subject}_oid=".urlencode($_REQUEST[$subject.'_oid']).'&';
- $vars .= "section={$subject}&{$subject}=".urlencode($_REQUEST[$subject]);
+ $vars .= "subject={$subject}&{$subject}=".urlencode($_REQUEST[$subject]);
$trail[$subject] = array(
'title' => $lang['str'.$subject],
'text' => $_REQUEST[$subject],
@@ -918,7 +1092,7 @@
echo $str;
if ($help) {
echo "<a class=\"help\" href=\"";
- echo htmlspecialchars("help.php?help=".urlencode($help));
+ echo htmlspecialchars("help.php?help=".urlencode($help)."&server=".urlencode($_REQUEST['server']));
echo "\" title=\"{$lang['strhelp']}\" target=\"phppgadminhelp\">{$lang['strhelpicon']}</a>";
}
}
@@ -934,6 +1108,18 @@
echo "-->\n";
echo "</script>\n";
}
+
+ /**
+ * Outputs JavaScript to set the name of the browser window.
+ * @param $name the window name
+ * @param $addServer if true (default) then the server id is
+ * attached to the name.
+ */
+ function setWindowName($name, $addServer = true) {
+ echo "<script type=\"text/javascript\">\n<!--\n";
+ echo " window.name = '{$name}", ($addServer ? ':'.htmlspecialchars($_REQUEST['server']) : ''), "';\n";
+ echo "-->\n</script>\n";
+ }
/**
* Converts a PHP.INI size variable to bytes. Taken from publically available
@@ -941,7 +1127,7 @@
* @param $strIniSize The PHP.INI variable
* @return size in bytes, false on failure
*/
- function inisizeToBytes($strIniSize) {
+ function inisizeToBytes($strIniSize) {
// This function will take the string value of an ini 'size' parameter,
// and return a double (64-bit float) representing the number of bytes
// that the parameter represents. Or false if $strIniSize is unparseable.
@@ -965,8 +1151,73 @@
default:
return $nSize;
}
- }
+ }
+
+ /**
+ * Display a URL given an action associative array.
+ * @param $action An associative array of the follow properties:
+ * 'url' => The first part of the URL (before the ?)
+ * 'urlvars' => Associative array of (URL variable => field name)
+ * these are appended to the URL
+ * 'urlfn' => Function to apply to URL before display
+ * @param $fields Field data from which 'urlfield' and 'vars' are obtained.
+ * @param $attr If supplied then the URL will be quoted and prefixed with
+ * '$attr='.
+ */
+ function printActionUrl(&$action, &$fields, $attr = null) {
+ $url = value($action['url'], $fields);
+
+ if ($url === false) return '';
+
+ if (!empty($action['urlvars'])) {
+ $urlvars = value($action['urlvars'], $fields);
+ } else {
+ $urlvars = array();
+ }
+
+ if (isset($urlvars['subject'])) {
+ $subject = value($urlvars['subject'], $fields);
+ if (isset($_REQUEST['server']) && $subject != 'root') {
+ $urlvars['server'] = $_REQUEST['server'];
+ if (isset($_REQUEST['database']) && $subject != 'server') {
+ $urlvars['database'] = $_REQUEST['database'];
+ if (isset($_REQUEST['schema']) && $subject != 'database') {
+ $urlvars['schema'] = $_REQUEST['schema'];
+ }
+ }
+ }
+ }
+
+ $sep = '?';
+ foreach ($urlvars as $var => $varfield) {
+ $url .= $sep . value_url($var, $fields) . '=' . value_url($varfield, $fields);
+ $sep = '&';
+ }
+
+ $url = htmlentities($url);
+
+ if ($attr !== null && $url != '')
+ return ' '.$attr.'="'.$url.'"';
+ else
+ return $url;
+ }
+ function getRequestVars($subject = '') {
+ $v = array();
+ if (!empty($subject))
+ $v['subject'] = $subject;
+ if (isset($_REQUEST['server']) && $subject != 'root') {
+ $v['server'] = $_REQUEST['server'];
+ if (isset($_REQUEST['database']) && $subject != 'server') {
+ $v['database'] = $_REQUEST['database'];
+ if (isset($_REQUEST['schema']) && $subject != 'database') {
+ $v['schema'] = $_REQUEST['schema'];
+ }
+ }
+ }
+ return $v;
+ }
+
function printUrlVars(&$vars, &$fields) {
foreach ($vars as $var => $varfield) {
echo "{$var}=", urlencode($fields[$varfield]), "&amp;";
@@ -1067,7 +1318,7 @@
switch ($column_id) {
case 'actions':
foreach ($alt_actions as $action) {
- if (isset($action['disable'])) {
+ if (isset($action['disable']) && $action['disable'] === true) {
echo "<td class=\"data{$id}\"></td>";
} else {
echo "<td class=\"opbutton{$id}\">";
@@ -1079,15 +1330,17 @@
break;
default;
echo "<td class=\"data{$id}\">";
- if (isset($column['url'])) {
- echo "<a href=\"{$column['url']}";
- $misc->printUrlVars($column['vars'], $tabledata->f);
- echo "\">";
- }
+ if (isset($tabledata->f[$column['field']])) {
+ if (isset($column['url'])) {
+ echo "<a href=\"{$column['url']}";
+ $misc->printUrlVars($column['vars'], $tabledata->f);
+ echo "\">";
+ }
- $type = isset($column['type']) ? $column['type'] : null;
- $params = isset($column['params']) ? $column['params'] : array();
- echo $misc->printVal($tabledata->f[$column['field']], $type, $params);
+ $type = isset($column['type']) ? $column['type'] : null;
+ $params = isset($column['params']) ? $column['params'] : array();
+ echo $misc->printVal($tabledata->f[$column['field']], $type, $params);
+ }
if (isset($column['url'])) echo "</a>";
@@ -1112,6 +1365,69 @@
}
}
+ /** Produce XML data for the browser tree
+ * @param $treedata A set of records to populate the tree.
+ * @param $attrs Attributes for tree items
+ * 'text' - the text for the tree node
+ * 'icon' - an icon for node
+ * 'openIcon' - an alternative icon when the node is expanded
+ * 'toolTip' - tool tip text for the node
+ * 'action' - URL to visit when single clicking the node
+ * 'branch' - URL for child nodes (tree XML)
+ * 'expand' - the action to return XML for the subtree
+ * 'nodata' - message to display when node has no children
+ */
+ function printTreeXML(&$treedata, &$attrs) {
+ global $conf, $lang;
+ header("Content-Type: text/xml");
+ header("Cache-Control: no-cache");
+
+ echo "<?xml version=\"1.0\"?>\n";
+
+ echo "<tree>\n";
+
+ if ($treedata->recordCount() > 0) {
+ while (!$treedata->EOF) {
+ $rec =& $treedata->f;
+
+ echo "<tree";
+ echo value_xml_attr('text', $attrs['text'], $rec);
+ echo value_xml_attr('action', $attrs['action'], $rec);
+ echo value_xml_attr('src', $attrs['branch'], $rec);
+
+ $icon = $this->icon(value($attrs['icon'], $rec));
+ echo value_xml_attr('icon', $icon, $rec);
+
+ if (!empty($attrs['openIcon'])) {
+ $icon = $this->icon(value($attrs['openIcon'], $rec));
+ }
+ echo value_xml_attr('openIcon', $icon, $rec);
+
+ echo value_xml_attr('toolTip', $attrs['toolTip'], $rec);
+
+ echo "/>\n";
+
+ $treedata->moveNext();
+ }
+ } else {
+ $msg = isset($attrs['nodata']) ? $attrs['nodata'] : $lang['strnoobjects'];
+ echo "<tree text=\"{$msg}\" onaction=\"this.parentNode.reload()\" icon=\"", $this->icon('error'), "\"/>\n";
+ }
+
+ echo "</tree>\n";
+ }
+
+ function icon($icon) {
+ global $conf;
+ $path = "images/themes/{$conf['theme']}/{$icon}";
+ if (file_exists($path.'.png')) return $path.'.png';
+ if (file_exists($path.'.gif')) return $path.'.gif';
+ $path = "images/themes/default/{$icon}";
+ if (file_exists($path.'.png')) return $path.'.png';
+ if (file_exists($path.'.gif')) return $path.'.gif';
+ return '';
+ }
+
/**
* Function to escape command line parameters
* @param $str The string to escape
@@ -1150,5 +1466,88 @@
else
return escapeshellcmd($str);
}
+
+ /**
+ * Get list of servers
+ * @param $recordset return as RecordSet suitable for printTable if true,
+ * otherwise just return an array.
+ */
+ function &getServers($recordset = false) {
+ global $conf;
+
+ $srvs = isset($_SESSION['webdbLogin']) && is_array($_SESSION['webdbLogin']) ? $_SESSION['webdbLogin'] : array();
+
+ foreach($conf['servers'] as $idx => $info) {
+ $server_id = $info['host'].':'.$info['port'];
+
+ if (!isset($srvs[$server_id])) {
+ $srvs[$server_id] = $info;
+ }
+ $srvs[$server_id]['id'] = $server_id;
+ }
+
+ function _cmp_desc($a, $b) {
+ return strcmp($a['desc'], $b['desc']);
+ }
+ uasort($srvs, '_cmp_desc');
+
+ if ($recordset) {
+ include_once('classes/ArrayRecordSet.php');
+ return new ArrayRecordSet($srvs);
+ }
+ return $srvs;
+ }
+
+ /**
+ * Get information on a server.
+ * If the parameter isn't supplied then the currently
+ * connected server is returned.
+ * @param $server_id A server identifier (host:port)
+ * @return An associative array of server properties
+ */
+ function getServerInfo($server_id = null) {
+ global $conf;
+
+ if ($server_id === null && isset($_REQUEST['server']))
+ $server_id = $_REQUEST['server'];
+
+ // Check for the server in the logged-in list
+ if (isset($_SESSION['webdbLogin'][$server_id]))
+ return $_SESSION['webdbLogin'][$server_id];
+
+ // Otherwise, look for it in the conf file
+ foreach($conf['servers'] as $idx => $info) {
+ if ($server_id == $info['host'].':'.$info['port'])
+ return $info;
+ }
+
+ return null;
+ }
+
+ /**
+ * Set server information.
+ * @param $key parameter name to set, or null to replace all
+ * params with the assoc-array in $value.
+ * @param $value the new value, or null to unset the parameter
+ * @param $server_id the server identifier, or null for current
+ * server.
+ */
+ function setServerInfo($key, $value, $server_id = null)
+ {
+ if ($server_id === null && isset($_REQUEST['server']))
+ $server_id = $_REQUEST['server'];
+
+ if ($key === null) {
+ if ($value === null)
+ unset($_SESSION['webdbLogin'][$server_id]);
+ else
+ $_SESSION['webdbLogin'][$server_id] = $value;
+ } else {
+ if ($value === null)
+ unset($_SESSION['webdbLogin'][$server_id][$key]);
+ else
+ $_SESSION['webdbLogin'][$server_id][$key] = $value;
+ }
+ }
}
?>
diff --git a/classes/Reports.php b/classes/Reports.php
index 8cabfcea..65fe2e19 100644
--- a/classes/Reports.php
+++ b/classes/Reports.php
@@ -4,7 +4,7 @@
* the functions provided by the database driver exclusively, and hence
* will work with any database without modification.
*
- * $Id: Reports.php,v 1.11 2004/07/01 07:15:11 chriskl Exp $
+ * $Id: Reports.php,v 1.12 2005/05/02 15:47:26 chriskl Exp $
*/
class Reports {
@@ -34,10 +34,11 @@
* @return A recordset
*/
function &getReports() {
- global $conf;
+ global $conf, $misc;
// Filter for owned reports if necessary
if ($conf['owned_reports_only']) {
- $filter['created_by'] = $_SESSION['webdbUsername'];
+ $server_info = $misc->getServerInfo();
+ $filter['created_by'] = $server_info['username'];
$ops = array('created_by' => '=');
}
else $filter = $ops = array();
@@ -71,10 +72,12 @@
* @return 0 success
*/
function createReport($report_name, $db_name, $descr, $report_sql) {
+ global $misc;
+ $server_info = $misc->getServerInfo();
$temp = array(
'report_name' => $report_name,
'db_name' => $db_name,
- 'created_by' => $_SESSION['webdbUsername'],
+ 'created_by' => $server_info['username'],
'report_sql' => $report_sql
);
if ($descr != '') $temp['descr'] = $descr;
@@ -92,10 +95,12 @@
* @return 0 success
*/
function alterReport($report_id, $report_name, $db_name, $descr, $report_sql) {
+ global $misc;
+ $server_info = $misc->getServerInfo();
$temp = array(
'report_name' => $report_name,
'db_name' => $db_name,
- 'created_by' => $_SESSION['webdbUsername'],
+ 'created_by' => $server_info['username'],
'report_sql' => $report_sql
);
if ($descr != '') $temp['descr'] = $descr;
diff --git a/classes/database/Postgres.php b/classes/database/Postgres.php
index 30cf2da1..cf8c28d3 100755
--- a/classes/database/Postgres.php
+++ b/classes/database/Postgres.php
@@ -4,7 +4,7 @@
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
*
- * $Id: Postgres.php,v 1.260 2005/04/30 18:01:59 soranzo Exp $
+ * $Id: Postgres.php,v 1.261 2005/05/02 15:47:26 chriskl Exp $
*/
// @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -407,10 +407,12 @@ class Postgres extends ADODB_base {
* @return A list of databases, sorted alphabetically
*/
function &getDatabases($currentdatabase = NULL) {
- global $conf;
+ global $conf, $misc;
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($_SESSION['webdbUsername'])) {
- $username = $_SESSION['webdbUsername'];
+ $server_info = $misc->getServerInfo();
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
+ $username = $server_info['username'];
$this->clean($username);
$clause = " AND pu.usename='{$username}'";
}
@@ -3353,7 +3355,9 @@ class Postgres extends ADODB_base {
pt.typname AS proresult,
pl.lanname AS prolanguage,
oidvectortypes(pc.proargtypes) AS proarguments,
- (SELECT description FROM pg_description pd WHERE pc.oid=pd.objoid) AS procomment
+ (SELECT description FROM pg_description pd WHERE pc.oid=pd.objoid) AS procomment,
+ proname || ' (' || proarguments || ')' AS proproto,
+ CASE WHEN proretset THEN 'setof ' ELSE '' END || pt.typname AS proreturns
FROM
pg_proc pc, pg_user pu, pg_type pt, pg_language pl
WHERE
@@ -3368,7 +3372,9 @@ class Postgres extends ADODB_base {
proretset,
'OPAQUE' AS proresult,
oidvectortypes(pc.proargtypes) AS proarguments,
- (SELECT description FROM pg_description pd WHERE pc.oid=pd.objoid) AS procomment
+ (SELECT description FROM pg_description pd WHERE pc.oid=pd.objoid) AS procomment,
+ proname || ' (' || proarguments || ')' AS proproto,
+ CASE WHEN proretset THEN 'setof ' ELSE '' END || 'OPAQUE' AS proreturns
FROM
pg_proc pc, pg_user pu, pg_type pt
WHERE
diff --git a/classes/database/Postgres71.php b/classes/database/Postgres71.php
index bf828ac5..bf35f02f 100644
--- a/classes/database/Postgres71.php
+++ b/classes/database/Postgres71.php
@@ -4,7 +4,7 @@
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
*
- * $Id: Postgres71.php,v 1.70 2005/02/06 20:03:20 soranzo Exp $
+ * $Id: Postgres71.php,v 1.71 2005/05/02 15:47:26 chriskl Exp $
*/
// @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -86,10 +86,12 @@ class Postgres71 extends Postgres {
* @return A list of databases, sorted alphabetically
*/
function &getDatabases($currentdatabase = NULL) {
- global $conf;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($_SESSION['webdbUsername'])) {
- $username = $_SESSION['webdbUsername'];
+ global $conf, $misc;
+
+ $server_info = $misc->getServerInfo();
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
+ $username = $server_info['username'];
$this->clean($username);
$clause = " AND pu.usename='{$username}'";
}
diff --git a/classes/database/Postgres72.php b/classes/database/Postgres72.php
index 8f6da669..54d850a8 100644
--- a/classes/database/Postgres72.php
+++ b/classes/database/Postgres72.php
@@ -4,7 +4,7 @@
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
*
- * $Id: Postgres72.php,v 1.78 2004/11/10 01:46:36 chriskl Exp $
+ * $Id: Postgres72.php,v 1.79 2005/05/02 15:47:26 chriskl Exp $
*/
@@ -324,7 +324,9 @@ class Postgres72 extends Postgres71 {
false AS proretset,
format_type(p.prorettype, NULL) AS proresult,
oidvectortypes(p.proargtypes) AS proarguments,
- (SELECT description FROM pg_description pd WHERE p.oid=pd.objoid) AS procomment
+ (SELECT description FROM pg_description pd WHERE p.oid=pd.objoid) AS procomment,
+ p.proname || ' (' || oidvectortypes(p.proargtypes) || ')' AS proproto,
+ format_type(p.prorettype, NULL) AS proreturns
FROM
pg_proc p
WHERE
diff --git a/classes/database/Postgres73.php b/classes/database/Postgres73.php
index 14f3b9bd..0ea905c1 100644
--- a/classes/database/Postgres73.php
+++ b/classes/database/Postgres73.php
@@ -4,7 +4,7 @@
* A class that implements the DB interface for Postgres
* Note: This class uses ADODB and returns RecordSets.
*
- * $Id: Postgres73.php,v 1.142 2004/12/06 02:48:34 chriskl Exp $
+ * $Id: Postgres73.php,v 1.143 2005/05/02 15:47:26 chriskl Exp $
*/
// @@@ THOUGHT: What about inherits? ie. use of ONLY???
@@ -720,7 +720,9 @@ class Postgres73 extends Postgres72 {
pg_catalog.format_type(p.prorettype, NULL) AS proresult,
pg_catalog.oidvectortypes(p.proargtypes) AS proarguments,
pl.lanname AS prolanguage,
- pg_catalog.obj_description(p.oid, 'pg_proc') AS procomment
+ pg_catalog.obj_description(p.oid, 'pg_proc') AS procomment,
+ p.proname || ' (' || pg_catalog.oidvectortypes(p.proargtypes) || ')' AS proproto,
+ CASE WHEN p.proretset THEN 'setof ' ELSE '' END || pg_catalog.format_type(p.prorettype, NULL) AS proreturns
FROM pg_catalog.pg_proc p
INNER JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
INNER JOIN pg_catalog.pg_language pl ON pl.oid = p.prolang
diff --git a/classes/database/Postgres80.php b/classes/database/Postgres80.php
index 9d9855fc..abba2611 100644
--- a/classes/database/Postgres80.php
+++ b/classes/database/Postgres80.php
@@ -3,7 +3,7 @@
/**
* PostgreSQL 8.0 support
*
- * $Id: Postgres80.php,v 1.12 2005/04/30 18:02:01 soranzo Exp $
+ * $Id: Postgres80.php,v 1.13 2005/05/02 15:47:26 chriskl Exp $
*/
include_once('./classes/database/Postgres74.php');
@@ -48,10 +48,12 @@ class Postgres80 extends Postgres74 {
* @return A list of databases, sorted alphabetically
*/
function &getDatabases($currentdatabase = NULL) {
- global $conf;
-
- if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($_SESSION['webdbUsername'])) {
- $username = $_SESSION['webdbUsername'];
+ global $conf, $misc;
+
+ $server_info = $misc->getServerInfo();
+
+ if (isset($conf['owned_only']) && $conf['owned_only'] && !$this->isSuperUser($server_info['username'])) {
+ $username = $server_info['username'];
$this->clean($username);
$clause = " AND pu.usename='{$username}'";
}
diff --git a/constraints.php b/constraints.php
index 85776870..0dcdd954 100644
--- a/constraints.php
+++ b/constraints.php
@@ -3,7 +3,7 @@
/**
* List constraints on a table
*
- * $Id: constraints.php,v 1.40 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: constraints.php,v 1.41 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -478,13 +478,13 @@
$misc->printTable($constraints, $columns, $actions, $lang['strnoconstraints'], 'cnPre');
- echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=add_check&{$misc->href}&table=", urlencode($_REQUEST['table']),
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=add_check&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddcheck']}</a> |\n";
- echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_unique_key&{$misc->href}&table=", urlencode($_REQUEST['table']),
+ echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_unique_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['stradduniq']}</a> |\n";
- echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_primary_key&{$misc->href}&table=", urlencode($_REQUEST['table']),
+ echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_primary_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddpk']}</a> |\n";
- echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_foreign_key&{$misc->href}&table=", urlencode($_REQUEST['table']),
+ echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=add_foreign_key&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),
"\">{$lang['straddfk']}</a></p>\n";
}
diff --git a/conversions.php b/conversions.php
index 7437e0dc..316bcb1a 100644
--- a/conversions.php
+++ b/conversions.php
@@ -3,7 +3,7 @@
/**
* Manage conversions in a database
*
- * $Id: conversions.php,v 1.9 2004/09/01 16:35:58 jollytoad Exp $
+ * $Id: conversions.php,v 1.10 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -54,7 +54,27 @@
$misc->printTable($conversions, $columns, $actions, $lang['strnoconversions']);
}
-
+
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $conversions = &$data->getconversions();
+
+ $attrs = array(
+ 'text' => field('conname'),
+ 'icon' => 'conversions',
+ 'toolTip'=> field('concomment')
+ );
+
+ $misc->printTreeXML($conversions, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strconversions']);
$misc->printBody();
diff --git a/database.php b/database.php
index a3726770..a3aee0ca 100755
--- a/database.php
+++ b/database.php
@@ -3,7 +3,7 @@
/**
* Manage schemas within a database
*
- * $Id: database.php,v 1.65 2004/11/29 01:48:38 chriskl Exp $
+ * $Id: database.php,v 1.66 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -318,7 +318,7 @@
}
echo "</p>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
- echo "<p><input type=\"hidden\" name=\"mode\" value=\"database\" />\n";
+ echo "<input type=\"hidden\" name=\"subject\" value=\"database\" />\n";
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
@@ -389,11 +389,13 @@
if ($data->hasSignals()) {
$columns['actions'] = array('title' => $lang['stractions']);
-
+
+ $href = $misc->getHREF('schema');
+
$actions = array(
'cancel' => array(
'title' => $lang['strcancel'],
- 'url' => "{$PHP_SELF}?action=signal&amp;signal=CANCEL&amp;database=" . urlencode($_REQUEST['database']) . "&amp;",
+ 'url' => "{$PHP_SELF}?action=signal&amp;signal=CANCEL&amp;{$href}&amp;",
'vars' => array('procpid' => 'procpid')
)
);
@@ -427,7 +429,7 @@
$status = $data->recluster();
if ($status == 0) doAdmin('', $lang['strclusteredgood']);
else doAdmin('', $lang['strclusteredbad']);
- break;
+ break;
case 'reindex';
$status = $data->reindex('DATABASE', $_REQUEST['database'], isset($_REQUEST['reindex_force']));
if ($status == 0) doAdmin('', $lang['strreindexgood']);
@@ -549,6 +551,7 @@
echo "<p>", sprintf($lang['strconfdropschema'], $misc->printVal($_REQUEST['schema'])), "</p>\n";
echo "<form action=\"{$PHP_SELF}\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"database\" value=\"", htmlspecialchars($_REQUEST['database']), "\" />\n";
echo "<input type=\"hidden\" name=\"schema\" value=\"", htmlspecialchars($_REQUEST['schema']), "\" />\n";
@@ -579,8 +582,10 @@
global $data, $misc;
global $PHP_SELF, $lang;
+ $server_info = $misc->getServerInfo();
+
if (!isset($_POST['formName'])) $_POST['formName'] = '';
- if (!isset($_POST['formAuth'])) $_POST['formAuth'] = $_SESSION['webdbUsername'];
+ if (!isset($_POST['formAuth'])) $_POST['formAuth'] = $server_info['username'];
if (!isset($_POST['formSpc'])) $_POST['formSpc'] = '';
if (!isset($_POST['formComment'])) $_POST['formComment'] = '';
@@ -592,6 +597,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table width=\"100%\">\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data1\"><input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
@@ -673,39 +679,107 @@
),
);
+ $href = $misc->getHREF('schema');
+
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => "redirect.php?section=schema&amp;database=".urlencode($_REQUEST['database'])."&amp;",
+ 'url' => "redirect.php?subject=schema&amp;{$href}&amp;",
'vars' => array('schema' => 'nspname'),
),
'drop' => array(
'title' => $lang['strdrop'],
- 'url' => "{$PHP_SELF}?action=confirm_drop&amp;database=".urlencode($_REQUEST['database'])."&amp;",
+ 'url' => "{$PHP_SELF}?action=confirm_drop&amp;{$href}&amp;",
'vars' => array('schema' => 'nspname'),
),
'privileges' => array(
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?subject=schema&amp;database=".urlencode($_REQUEST['database'])."&amp;",
+ 'url' => "privileges.php?subject=schema&amp;{$href}&amp;",
'vars' => array('schema' => 'nspname'),
),
'alter' => array(
'title' => $lang['stralter'],
- 'url' => "{$PHP_SELF}?action=alter_schema&amp;database=".urlencode($_REQUEST['database'])."&amp;",
+ 'url' => "{$PHP_SELF}?action=alter_schema&amp;{$href}&amp;",
'vars' => array('schema' => 'nspname'),
),
);
$misc->printTable($schemas, $columns, $actions, $lang['strnoschemas']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?database=", urlencode($_REQUEST['database']),
- "&amp;action=create\">{$lang['strcreateschema']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$href}\">{$lang['strcreateschema']}</a></p>\n";
} else {
// If the database does not support schemas...
echo "<p>{$lang['strnoschemas']}</p>\n";
}
}
+ function doTree() {
+ global $misc, $data, $lang, $PHP_SELF;
+
+ $schemas = &$data->getSchemas();
+
+ $reqvars = $misc->getRequestVars('schema');
+
+ $attrs = array(
+ 'text' => field('nspname'),
+ 'icon' => 'folder',
+ 'toolTip'=> field('nspcomment'),
+ 'action' => url('redirect.php',
+ $reqvars,
+ array(
+ 'subject' => 'schema',
+ 'schema' => field('nspname')
+ )
+ ),
+ 'branch' => url('database.php',
+ $reqvars,
+ array(
+ 'action' => 'subtree',
+ 'schema' => field('nspname')
+ )
+ )
+ );
+
+ $misc->printTreeXML($schemas, $attrs);
+ exit;
+ }
+
+ function doSubTree() {
+ global $misc, $data, $lang;
+
+ include_once('classes/ArrayRecordSet.php');
+ $tabs = $misc->getNavTabs('schema');
+
+ // Remove Privileges link
+ unset($tabs['privileges']);
+
+ // Remove hidden links
+ foreach ($tabs as $i => $tab) {
+ if (isset($tab['hide']) && $tab['hide'] === true)
+ unset($tabs[$i]);
+ }
+ $items =& new ArrayRecordSet($tabs);
+
+ $reqvars = $misc->getRequestVars('schema');
+
+ $attrs = array(
+ 'text' => noEscape(field('title')),
+ 'icon' => field('icon', 'folder'),
+ 'action' => url(field('url'),
+ $reqvars,
+ field('urlvars', array())
+ ),
+ 'branch' => url(field('url'),
+ $reqvars,
+ field('urlvars'),
+ array('action' => 'tree')
+ )
+ );
+
+ $misc->printTreeXML($items, $attrs);
+ exit;
+ }
+
/**
* Display a form to permit editing schema properies.
* TODO: permit changing name, owner
@@ -753,6 +827,9 @@
doAlterSchema($lang['strschemaalteredbad']);
}
+ if ($action == 'tree') doTree();
+ if ($action == 'subtree') doSubTree();
+
$misc->printHeader($lang['strschemas']);
$misc->printBody();
diff --git a/dataexport.php b/dataexport.php
index 983cba88..fc9212f3 100644
--- a/dataexport.php
+++ b/dataexport.php
@@ -4,7 +4,7 @@
* Does an export to the screen or as a download. This checks to
* see if they have pg_dump set up, and will use it if possible.
*
- * $Id: dataexport.php,v 1.19 2005/03/04 02:27:29 chriskl Exp $
+ * $Id: dataexport.php,v 1.20 2005/05/02 15:47:23 chriskl Exp $
*/
$extensions = array(
@@ -23,28 +23,19 @@
// What must we do in this case? Maybe redirect to the homepage?
// If format is set, then perform the export
- if (isset($_REQUEST['what'])) {
-
+ if (isset($_REQUEST['what'])) {
+
// Include application functions
$_no_output = true;
include_once('./libraries/lib.inc.php');
-
+
switch ($_REQUEST['what']) {
case 'dataonly':
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()
&& ($_REQUEST['d_format'] == 'copy' || $_REQUEST['d_format'] == 'sql')) {
- $url = 'dbexport.php?mode=database&database=' . urlencode($_REQUEST['database']);
- $url .= '&what=' . urlencode($_REQUEST['what']);
- $url .= '&table=' . urlencode($_REQUEST['table']);
- if ($data->hasSchemas()) $url .= '&schema=' . urlencode($_REQUEST['schema']);
- $url .= '&d_format=' . urlencode($_REQUEST['d_format']);
- $url .= '&output=' . urlencode($_REQUEST['output']);
- if (isset($_REQUEST['d_oids'])) $url .= '&d_oids=' . urlencode($_REQUEST['d_oids']);
- $url .= "&" . SID;
-
- header("Location: {$url}");
+ include('./dbexport.php');
exit;
}
else {
@@ -56,15 +47,7 @@
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()) {
- $url = 'dbexport.php?mode=database&database=' . urlencode($_REQUEST['database']);
- $url .= '&what=' . urlencode($_REQUEST['what']);
- $url .= '&table=' . urlencode($_REQUEST['table']);
- if ($data->hasSchemas()) $url .= '&schema=' . urlencode($_REQUEST['schema']);
- $url .= '&output=' . urlencode($_REQUEST['output']);
- if (isset($_REQUEST['s_clean'])) $url .= '&s_clean=' . urlencode($_REQUEST['s_clean']);
- $url .= "&" . SID;
-
- header("Location: {$url}");
+ include('./dbexport.php');
exit;
}
else $clean = isset($_REQUEST['s_clean']);
@@ -73,17 +56,7 @@
// Check to see if they have pg_dump set up and if they do, use that
// instead of custom dump code
if ($misc->isDumpEnabled()) {
- $url = 'dbexport.php?mode=database&database=' . urlencode($_REQUEST['database']);
- $url .= '&what=' . urlencode($_REQUEST['what']);
- $url .= '&table=' . urlencode($_REQUEST['table']);
- if ($data->hasSchemas()) $url .= '&schema=' . urlencode($_REQUEST['schema']);
- $url .= '&sd_format=' . urlencode($_REQUEST['sd_format']);
- $url .= '&output=' . urlencode($_REQUEST['output']);
- if (isset($_REQUEST['sd_clean'])) $url .= '&sd_clean=' . urlencode($_REQUEST['sd_clean']);
- if (isset($_REQUEST['sd_oids'])) $url .= '&sd_oids=' . urlencode($_REQUEST['sd_oids']);
- $url .= "&" . SID;
-
- header("Location: {$url}");
+ include('./dbexport.php');
exit;
}
else {
@@ -101,7 +74,7 @@
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
header('Content-Type: text/plain');
}
- else {
+ else {
header('Content-Type: application/download');
if (isset($extensions[$format]))
@@ -118,6 +91,11 @@
if (isset($_REQUEST['query'])) $_REQUEST['query'] = trim(unserialize($_REQUEST['query']));
+ // Set the schema search path
+ if ($data->hasSchemas() && isset($_REQUEST['search_path'])) {
+ $data->setSearchPath(array_map('trim',explode(',',$_REQUEST['search_path'])));
+ }
+
// Set up the dump transaction
$status = $data->beginDump();
@@ -321,14 +299,14 @@
$status = $data->endDump();
}
else {
- if (!isset($msg)) $msg = null;
-
// Include application functions
include_once('./libraries/lib.inc.php');
- $misc->printHeader($lang['strexport']);
- echo "<h2>", $misc->printVal($_REQUEST['database']), ": {$lang['strexport']}</h2>\n";
- $misc->printMsg($msg);
+ $misc->printHeader($lang['strexport']);
+ $misc->printBody();
+ $misc->printTrail(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'database');
+ $misc->printTitle($lang['strexport']);
+ if (isset($msg)) $misc->printMsg($msg);
echo "<form action=\"{$_SERVER['PHP_SELF']}\" method=\"post\">\n";
echo "<table>\n";
@@ -355,6 +333,9 @@
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
}
echo "<input type=\"hidden\" name=\"query\" value=\"", htmlspecialchars(serialize($_REQUEST['query'])), "\" />\n";
+ if (isset($_REQUEST['search_path'])) {
+ echo "<input type=\"hidden\" name=\"search_path\" value=\"", htmlspecialchars($_REQUEST['search_path']), "\" />\n";
+ }
echo $misc->form;
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
diff --git a/dbexport.php b/dbexport.php
index b4c9662f..18cc0017 100644
--- a/dbexport.php
+++ b/dbexport.php
@@ -3,7 +3,7 @@
* Does an export of a database or a table (via pg_dump)
* to the screen or as a download.
*
- * $Id: dbexport.php,v 1.20 2005/04/12 01:52:16 chriskl Exp $
+ * $Id: dbexport.php,v 1.21 2005/05/02 15:47:23 chriskl Exp $
*/
// Prevent timeouts on large exports (non-safe mode only)
@@ -40,36 +40,32 @@
}
// Set environmental variables that pg_dump uses
- putenv('PGPASSWORD=' . $_SESSION['webdbPassword']);
- putenv('PGUSER=' . $_SESSION['webdbUsername']);
- $hostname = $conf['servers'][$_SESSION['webdbServerID']]['host'];
+ $server_info = $misc->getServerInfo();
+ putenv('PGPASSWORD=' . $server_info['password']);
+ putenv('PGUSER=' . $server_info['username']);
+ $hostname = $server_info['host'];
if ($hostname !== null && $hostname != '') {
putenv('PGHOST=' . $hostname);
}
- $port = $conf['servers'][$_SESSION['webdbServerID']]['port'];
+ $port = $server_info['port'];
if ($port !== null && $port != '') {
putenv('PGPORT=' . $port);
}
- if ($_REQUEST['mode'] == 'database') {
- putenv('PGDATABASE=' . $_REQUEST['database']);
- }
- // Check if we're doing a cluster-wide dump or just a per-database dump
- if ($_REQUEST['mode'] == 'database') {
- // Get path of the pg_dump executable.
- $exe = $misc->escapeShellCmd($conf['servers'][$_SESSION['webdbServerID']]['pg_dump_path']);
- }
- else {
- // Get path of the pg_dumpall executable.
- $exe = $misc->escapeShellCmd($conf['servers'][$_SESSION['webdbServerID']]['pg_dumpall_path']);
- }
+ // Are we doing a cluster-wide dump or just a per-database dump
+ $dumpall = ($_REQUEST['subject'] == 'server');
+
+ // Get the path og the pg_dump/pg_dumpall executable
+ $exe = $misc->escapeShellCmd($server_info[$dumpall ? 'pg_dumpall_path' : 'pg_dump_path']);
// Build command for executing pg_dump. '-i' means ignore version differences.
$cmd = $exe . " -i";
- // Check for a table specified
- if (isset($_REQUEST['table']) && $_REQUEST['mode'] == 'database') {
-
+
+ // Check for a specified table/view
+ switch ($_REQUEST['subject']) {
+ case 'table':
+ case 'view':
// Obtain the pg_dump version number
$version = array();
preg_match("/(\d+(?:\.\d+)?)(?:\.\d+)?.*$/", exec($exe . " --version"), $version);
@@ -78,7 +74,7 @@
// set dump schema as well. Also, mixed case dumping has been fixed
// then..
if (((float) $version[1]) >= 7.4) {
- $cmd .= " -t " . $misc->escapeShellArg($_REQUEST['table']);
+ $cmd .= " -t " . $misc->escapeShellArg($_REQUEST[$_REQUEST['subject']]);
// Even though they're using a schema-enabled pg_dump, the backend database
// may not support schemas.
if ($data->hasSchemas()) {
@@ -88,12 +84,12 @@
else {
// This is an annoying hack needed to work around a bug in dumping
// mixed case tables in pg_dump prior to 7.4
- $cmd .= " -t " . $misc->escapeShellArg('"' . $_REQUEST['table'] . '"');
+ $cmd .= " -t " . $misc->escapeShellArg('"' . $_REQUEST[$_REQUEST['subject']] . '"');
}
}
// Check for GZIP compression specified
- if ($_REQUEST['output'] == 'gzipped' && $_REQUEST['mode'] == 'database') {
+ if ($_REQUEST['output'] == 'gzipped' && !$dumpall) {
$cmd .= " -Z 9";
}
@@ -113,6 +109,10 @@
if (isset($_REQUEST['sd_clean'])) $cmd .= ' -c';
break;
}
+
+ if (!$dumpall) {
+ putenv('PGDATABASE=' . $_REQUEST['database']);
+ }
// Execute command and return the output to the screen
passthru($cmd);
diff --git a/display.php b/display.php
index 4ade6141..fa335c1d 100644
--- a/display.php
+++ b/display.php
@@ -9,7 +9,7 @@
* @param $return_desc The return link name
* @param $page The current page
*
- * $Id: display.php,v 1.48 2005/03/04 02:27:38 chriskl Exp $
+ * $Id: display.php,v 1.49 2005/05/02 15:47:23 chriskl Exp $
*/
// Prevent timeouts on large exports (non-safe mode only)
@@ -398,8 +398,10 @@
// Report views don't set a schema, so we need to disable create view in that case
if (isset($_REQUEST['schema'])) echo " | <a class=\"navlink\" href=\"views.php?action=create&amp;formDefinition=",
urlencode($_REQUEST['query']), "&amp;{$misc->href}\">{$lang['strcreateview']}</a>\n";
- echo " | <a class=\"navlink\" href=\"dataexport.php?query=",
- urlencode($_REQUEST['query']), "&amp;{$misc->href}\">{$lang['strdownload']}</a>\n";
+ echo " | <a class=\"navlink\" href=\"dataexport.php?query=", urlencode($_REQUEST['query']);
+ if (isset($_REQUEST['search_path']))
+ echo "&amp;search_path=", urlencode($_REQUEST['search_path']);
+ echo "&amp;{$misc->href}\">{$lang['strdownload']}</a>\n";
}
// Insert
diff --git a/domains.php b/domains.php
index f9d5ef3a..aa1d33a5 100644
--- a/domains.php
+++ b/domains.php
@@ -3,7 +3,7 @@
/**
* Manage domains in a database
*
- * $Id: domains.php,v 1.19 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: domains.php,v 1.20 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -424,6 +424,35 @@
echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$misc->href}\">{$lang['strcreatedomain']}</a></p>\n";
}
+
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data, $PHP_SELF;
+
+ $domains = &$data->getDomains();
+
+ $reqvars = $misc->getRequestVars('domain');
+
+ $attrs = array(
+ 'text' => field('domname'),
+ 'icon' => 'domains',
+ 'toolTip'=> field('domcomment'),
+ 'action' => url('domains.php',
+ $reqvars,
+ array(
+ 'action' => 'properties',
+ 'domain' => field('domname')
+ )
+ )
+ );
+
+ $misc->printTreeXML($domains, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
$misc->printHeader($lang['strdomains']);
$misc->printBody();
diff --git a/functions.php b/functions.php
index ded185b8..d24e0fad 100644
--- a/functions.php
+++ b/functions.php
@@ -3,7 +3,7 @@
/**
* Manage functions in a database
*
- * $Id: functions.php,v 1.47 2004/09/18 11:59:40 soranzo Exp $
+ * $Id: functions.php,v 1.48 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -470,12 +470,6 @@
global $data, $conf, $misc, $func;
global $PHP_SELF, $lang;
- function fnPre(&$rowdata) {
- global $data;
- $rowdata->f['+proproto'] = $rowdata->f['proname'] . " (" . $rowdata->f['proarguments'] . ")";
- $rowdata->f['+proreturns'] = ($data->phpBool($rowdata->f['proretset']) ? 'setof ' : '') . $rowdata->f['proresult'];
- }
-
$misc->printTrail('schema');
$misc->printTabs('schema','functions');
$misc->printMsg($msg);
@@ -485,12 +479,12 @@
$columns = array(
'function' => array(
'title' => $lang['strfunction'],
- 'field' => '+proproto',
+ 'field' => 'proproto',
'type' => 'verbatim',
),
'returns' => array(
'title' => $lang['strreturns'],
- 'field' => '+proreturns',
+ 'field' => 'proreturns',
'type' => 'verbatim',
),
'proglanguage' => array(
@@ -509,33 +503,65 @@
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => "redirect.php?section=function&action=properties&amp;{$misc->href}&amp;",
- 'vars' => array('function' => '+proproto', 'function_oid' => 'prooid'),
+ 'url' => "redirect.php?subject=function&action=properties&amp;{$misc->href}&amp;",
+ 'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
'alter' => array(
'title' => $lang['stralter'],
'url' => "{$PHP_SELF}?action=edit&amp;{$misc->href}&amp;",
- 'vars' => array('function' => '+proproto', 'function_oid' => 'prooid'),
+ 'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
'drop' => array(
'title' => $lang['strdrop'],
'url' => "{$PHP_SELF}?action=confirm_drop&amp;{$misc->href}&amp;",
- 'vars' => array('function' => '+proproto', 'function_oid' => 'prooid'),
+ 'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
'privileges' => array(
'title' => $lang['strprivileges'],
'url' => "privileges.php?{$misc->href}&amp;subject=function&amp;",
- 'vars' => array('function' => '+proproto', 'function_oid' => 'prooid'),
+ 'vars' => array('function' => 'proproto', 'function_oid' => 'prooid'),
),
);
- $misc->printTable($funcs, $columns, $actions, $lang['strnofunctions'], 'fnPre');
+ $misc->printTable($funcs, $columns, $actions, $lang['strnofunctions']);
echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$misc->href}\">{$lang['strcreateplfunction']}</a> | ";
echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;language=internal&amp;{$misc->href}\">{$lang['strcreateinternalfunction']}</a> | ";
echo "<a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;language=C&amp;{$misc->href}\">{$lang['strcreatecfunction']}</a></p>\n";
}
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $funcs = &$data->getFunctions();
+
+ $proto = concat(field('proname'),' (',field('proarguments'),')');
+
+ $reqvars = $misc->getRequestVars('function');
+
+ $attrs = array(
+ 'text' => $proto,
+ 'icon' => 'functions',
+ 'toolTip' => field('procomment'),
+ 'action' => url('redirect.php',
+ $reqvars,
+ array(
+ 'action' => 'properties',
+ 'function' => $proto,
+ 'function_oid' => field('prooid')
+ )
+ )
+ );
+
+ $misc->printTreeXML($funcs, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strfunctions']);
$misc->printBody();
diff --git a/groups.php b/groups.php
index 8ba7318e..870c5914 100644
--- a/groups.php
+++ b/groups.php
@@ -3,7 +3,7 @@
/**
* Manage groups in a database cluster
*
- * $Id: groups.php,v 1.19 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: groups.php,v 1.20 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -41,6 +41,7 @@
echo "<p>", sprintf($lang['strconfdropmember'], $misc->printVal($_REQUEST['user']), $misc->printVal($_REQUEST['group'])), "</p>\n";
echo "<form action=\"{$PHP_SELF}\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop_member\" />\n";
echo "<input type=\"hidden\" name=\"group\" value=\"", htmlspecialchars($_REQUEST['group']), "\" />\n";
echo "<input type=\"hidden\" name=\"user\" value=\"", htmlspecialchars($_REQUEST['user']), "\" />\n";
@@ -105,7 +106,7 @@
echo "<input type=\"hidden\" name=\"action\" value=\"add_member\" />\n";
echo "</form>\n";
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF\">{$lang['strshowallgroups']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?{$misc->href}\">{$lang['strshowallgroups']}</a></p>\n";
}
/**
@@ -122,6 +123,7 @@
echo "<p>", sprintf($lang['strconfdropgroup'], $misc->printVal($_REQUEST['group'])), "</p>\n";
echo "<form action=\"{$PHP_SELF}\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"group\" value=\"", htmlspecialchars($_REQUEST['group']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
@@ -155,6 +157,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data\"><input size=\"32\" maxlength=\"{$data->_maxNameLen}\" name=\"name\" value=\"", htmlspecialchars($_POST['name']), "\" /></td>\n\t</tr>\n";
@@ -162,7 +165,7 @@
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strmembers']}</th>\n";
echo "\t\t<td class=\"data\">\n";
- echo "\t\t\t<select name=\"members[]\" multiple=\"multiple\" size=\"", min(6, $users->recordCount()), "\">\n";
+ echo "\t\t\t<select name=\"members[]\" multiple=\"multiple\" size=\"", min(40, $users->recordCount()), "\">\n";
while (!$users->EOF) {
$username = $users->f['usename'];
echo "\t\t\t\t<option value=\"{$username}\"",
@@ -238,7 +241,7 @@
$misc->printTable($groups, $columns, $actions, $lang['strnogroups']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create\">{$lang['strcreategroup']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$misc->href}\">{$lang['strcreategroup']}</a></p>\n";
}
diff --git a/images/themes/default/I.png b/images/themes/default/I.png
new file mode 100644
index 00000000..f56e3054
--- /dev/null
+++ b/images/themes/default/I.png
Binary files differ
diff --git a/images/themes/default/L.png b/images/themes/default/L.png
new file mode 100644
index 00000000..825498bb
--- /dev/null
+++ b/images/themes/default/L.png
Binary files differ
diff --git a/images/themes/default/Lminus.png b/images/themes/default/Lminus.png
new file mode 100644
index 00000000..2ed7a192
--- /dev/null
+++ b/images/themes/default/Lminus.png
Binary files differ
diff --git a/images/themes/default/Lplus.png b/images/themes/default/Lplus.png
new file mode 100644
index 00000000..b50e9bb9
--- /dev/null
+++ b/images/themes/default/Lplus.png
Binary files differ
diff --git a/images/themes/default/T.png b/images/themes/default/T.png
new file mode 100644
index 00000000..b127a8c4
--- /dev/null
+++ b/images/themes/default/T.png
Binary files differ
diff --git a/images/themes/default/Tminus.png b/images/themes/default/Tminus.png
new file mode 100644
index 00000000..ca962d8e
--- /dev/null
+++ b/images/themes/default/Tminus.png
Binary files differ
diff --git a/images/themes/default/Tplus.png b/images/themes/default/Tplus.png
new file mode 100644
index 00000000..0f9859da
--- /dev/null
+++ b/images/themes/default/Tplus.png
Binary files differ
diff --git a/images/themes/default/blank.png b/images/themes/default/blank.png
new file mode 100644
index 00000000..fa9a36d9
--- /dev/null
+++ b/images/themes/default/blank.png
Binary files differ
diff --git a/images/themes/default/file.png b/images/themes/default/file.png
new file mode 100644
index 00000000..5e274c4d
--- /dev/null
+++ b/images/themes/default/file.png
Binary files differ
diff --git a/images/themes/default/folder.png b/images/themes/default/folder.png
new file mode 100644
index 00000000..a65d0317
--- /dev/null
+++ b/images/themes/default/folder.png
Binary files differ
diff --git a/images/themes/default/folderOpen.png b/images/themes/default/folderOpen.png
new file mode 100644
index 00000000..a13a2edc
--- /dev/null
+++ b/images/themes/default/folderOpen.png
Binary files differ
diff --git a/images/themes/default/loading.gif b/images/themes/default/loading.gif
new file mode 100644
index 00000000..f3f1963a
--- /dev/null
+++ b/images/themes/default/loading.gif
Binary files differ
diff --git a/images/themes/default/root.png b/images/themes/default/root.png
new file mode 100644
index 00000000..a65d0317
--- /dev/null
+++ b/images/themes/default/root.png
Binary files differ
diff --git a/images/themes/default/title.png b/images/themes/default/title.png
index 2015f307..99a58e36 100644
--- a/images/themes/default/title.png
+++ b/images/themes/default/title.png
Binary files differ
diff --git a/index.php b/index.php
index 9e11a725..f506fcd3 100755
--- a/index.php
+++ b/index.php
@@ -3,33 +3,36 @@
/**
* Main access point to the app.
*
- * $Id: index.php,v 1.11 2004/07/12 04:18:40 chriskl Exp $
+ * $Id: index.php,v 1.12 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
+ $_no_db_connection = true;
include_once('./libraries/lib.inc.php');
$misc->printHeader();
+
+ $rtl = (strcasecmp($lang['applangdir'], 'rtl') == 0);
+
+ $cols = $rtl ? '*,'.$conf['left_width'] : $conf['left_width'].',*';
+ $mainframe = '<frame src="intro.php" name="detail" id="detail" frameborder="0" />'
?>
-<frameset rows="52,*,12">
- <frame src="topbar.php" name="topbar" scrolling="no" noresize="noresize" frameborder="0" />
-<?php if (strcasecmp($lang['applangdir'], 'rtl') == 0) : ?>
- <frameset cols="*,<?php echo $conf['left_width'] ?>">
- <frame src="intro.php" name="detail" frameborder="0" />
- <frame src="browser.php" name="browser" frameborder="0" />
- </frameset>
-<?php else: ?>
- <frameset cols="<?php echo $conf['left_width'] ?>,*">
- <frame src="browser.php" name="browser" frameborder="0" />
- <frame src="intro.php" name="detail" frameborder="0" />
- </frameset>
-<?php endif; ?>
- <frame src="bottombar.php" name="bottombar" scrolling="no" noresize="noresize" frameborder="0" />
+<frameset cols="<?php echo $cols ?>">
+
+<?php if ($rtl) echo $mainframe; ?>
+
+ <frame src="browser.php" name="browser" id="browser" frameborder="0" />
+
+<?php if (!$rtl) echo $mainframe; ?>
+
<noframes>
<body>
- <?php echo $lang['strnoframes'] ?>
+ <?php echo $lang['strnoframes'] ?><br />
+ <a href="intro.php"><?php echo $lang['strnoframeslink'] ?></a>
</body>
</noframes>
+
</frameset>
+
<?php
$misc->printFooter(false);
?>
diff --git a/indexes.php b/indexes.php
index a3c1d7c7..06c33d38 100644
--- a/indexes.php
+++ b/indexes.php
@@ -3,7 +3,7 @@
/**
* List indexes on a table
*
- * $Id: indexes.php,v 1.34 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: indexes.php,v 1.35 2005/05/02 15:47:23 chriskl Exp $
*/
// Include application functions
@@ -308,7 +308,7 @@
$misc->printTable($indexes, $columns, $actions, $lang['strnoindexes'], 'indPre');
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create_index&{$misc->href}&table=", urlencode($_REQUEST['table']), "\">{$lang['strcreateindex']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create_index&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']), "\">{$lang['strcreateindex']}</a></p>\n";
}
$misc->printHeader($lang['strindexes'], "<script src=\"indexes.js\" type=\"text/javascript\"></script>");
diff --git a/intro.php b/intro.php
index c0af8f46..5fcf3651 100755
--- a/intro.php
+++ b/intro.php
@@ -3,7 +3,7 @@
/**
* Intro screen
*
- * $Id: intro.php,v 1.14 2005/01/17 10:09:43 jollytoad Exp $
+ * $Id: intro.php,v 1.15 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions (no db conn)
@@ -12,26 +12,39 @@
$misc->printHeader();
$misc->printBody();
+
+ $misc->printTrail('root');
+ $misc->printTabs('root','intro');
?>
<h1><?php echo "$appName $appVersion (PHP ". phpversion() .')' ?></h1>
-<p><?php echo $lang['strintro'] ?></p>
-
-<ul>
-<li><b><a href="all_db.php"><?php echo $lang['strdatabases'] ?></a></b></li>
-<li><b><a href="http://phppgadmin.sourceforge.net/" target="_top"><?php echo $lang['strppahome'] ?></a></b></li>
-<li><b><a href="<?php echo $lang['strpgsqlhome_url'] ?>" target="_top"><?php echo $lang['strpgsqlhome'] ?></a></b></li>
+<form method="get" action="<?php echo $_SERVER['PHP_SELF'] ?>">
+ <label>
+ <select name="language" onchange="this.form.submit()">
<?php
- //if ( isset($conf['docdir'])) {
- // echo "<li><b><a href=\"". $conf['docdir'] ."\" target=\"_top\">";
- // echo $lang['strlocaldocs'] ."</a></b></li>";
- //}
+ $language = isset($_SESSION['webdbLanguage']) ? $_SESSION['webdbLanguage'] : 'english';
+ foreach ($appLangFiles as $k => $v) {
+ echo "<option value=\"{$k}\"",
+ ($k == $language) ? ' selected="selected"' : '',
+ ">{$v}</option>\n";
+ }
?>
-<li><b><a href="http://sourceforge.net/tracker/?group_id=37132&amp;atid=418980" target="_top"><?php echo $lang['strreportbug'] ?></a></b></li>
-<li><b><a href="<?php echo $lang['strviewfaq_url'] ?>" target="_top"><?php echo $lang['strviewfaq'] ?></a></b></li>
+ </select>
+ <noscript><input type="submit" value="<?php echo $lang['stralter'] ?>" /></noscript>
+ </label>
+</form>
+
+<p><?php echo $lang['strintro'] ?></p>
+
+<ul class="intro">
+<li><a href="http://phppgadmin.sourceforge.net/" target="_top"><?php echo $lang['strppahome'] ?></a></li>
+<li><a href="<?php echo $lang['strpgsqlhome_url'] ?>" target="_top"><?php echo $lang['strpgsqlhome'] ?></a></li>
+<li><a href="http://sourceforge.net/tracker/?group_id=37132&amp;atid=418980" target="_top"><?php echo $lang['strreportbug'] ?></a></li>
+<li><a href="<?php echo $lang['strviewfaq_url'] ?>" target="_top"><?php echo $lang['strviewfaq'] ?></a></li>
</ul>
<?php
+ if (isset($_GET['language'])) $_reload_browser = true;
$misc->printFooter();
?>
diff --git a/lang/english.php b/lang/english.php
index b9ccfb0e..157b7920 100755
--- a/lang/english.php
+++ b/lang/english.php
@@ -4,7 +4,7 @@
* English language file for phpPgAdmin. Use this as a basis
* for new translations.
*
- * $Id: english.php,v 1.174 2005/04/30 18:02:02 soranzo Exp $
+ * $Id: english.php,v 1.175 2005/05/02 15:47:27 chriskl Exp $
*/
// Language and character set
@@ -29,6 +29,10 @@
$lang['strloginfailed'] = 'Login failed';
$lang['strlogindisallowed'] = 'Login disallowed for security reasons.';
$lang['strserver'] = 'Server';
+ $lang['strservers'] = 'Servers';
+ $lang['strintroduction'] = 'Introduction';
+ $lang['strhost'] = 'Host';
+ $lang['strport'] = 'Port';
$lang['strlogout'] = 'Logout';
$lang['strowner'] = 'Owner';
$lang['straction'] = 'Action';
@@ -128,7 +132,8 @@
$lang['strfileimported'] = 'File imported.';
// Error handling
- $lang['strnoframes'] = 'You need a frames-enabled browser to use this application.';
+ $lang['strnoframes'] = 'This application works best with a frames-enabled browser, but can be used without frames by following the link below.';
+ $lang['strnoframeslink'] = 'Use without frames';
$lang['strbadconfig'] = 'Your config.inc.php is out of date. You will need to regenerate it from the new config.inc.php-dist.';
$lang['strnotloaded'] = 'Your PHP installation does not support PostgreSQL. You need to recompile PHP using the --with-pgsql configure option.';
$lang['strpostgresqlversionnotsupported'] = 'Version of PostgreSQL not supported. Please upgrade to version %s or later.';
@@ -639,5 +644,10 @@
$lang['strtimefmt'] = 'jS M, Y g:iA';
$lang['strhelp'] = 'Help';
$lang['strhelpicon'] = '?';
+ $lang['strlogintitle'] = 'Login to %s';
+ $lang['strlogoutmsg'] = 'Logged out of %s';
+ $lang['strloading'] = 'Loading...';
+ $lang['strerrorloading'] = 'Error Loading';
+ $lang['strclicktoreload'] = 'Click to reload';
?>
diff --git a/lang/translations.php b/lang/translations.php
new file mode 100644
index 00000000..4ff4d028
--- /dev/null
+++ b/lang/translations.php
@@ -0,0 +1,73 @@
+<?php
+ /**
+ * Supported Translations for phpPgAdmin
+ *
+ * $Id: translations.php,v 1.2 2005/05/02 15:47:27 chriskl Exp $
+ */
+
+
+ // List of language files, and encoded language name.
+
+ $appLangFiles = array(
+ 'afrikaans' => 'Afrikaans',
+ 'arabic' => '&#1593;&#1585;&#1576;&#1610;',
+ 'chinese-tr' => '&#32321;&#39636;&#20013;&#25991;',
+ 'chinese-sim' => '&#31616;&#20307;&#20013;&#25991;',
+ 'czech' => '&#268;esky',
+ 'danish' => 'Danish',
+ 'dutch' => 'Nederlands',
+ 'english' => 'English',
+ 'french' => 'Fran&ccedil;ais',
+ 'german' => 'Deutsch',
+ 'hebrew' => 'Hebrew',
+ 'italian' => 'Italiano',
+ 'japanese' => '&#26085;&#26412;&#35486;',
+ 'hungarian' => 'Magyar',
+ 'mongol' => 'Mongolian',
+ 'polish' => 'Polski',
+ 'portuguese-br' => 'Portugu&ecirc;s-Brasileiro',
+ 'romanian' => 'Rom&acirc;n&#259;',
+ 'russian' => '&#1056;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;',
+ 'slovak' => 'Slovensky',
+ 'swedish' => 'Svenska',
+ 'spanish' => 'Espa&ntilde;ol',
+ 'turkish' => 'T&uuml;rk&ccedil;e',
+ 'ukrainian' => '&#1059;&#1082;&#1088;&#1072;&#9558;&#1085;&#1089;&#1100;&#1082;&#1072;'
+ );
+
+
+ // ISO639 language code to language file mapping.
+ // See http://www.w3.org/WAI/ER/IG/ert/iso639.htm for language codes
+
+ // If it's available 'language-country', but not general
+ // 'language' translation (eg. 'portuguese-br', but not 'portuguese')
+ // specify both 'la' => 'language-country' and 'la-co' => 'language-country'.
+
+ $availableLanguages = array(
+ 'af' => 'afrikaans',
+ 'ar' => 'arabic',
+ 'zh' => 'chinese-tr',
+ 'zh-cn' => 'chinese-sim',
+ 'cs' => 'czech',
+ 'da' => 'danish',
+ 'nl' => 'dutch',
+ 'en' => 'english',
+ 'fr' => 'french',
+ 'de' => 'german',
+ 'he' => 'hebrew',
+ 'it' => 'italian',
+ 'ja' => 'japanese',
+ 'hu' => 'hungarian',
+ 'mn' => 'mongol',
+ 'pl' => 'polish',
+ 'pt' => 'portuguese-br',
+ 'pt-br' => 'portuguese-br',
+ 'ro' => 'romanian',
+ 'ru' => 'russian',
+ 'sk' => 'slovak',
+ 'sv' => 'swedish',
+ 'es' => 'spanish',
+ 'tr' => 'turkish',
+ 'uk' => 'ukrainian'
+ );
+?>
diff --git a/libraries/decorator.inc.php b/libraries/decorator.inc.php
new file mode 100644
index 00000000..3427f377
--- /dev/null
+++ b/libraries/decorator.inc.php
@@ -0,0 +1,206 @@
+<?php
+// $Id: decorator.inc.php,v 1.2 2005/05/02 15:47:28 chriskl Exp $
+
+// This group of functions and classes provides support for
+// resolving values in a lazy manner (ie, as and when required)
+// using the Decorator pattern.
+
+###TODO: Better documentation!!!
+
+// Construction functions:
+
+function field($fieldName, $default = null) {
+ return new FieldDecorator($fieldName, $default);
+}
+
+function merge(/* ... */) {
+ return new ArrayMergeDecorator(func_get_args());
+}
+
+function concat(/* ... */) {
+ return new ConcatDecorator(func_get_args());
+}
+
+function callback($callback, $params = null) {
+ return new CallbackDecorator($callback, $params);
+}
+
+function ifempty($value, $empty, $full = null) {
+ return new IfEmptyDecorator($value, $empty, $full);
+}
+
+function url($base, $vars = null /* ... */) {
+ // If more than one array of vars is given,
+ // use an ArrayMergeDecorator to have them merged
+ // at value evaluation time.
+ if (func_num_args() > 2) {
+ $v = func_get_args();
+ array_shift($v);
+ return new UrlDecorator($base, new ArrayMergeDecorator($v));
+ }
+ return new UrlDecorator($base, $vars);
+}
+
+function noEscape($value) {
+ if (is_a($value, 'Decorator')) {
+ $value->esc = false;
+ return $value;
+ }
+ return new Decorator($value, false);
+}
+
+// Resolving functions:
+
+function value(&$var, &$fields, $esc = null) {
+ if (is_a($var, 'Decorator')) {
+ $val =& $var->value($fields);
+ if (!$var->esc) $esc = null;
+ } else {
+ $val =& $var;
+ }
+ if (is_string($val)) {
+ switch($esc) {
+ case 'xml':
+ return strtr($val, array(
+ '&' => '&amp;',
+ "'" => '&apos;', '"' => '&quot;',
+ '<' => '&lt;', '>' => '&gt;'
+ ));
+ case 'html':
+ return htmlspecialchars($val);
+ case 'url':
+ return urlencode($val);
+ }
+ }
+ return $val;
+}
+
+function value_xml(&$var, &$fields) {
+ return value($var, $fields, 'xml');
+}
+
+function value_xml_attr($attr, &$var, &$fields) {
+ $val = value($var, $fields, 'xml');
+ if (!empty($val))
+ return " {$attr}=\"{$val}\"";
+ else
+ return '';
+}
+
+function value_url(&$var, &$fields) {
+ return value($var, $fields, 'url');
+}
+
+// Underlying classes:
+
+class Decorator
+{
+ var $esc = true;
+
+ function Decorator($value, $esc = true) {
+ $this->v = $value;
+ $this->esc = $esc;
+ }
+
+ function value() {
+ return $this->v;
+ }
+}
+
+class FieldDecorator extends Decorator
+{
+ function FieldDecorator($fieldName, $default = null) {
+ $this->f = $fieldName;
+ if ($default !== null) $this->d = $default;
+ }
+
+ function value($fields) {
+ return isset($fields[$this->f]) ? $fields[$this->f] : (isset($this->d) ? $this->d : null);
+ }
+}
+
+class ArrayMergeDecorator extends Decorator
+{
+ function ArrayMergeDecorator($arrays) {
+ $this->m = $arrays;
+ }
+
+ function value($fields) {
+ $accum = array();
+ foreach($this->m as $var) {
+ $accum = array_merge($accum, value($var, $fields));
+ }
+ return $accum;
+ }
+}
+
+class ConcatDecorator extends Decorator
+{
+ function ConcatDecorator($values) {
+ $this->c = $values;
+ }
+
+ function value($fields) {
+ $accum = '';
+ foreach($this->c as $var) {
+ $accum .= value($var, $fields);
+ }
+ return $accum;
+ }
+}
+
+class CallbackDecorator extends Decorator
+{
+ function CallbackDecorator($callback, $param = null) {
+ $this->fn = $callback;
+ $this->p = $param;
+ }
+
+ function value($fields) {
+ return call_user_func($this->fn, $fields, $this->p);
+ }
+}
+
+class IfEmptyDecorator extends Decorator
+{
+ function IfEmptyDecorator($value, $empty, $full = null) {
+ $this->v = $value;
+ $this->e = $empty;
+ if ($full !== null) $this->f = $full;
+ }
+
+ function value($fields) {
+ $val = value($this->v, $fields);
+ if (empty($val))
+ return value($this->e, $fields);
+ else
+ return isset($this->f) ? value($this->f, $fields) : $val;
+ }
+}
+
+class UrlDecorator extends Decorator
+{
+ function UrlDecorator($base, $queryVars = null) {
+ $this->b = $base;
+ if ($queryVars !== null)
+ $this->q = $queryVars;
+ }
+
+ function value($fields) {
+ $url = value($this->b, $fields);
+
+ if ($url === false) return '';
+
+ if (!empty($this->q)) {
+ $queryVars = value($this->q, $fields);
+
+ $sep = '?';
+ foreach ($queryVars as $var => $value) {
+ $url .= $sep . value_url($var, $fields) . '=' . value_url($value, $fields);
+ $sep = '&';
+ }
+ }
+ return $url;
+ }
+}
+?>
diff --git a/libraries/errorhandler.inc.php b/libraries/errorhandler.inc.php
index 2e7b1d0e..5afdaeb2 100644
--- a/libraries/errorhandler.inc.php
+++ b/libraries/errorhandler.inc.php
@@ -3,7 +3,7 @@
/**
* Overrides default ADODB error handler to provide nicer error handling.
*
- * $Id: errorhandler.inc.php,v 1.16 2004/07/19 03:01:54 chriskl Exp $
+ * $Id: errorhandler.inc.php,v 1.17 2005/05/02 15:47:28 chriskl Exp $
*/
define('ADODB_ERROR_HANDLER','Error_Handler');
@@ -38,6 +38,8 @@ function Error_Handler($dbms, $fn, $errno, $errmsg, $p1=false, $p2=false)
case 'PCONNECT':
case 'CONNECT':
$_failed = true;
+ unset($_SESSION['webdbLogin'][$_REQUEST['server']]);
+ $msg = $lang['strloginfailed'];
include('./login.php');
exit;
break;
diff --git a/libraries/lib.inc.php b/libraries/lib.inc.php
index f18c1283..79ab4713 100644
--- a/libraries/lib.inc.php
+++ b/libraries/lib.inc.php
@@ -3,8 +3,10 @@
/**
* Function library read in upon startup
*
- * $Id: lib.inc.php,v 1.93 2005/03/16 01:49:11 chriskl Exp $
+ * $Id: lib.inc.php,v 1.94 2005/05/02 15:47:28 chriskl Exp $
*/
+ include_once('decorator.inc.php');
+ include_once('./lang/translations.php');
// Set error reporting level to max
error_reporting(E_ALL);
@@ -38,36 +40,6 @@
// backwards incompatible changes are made to config.inc.php-dist.
$conf['base_version'] = 14;
- // List of available language files. Remember to update login.php
- // when you update this list.
- $appLangFiles = array(
- 'afrikaans' => 'Afrikaans',
- 'arabic' => '&#1593;&#1585;&#1576;&#1610;',
- 'chinese-tr' => '&#32321;&#39636;&#20013;&#25991;',
- 'chinese-sim' => '&#31616;&#20307;&#20013;&#25991;',
- 'czech' => '&#268;esky',
- 'danish' => 'Danish',
- 'dutch' => 'Nederlands',
- 'english' => 'English',
- 'french' => 'Fran&ccedil;ais',
- 'german' => 'Deutsch',
- 'hebrew' => 'Hebrew',
- 'italian' => 'Italiano',
- 'japanese' => '&#26085;&#26412;&#35486;',
- 'hungarian' => 'Magyar',
- 'mongol' => 'Mongolian',
- 'polish' => 'Polski',
- 'portuguese-br' => 'Portugu&ecirc;s-Brasileiro',
- 'portuguese-pt' => 'Portugu&ecirc;s-Portugu&ecirc;s',
- 'romanian' => 'Rom&acirc;n&#259;',
- 'russian' => '&#1056;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;',
- 'slovak' => 'Slovensky',
- 'swedish' => 'Svenska',
- 'spanish' => 'Espa&ntilde;ol',
- 'turkish' => 'T&uuml;rk&ccedil;e',
- 'ukrainian' => '&#1059;&#1082;&#1088;&#1072;&#9558;&#1085;&#1089;&#1100;&#1082;&#1072;'
- );
-
// Always include english.php, since it's the master language file
if (!isset($conf['default_lang'])) $conf['default_lang'] = 'english';
$lang = array();
@@ -102,32 +74,64 @@
ini_set('arg_separator.output', '&amp;');
// If login action is set, then set session variables
- if (isset($_POST['formServer']) && isset($_POST['formUsername']) &&
- isset($_POST['formPassword']) && isset($_POST['formLanguage'])) {
- $_SESSION['webdbServerID'] = $_POST['formServer'];
- $_SESSION['webdbUsername'] = $_POST['formUsername'];
- $_SESSION['webdbPassword'] = $_POST['formPassword'];
- $_SESSION['webdbLanguage'] = $_POST['formLanguage'];
+ if (isset($_POST['loginServer']) && isset($_POST['loginUsername']) &&
+ isset($_POST['loginPassword'])) {
+
+ $_server_info = $misc->getServerInfo($_POST['loginServer']);
+
+ $_server_info['username'] = $_POST['loginUsername'];
+ $_server_info['password'] = $_POST['loginPassword'];
+
+ $misc->setServerInfo(null, $_server_info, $_POST['loginServer']);
+
+ $_reload_browser = true;
}
- // If the logged in settings aren't present, put up the login screen.
- if (!isset($_SESSION['webdbUsername'])
- || !isset($_SESSION['webdbPassword'])
- || !isset($_SESSION['webdbServerID'])
- || !isset($_SESSION['webdbLanguage'])
- || !isset($conf['servers'][$_SESSION['webdbServerID']])) {
- include('./login.php');
- exit;
+ // Determine language file to import:
+
+ // 1. Check for the language from a request var
+ if (isset($_REQUEST['language'])) {
+ $_language = strtolower($_REQUEST['language']);
+ if (!isset($appLangFiles[$_language]))
+ unset($_language);
}
-
- // Import language file
- include('./lang/recoded/' . strtolower($_SESSION['webdbLanguage']) . '.php');
-
- // If extra login check fails, back to the login screen
- $_allowed = $misc->checkExtraSecurity();
- if (!$_allowed) {
- include('./login.php');
- exit;
+
+ // 2. Check for language session var
+ if (!isset($_language) && isset($_SESSION['webdbLanguage']) && isset($appLangFiles[$_SESSION['webdbLanguage']])) {
+ $_language = $_SESSION['webdbLanguage'];
+ }
+
+ // 3. Check for acceptable languages in HTTP_ACCEPT_LANGUAGE var
+ if (!isset($_language) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+ // extract acceptable language tags
+ // (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)
+ preg_match_all('/\s*([a-z]{1,8}(?:-[a-z]{1,8})*)(?:;q=([01](?:.[0-9]{0,3})?))?\s*(?:,|$)/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']), $_m, PREG_SET_ORDER);
+ foreach($_m as $_l) { // $_l[1] = language tag, [2] = quality
+ if (!isset($_l[2])) $_l[2] = 1; // Default quality to 1
+ if ($_l[2] > 0 && $_l[2] <= 1 && isset($availableLanguages[$_l[1]])) {
+ // Build up array of (quality => language_file)
+ $_acceptLang[$_l[2]] = $availableLanguages[$_l[1]];
+ }
+ }
+ unset($_m);
+ unset($_l);
+ if (isset($_acceptLang)) {
+ // Sort acceptable languages by quality
+ krsort($_acceptLang, SORT_NUMERIC);
+ $_language = reset($_acceptLang);
+ unset($_acceptLang);
+ }
+ }
+
+ // 4. Otherwise resort to the default set in the config file
+ if (!isset($_language) && isset($appLangFiles[$conf['default_lang']])) {
+ $_language = $conf['default_lang'];
+ }
+
+ // Import the language file
+ if (isset($_language)) {
+ include("./lang/recoded/{$_language}.php");
+ $_SESSION['webdbLanguage'] = $_language;
}
// Check database support is properly compiled in
@@ -138,36 +142,30 @@
// Create data accessor object, if necessary
if (!isset($_no_db_connection)) {
+ if (!isset($_REQUEST['server'])) {
+ die('No server supplied!');
+ # TODO: nice error
+ }
+
+ $_server_info = $misc->getServerInfo();
+
+ // Redirect to the login form if not logged in
+ if (!isset($_server_info['username'])) {
+ include('./login.php');
+ exit;
+ }
+
// Connect to the current database, or if one is not specified
// then connect to the default database.
if (isset($_REQUEST['database']))
$_curr_db = $_REQUEST['database'];
else
- $_curr_db = $conf['servers'][$_SESSION['webdbServerID']]['defaultdb'];
+ $_curr_db = $_server_info['defaultdb'];
- // Create the connection object and make the connection
include_once('./classes/database/Connection.php');
- $_connection = new Connection(
- $conf['servers'][$_SESSION['webdbServerID']]['host'],
- $conf['servers'][$_SESSION['webdbServerID']]['port'],
- $_SESSION['webdbUsername'],
- $_SESSION['webdbPassword'],
- $_curr_db
- );
-
- // Get the name of the database driver we need to use. The description
- // of the server is returned and placed into the conf array.
- $_type = $_connection->getDriver($conf['description']);
- if ($_type === null) {
- printf($lang['strpostgresqlversionnotsupported'], $postgresqlMinVer);
- exit;
- }
-
- // Create a database wrapper class for easy manipulation of the
- // connection.
- require_once('./classes/database/' . $_type . '.php');
- $data = new $_type($_connection->conn);
- $data->platform = $_connection->platform;
+
+ // Connect to database and set the global $data variable
+ $data =& $misc->getDatabaseAccessor($_curr_db);
// If schema is defined and database supports schemas, then set the
// schema explicitly.
diff --git a/login.php b/login.php
index 19229a21..ab115f3f 100755
--- a/login.php
+++ b/login.php
@@ -3,175 +3,51 @@
/**
* Login screen
*
- * $Id: login.php,v 1.24 2005/03/16 01:48:59 chriskl Exp $
+ * $Id: login.php,v 1.25 2005/05/02 15:47:24 chriskl Exp $
*/
// This needs to be an include once to prevent lib.inc.php infinite recursive includes.
// Check to see if the configuration file exists, if not, explain
require_once('./libraries/lib.inc.php');
+
+ $misc->printHeader($lang['strlogin']);
+ $misc->printBody();
+ $misc->printTrail('root');
+
+ $server_info = $misc->getServerInfo($_REQUEST['server']);
+
+ $misc->printTitle(sprintf($lang['strlogintitle'], $server_info['desc']));
+
+ $loginServer = htmlspecialchars($_REQUEST['server']);
+ $loginUsername = '';
+
+ if (isset($msg)) $misc->printMsg($msg);
+?>
- // Prepare form variables
- if (!isset($_POST['formServer'])) $_POST['formServer'] = '';
- if (!isset($_POST['formLanguage'])) {
- // Parse the user acceptable language in HTTP_ACCEPT_LANGUAGE
- // ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 )
- // If there's one available, then overwrite the default language.
- if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
- $userLanguage = '';
- $userLanguages = array();
- $acceptableLanguages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
- foreach ($acceptableLanguages as $accLang) {
- $languageInfos = explode(';', trim($accLang));
- $languageRange = strtolower($languageInfos[0]);
- if (isset($languageInfos[1]) && substr($languageInfos[1], 0, 2) == 'q=')
- $languageQuality = (float)substr($languageInfos[1], 2, 5);
- else
- $languageQuality = 1;
- // If the language is already in the array, check that we
- // don't overwrite its quality value with a lower one
- if ((!array_key_exists($languageRange, $userLanguages))
- || ($userLanguages[$languageRange] < $languageQuality))
- $userLanguages[$languageRange] = $languageQuality;
- }
- arsort($userLanguages, SORT_NUMERIC);
-
- // if it's available 'language-country', but not general 'language' translation
- // (eg. 'portuguese-br', but not 'portuguese')
- // specify both 'la' => 'language-country' and 'la-co' => 'language-country'.
- // See http://www.w3.org/WAI/ER/IG/ert/iso639.htm for language codes
- $availableLanguages = array(
- 'af' => 'afrikaans',
- 'ar' => 'arabic',
- 'zh' => 'chinese-tr',
- 'zh-cn' => 'chinese-sim',
- 'cs' => 'czech',
- 'da' => 'danish',
- 'nl' => 'dutch',
- 'en' => 'english',
- 'fr' => 'french',
- 'de' => 'german',
- 'he' => 'hebrew',
- 'it' => 'italian',
- 'ja' => 'japanese',
- 'hu' => 'hungarian',
- 'mn' => 'mongol',
- 'pl' => 'polish',
- 'pt' => 'portuguese-pt',
- 'pt-br' => 'portuguese-br',
- 'pt-pt' => 'portuguese-pt',
- 'ro' => 'romanian',
- 'ru' => 'russian',
- 'sk' => 'slovak',
- 'sv' => 'swedish',
- 'es' => 'spanish',
- 'tr' => 'turkish',
- 'uk' => 'ukrainian'
- );
-
- reset($userLanguages);
- do {
- $languageRange = key($userLanguages);
- if (array_key_exists($languageRange, $availableLanguages)) {
- $userLanguage = $availableLanguages[$languageRange];
- }
- } while ($userLanguage == '' && next($userLanguages));
- if ($userLanguage != '') $conf['default_lang'] = $userLanguage;
- }
- $_POST['formLanguage'] = $conf['default_lang'];
- // Include default language over english.
- include_once('./lang/recoded/' . strtolower($conf['default_lang']) . '.php');
- }
-
- // Check for config file version mismatch
- if (!isset($conf['version']) || $conf['base_version'] > $conf['version']) {
- echo $lang['strbadconfig'];
- exit;
- }
-
- // Force encoding to UTF-8
- $lang['appcharset'] = 'UTF-8';
-
- // Output header
- if (isset($_failed) && $_failed) {
- $misc->printHeader($lang['strlogin'], "<script type=\"text/javascript\"><!--
- // show login form in top frame
- if (top != self) {
- window.top.location.href='./index.php?{$_SERVER['QUERY_STRING']}';
- }
- //-->
-</script>");
- } else {
- $misc->printHeader($lang['strlogin']);
+<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" name="login_form">
+<?php
+ if (!empty($_POST)) $vars =& $_POST;
+ else $vars =& $_GET;
+ // Pass request vars through form (is this a security risk???)
+ foreach ($vars as $key => $val) {
+ if (substr($key,0,5) == 'login') continue;
+ echo "<input type=\"hidden\" name=\"", htmlspecialchars($key), "\" value=\"", htmlspecialchars($val), "\" />\n";
}
- $misc->printBody();
?>
+ <input type="hidden" name="loginServer" value="<?php echo $loginServer; ?>" />
+ <table class="navbar" border="0" cellpadding="5" cellspacing="3">
+ <tr>
+ <td><?php echo $lang['strusername']; ?></td>
+ <td><input type="text" name="loginUsername" value="<?php echo $loginUsername; ?>" size="24" /></td>
+ </tr>
+ <tr>
+ <td><?php echo $lang['strpassword']; ?></td>
+ <td><input type="password" name="loginPassword" size="24" /></td>
+ </tr>
+ </table>
+ <p><input type="submit" name="loginSubmit" value="<?php echo $lang['strlogin']; ?>" /></p>
+</form>
- <table class="navbar" border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 100%">
- <tr>
- <td height="115" align="center" valign="middle">
- <center>
- <h1><?php echo $appName ?> <?php echo $appVersion ?> <?php echo $lang['strlogin'] ?></h1>
- <?php
- if (isset($_failed) && $_failed)
- echo "<p class=\"message\">{$lang['strloginfailed']}</p>";
- elseif (isset($_allowed) && !$_allowed) {
- echo "<p class=\"message\">{$lang['strlogindisallowed']}\n";
- echo "<br /><a href=\"{$lang['strviewfaq_url']}\">{$lang['strviewfaq']}</a></p>";
- }
- ?>
- <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" name="login_form">
- <table class="navbar" border="0" cellpadding="5" cellspacing="3">
- <tr>
- <th><?php echo $lang['strusername'] ?>:</th>
- <td><input type="text" name="formUsername" value="<?php echo (isset($_POST['formUsername'])) ? htmlspecialchars($_POST['formUsername']) : '' ?>" size="24" /></td>
- </tr>
- <tr>
- <th><?php echo $lang['strpassword'] ?>:</th>
- <td><input type="password" name="formPassword" size="24" /></td>
- </tr>
- <tr>
- <th><?php echo $lang['strserver'] ?>:</th>
- <td><select name="formServer">
- <?php
- for ($i = 0; $i < sizeof($conf['servers']); $i++) {
- echo "<option value=\"{$i}\"",
- ($i == $_POST['formServer']) ? ' selected="selected"' : '',
- ">", htmlspecialchars($conf['servers'][$i]['desc']), "</option>\n";
- }
- ?>
- </select></td>
- </tr>
- <tr>
- <th><?php echo $lang['strlanguage'] ?>:</th>
- <td><select name="formLanguage">
- <?php
- // Language name already encoded
- foreach ($appLangFiles as $k => $v) {
- echo "<option value=\"{$k}\"",
- ($k == $_POST['formLanguage']) ? ' selected="selected"' : '',
- ">{$v}</option>\n";
- }
- ?>
- </select></td>
- </tr>
- </table>
- <p><input type="submit" name="submitLogin" value="<?php echo $lang['strlogin'] ?>" /></p>
- </form>
- </center>
- <script type="text/javascript">
- <!--
- var uname = document.login_form.formUsername;
- var pword = document.login_form.formPassword;
- if (uname.value == "") {
- uname.focus();
- } else {
- pword.focus();
- }
- //-->
- </script>
- </td>
- </tr>
- </table>
<?php
// Output footer
$misc->printFooter();
diff --git a/opclasses.php b/opclasses.php
index 99243582..5db50573 100644
--- a/opclasses.php
+++ b/opclasses.php
@@ -3,7 +3,7 @@
/**
* Manage opclasss in a database
*
- * $Id: opclasses.php,v 1.6 2004/09/01 16:35:59 jollytoad Exp $
+ * $Id: opclasses.php,v 1.7 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -53,7 +53,30 @@
$misc->printTable($opclasses, $columns, $actions, $lang['strnoopclasses']);
}
-
+
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $opclasses = &$data->getOpClasses();
+
+ // OpClass prototype: "op_class/access_method"
+ $proto = concat(field('opcname'),'/',field('amname'));
+
+ $attrs = array(
+ 'text' => $proto,
+ 'icon' => 'operators',
+ 'toolTip'=> field('opccomment'),
+ );
+
+ $misc->printTreeXML($opclasses, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['stropclasses']);
$misc->printBody();
diff --git a/operators.php b/operators.php
index 75300e26..5130a815 100644
--- a/operators.php
+++ b/operators.php
@@ -3,7 +3,7 @@
/**
* Manage operators in a database
*
- * $Id: operators.php,v 1.17 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: operators.php,v 1.18 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -156,6 +156,42 @@
// echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$misc->href}\">{$lang['strcreateoperator']}</a></p>\n";
}
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data, $PHP_SELF;
+
+ $operators = &$data->getOperators();
+
+ // Operator prototype: "type operator type"
+ $proto = concat(field('oprleftname'), ' ', field('oprname'), ' ', field('oprrightname'));
+
+ // Alternative prototype: "operator (type,type)"
+ #$proto = concat(field('oprname'), ' (', field('oprleftname','NONE'), ',', field('oprrightname','NONE'), ')');
+
+ $reqvars = $misc->getRequestVars('operator');
+
+ $attrs = array(
+ 'text' => $proto,
+ 'icon' => 'operators',
+ 'toolTip'=> field('oprcomment'),
+ 'action' => url('operators.php',
+ $reqvars,
+ array(
+ 'action' => 'properties',
+ 'operator' => $proto,
+ 'operator_oid' => field('oid')
+ )
+ )
+ );
+
+ $misc->printTreeXML($operators, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['stroperators']);
$misc->printBody();
diff --git a/redirect.php b/redirect.php
index b864a315..2e07187f 100644
--- a/redirect.php
+++ b/redirect.php
@@ -1,7 +1,12 @@
<?php
+ $subject = isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'root';
+
+ if ($subject == 'root')
+ $_no_db_connection = true;
+
include_once('./libraries/lib.inc.php');
- $url = parse_url($misc->getLastTabURL($_REQUEST['section']));
+ $url = parse_url($misc->getLastTabURL($subject));
$_SERVER['PHP_SELF'] = $url['path'];
diff --git a/reports.php b/reports.php
index df78fe6c..05a24b3d 100644
--- a/reports.php
+++ b/reports.php
@@ -3,7 +3,7 @@
/**
* List reports in a database
*
- * $Id: reports.php,v 1.19 2004/09/02 13:53:56 jollytoad Exp $
+ * $Id: reports.php,v 1.20 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -37,6 +37,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table width=\"100%\">\n";
echo "<tr><th class=\"data left required\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\"><input name=\"report_name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
@@ -117,8 +118,8 @@
}
else echo "<p>{$lang['strinvalidparam']}</p>\n";
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF\">{$lang['strshowallreports']}</a> |\n";
- echo "<a class=\"navlink\" href=\"$PHP_SELF?action=edit&amp;report_id={$report->f['report_id']}\">{$lang['stredit']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?{$misc->href}\">{$lang['strshowallreports']}</a> |\n";
+ echo "<a class=\"navlink\" href=\"$PHP_SELF?action=edit&amp;{$misc->href}&amp;report_id={$report->f['report_id']}\">{$lang['stredit']}</a></p>\n";
}
/**
@@ -140,6 +141,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table width=\"100%\">\n";
echo "<tr><th class=\"data left required\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\"><input name=\"report_name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
@@ -210,6 +212,7 @@
echo "<p>", sprintf($lang['strconfdropreport'], $misc->printVal($report->f['report_name'])), "</p>\n";
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"report_id\" value=\"", htmlspecialchars($_REQUEST['report_id']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
@@ -234,7 +237,7 @@
global $PHP_SELF, $lang;
$misc->printTrail('server');
- $misc->printTitle($lang['strreports']);
+ $misc->printTabs('server','reports');
$misc->printMsg($msg);
$reports = &$reportsdb->getReports();
@@ -261,32 +264,34 @@
),
);
+ $return_url = urlencode("{$PHP_SELF}?{$misc->href}");
+
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => "{$PHP_SELF}?action=properties&amp;",
+ 'url' => "{$PHP_SELF}?action=properties&amp;{$misc->href}&amp;",
'vars' => array('report_id' => 'report_id'),
),
'run' => array(
'title' => $lang['strrun'],
- 'url' => "display.php?subject=report&amp;return_url={$PHP_SELF}&amp;return_desc=".urlencode($lang['strback'])."&amp;",
+ 'url' => "display.php?subject=report&amp;{$misc->href}&amp;return_url={$return_url}&amp;return_desc=".urlencode($lang['strback'])."&amp;",
'vars' => array('report' => 'report_name', 'database' => 'db_name', 'query' => 'report_sql'),
),
'edit' => array(
'title' => $lang['stredit'],
- 'url' => "{$PHP_SELF}?action=edit&amp;",
+ 'url' => "{$PHP_SELF}?action=edit&amp;{$misc->href}&amp;",
'vars' => array('report_id' => 'report_id'),
),
'drop' => array(
'title' => $lang['strdrop'],
- 'url' => "{$PHP_SELF}?action=confirm_drop&amp;",
+ 'url' => "{$PHP_SELF}?action=confirm_drop&amp;{$misc->href}&amp;",
'vars' => array('report_id' => 'report_id'),
),
);
$misc->printTable($reports, $columns, $actions, $lang['strnoreports']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create\">{$lang['strcreatereport']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$misc->href}\">{$lang['strcreatereport']}</a></p>\n";
}
$misc->printHeader($lang['strreports']);
@@ -296,7 +301,9 @@
include_once('./classes/Reports.php');
$reportsdb = new Reports($status);
if ($status != 0) {
- echo "<p>{$lang['strnoreportsdb']}</p>\n";
+ $misc->printTrail('server');
+ $misc->printTabs('server','reports');
+ $misc->printMsg($lang['strnoreportsdb']);
}
else {
switch ($action) {
diff --git a/sequences.php b/sequences.php
index ac4a8096..b5b27d1b 100644
--- a/sequences.php
+++ b/sequences.php
@@ -3,7 +3,7 @@
/**
* Manage sequences in a database
*
- * $Id: sequences.php,v 1.27 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: sequences.php,v 1.28 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -69,6 +69,33 @@
}
/**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $sequences = &$data->getSequences();
+
+ $reqvars = $misc->getRequestVars('sequence');
+
+ $attrs = array(
+ 'text' => field('seqname'),
+ 'icon' => 'sequences',
+ 'toolTip'=> field('seqcomment'),
+ 'action' => url('sequences.php',
+ $reqvars,
+ array (
+ 'action' => 'properties',
+ 'sequence' => field('seqname')
+ )
+ )
+ );
+
+ $misc->printTreeXML($sequences, $attrs);
+ exit;
+ }
+
+ /**
* Display the properties of a sequence
*/
function doProperties($msg = '') {
@@ -250,6 +277,8 @@
doProperties($lang['strsequenceresetbad']);
}
+ if ($action == 'tree') doTree();
+
// Print header
$misc->printHeader($lang['strsequences']);
$misc->printBody();
diff --git a/servers.php b/servers.php
new file mode 100644
index 00000000..ee1b65f8
--- /dev/null
+++ b/servers.php
@@ -0,0 +1,133 @@
+<?php
+
+ /**
+ * Manage servers
+ *
+ * $Id: servers.php,v 1.2 2005/05/02 15:47:24 chriskl Exp $
+ */
+
+ // Include application functions
+ $_no_db_connection = true;
+ include_once('./libraries/lib.inc.php');
+
+ $action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
+ if (!isset($msg)) $msg = '';
+ $PHP_SELF = $_SERVER['PHP_SELF'];
+
+ function doLogout() {
+ global $misc, $lang, $_reload_browser;
+
+ $server_info = $misc->getServerInfo($_REQUEST['logoutServer']);
+ $misc->setServerInfo(null,null,$_REQUEST['logoutServer']);
+ doDefault(sprintf($lang['strlogoutmsg'], $server_info['desc']));
+
+ $_reload_browser = true;
+ }
+
+ function doDefault($msg = '') {
+ global $conf, $misc;
+ global $PHP_SELF, $lang;
+
+ $misc->printTabs('root','servers');
+ $misc->printMsg($msg);
+
+ $servers =& $misc->getServers(true);
+
+ function svPre(&$rowdata, $actions) {
+ $actions['logout']['disable'] = empty($rowdata->f['username']);
+ return $actions;
+ }
+
+ $columns = array(
+ 'server' => array(
+ 'title' => $lang['strserver'],
+ 'field' => 'desc',
+ ),
+ 'host' => array(
+ 'title' => $lang['strhost'],
+ 'field' => 'host',
+ ),
+ 'port' => array(
+ 'title' => $lang['strport'],
+ 'field' => 'port',
+ ),
+ 'username' => array(
+ 'title' => $lang['strusername'],
+ 'field' => 'username',
+ ),
+ 'actions' => array(
+ 'title' => $lang['stractions'],
+ ),
+ );
+
+ $actions = array(
+ 'properties' => array(
+ 'title' => $lang['strproperties'],
+ 'url' => "redirect.php?subject=server&amp;",
+ 'vars' => array('server' => 'id'),
+ ),
+ 'logout' => array(
+ 'title' => $lang['strlogout'],
+ 'url' => "{$PHP_SELF}?action=logout&amp;",
+ 'vars' => array('logoutServer' => 'id'),
+ ),
+ );
+
+ $misc->printTable($servers, $columns, $actions, $lang['strnoobjects'], 'svPre');
+ }
+
+ function doTree() {
+ global $misc;
+
+ $servers =& $misc->getServers(true);
+
+ $reqvars = $misc->getRequestVars('server');
+
+ $attrs = array(
+ 'text' => field('desc'),
+
+ // Show different icons for logged in/out
+ 'icon' => ifempty(field('username'), 'serverOut', 'server'),
+
+ 'toolTip'=> field('id'),
+
+ 'action' => url('redirect.php',
+ $reqvars,
+ array('server' => field('id'))
+ ),
+
+ // Only create a branch url if the user has
+ // logged into the server.
+ 'branch' => ifempty(field('username'), false,
+ url('all_db.php',
+ $reqvars,
+ array(
+ 'action' => 'tree',
+ 'server' => field('id')
+ )
+ )
+ ),
+ );
+
+ $misc->printTreeXML($servers, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
+ $misc->printHeader($lang['strservers']);
+ $misc->printBody();
+ $misc->printTrail('root');
+
+ switch ($action) {
+ case 'logout':
+ doLogout();
+ break;
+ case 'tree':
+ default:
+ doDefault($msg);
+ break;
+ }
+
+ $misc->printFooter();
+?>
diff --git a/sqledit.php b/sqledit.php
index 1480b95e..4fce2925 100644
--- a/sqledit.php
+++ b/sqledit.php
@@ -3,7 +3,7 @@
/**
* Alternative SQL editing window
*
- * $Id: sqledit.php,v 1.25 2004/09/30 16:32:05 jollytoad Exp $
+ * $Id: sqledit.php,v 1.26 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -14,29 +14,51 @@
$PHP_SELF = $_SERVER['PHP_SELF'];
/**
- * Private function to display list of databases
+ * Private function to display server and list of databases
*/
- function _printDatabases() {
+ function _printConnection() {
global $data, $lang, $conf, $action, $misc;
-
+
+ // The javascript action on the select box reloads the
+ // popup whenever the server or database is changed.
+ // This ensures that the correct page encoding is used.
+ $onchange = "onchange=\"location.href='sqledit.php?action=" .
+ urlencode($action) . "&server=' + encodeURI(server.options[server.selectedIndex].value) + '&database=' + encodeURI(database.options[database.selectedIndex].value) + ";
+
+ // The exact URL to reload to is different between SQL and Find mode, however.
+ if ($action == 'find') {
+ $onchange .= "'&term=' + encodeURI(term.value) + '&filter=' + encodeURI(filter.value) + '&" . SID . "'\">\n";
+ } else {
+ $onchange .= "'&query=' + encodeURI(query.value) ";
+ if ($data->hasSchemas()) $onchange .= "+ '&search_path=' + encodeURI(search_path.value) ";
+ $onchange .= "+ (paginate.checked ? '&paginate=on' : '') + '&" . SID . "'\"";
+ }
+
+ echo "<table width=\"100%\"><tr><td>\n";
+ echo "<label>";
+ $misc->printHelp($lang['strserver'], 'pg.server');
+ echo ": <select name=\"server\" {$onchange}>\n";
+
+ $servers = $misc->getServers();
+ foreach($servers as $info) {
+ if (empty($info['username'])) continue;
+ echo "<option value=\"", htmlspecialchars($info['id']), "\"",
+ ((isset($_REQUEST['server']) && $info['id'] == $_REQUEST['server'])) ? ' selected="selected"' : '', ">",
+ htmlspecialchars("{$info['desc']} ({$info['id']})"), "</option>\n";
+ }
+ echo "</select>\n</td><td align=\"right\">\n";
+
// Get the list of all databases
$databases = &$data->getDatabases();
- if ($databases->recordCount() > 0) {
- // The javascript action on the select box reloads the popup whenever the database is changed.
- // This ensures that the correct page encoding is used. The exact URL to reload to is different
- // between SQL and Find mode, however.
- if ($action == 'sql') {
- echo "<p>";
- $misc->printHelp($lang['strdatabase'], 'pg.database');
- echo ": <select name=\"database\" onChange=\"location.href='sqledit.php?action=" .
- urlencode($action) . "&database=' + encodeURI(options[selectedIndex].value) + '&query=' + encodeURI(query.value) ";
- if ($data->hasSchemas()) echo "+ '&search_path=' + encodeURI(search_path.value) ";
- echo "+ (paginate.checked ? '&paginate=on' : '') + '&" . SID . "'\">\n";
- }
- else
- echo "<p>{$lang['strdatabase']}: <select name=\"database\" onChange=\"location.href='sqledit.php?action=" .
- urlencode($action) . "&database=' + encodeURI(options[selectedIndex].value) + '&term=' + encodeURI(term.value) + '&filter=' + encodeURI(filter.value) + '&" . SID . "'\">\n";
+ if ($databases->recordCount() > 0) {
+ // The javascript action on the select box reloads
+ // the popup whenever the database is changed.
+ // This ensures that the correct page encoding is used.
+
+ echo "<label>";
+ $misc->printHelp($lang['strdatabase'], 'pg.database');
+ echo ": <select name=\"database\" {$onchange}>\n";
while (!$databases->EOF) {
$dbname = $databases->f['datname'];
@@ -48,10 +70,13 @@
echo "</select></label>\n";
}
else {
+ $server_info = $misc->getServerInfo();
echo "<input type=\"hidden\" name=\"database\" value=\"",
- htmlspecialchars($conf['servers'][$_SESSION['webdbServerID']]['defaultdb']), "\" />\n";
- }
- }
+ htmlspecialchars($server_info['defaultdb']), "\" />\n";
+ }
+
+ echo "</td></tr></table>\n";
+ }
/**
* Searches for a named database object
@@ -59,14 +84,19 @@
function doFind() {
global $PHP_SELF, $data, $misc;
global $lang, $conf;
-
+
if (!isset($_GET['term'])) $_GET['term'] = '';
if (!isset($_GET['filter'])) $_GET['filter'] = '';
-
+
+ $misc->printHeader($lang['strfind']);
+
+ // Bring to the front always
+ echo "<body onload=\"window.focus();\">\n";
+
$misc->printTabs($misc->getNavTabs('popup'), 'find');
echo "<form action=\"database.php\" method=\"get\" target=\"detail\">\n<p>";
- _printDatabases();
+ _printConnection();
echo "</p><p><input name=\"term\" value=\"", htmlspecialchars($_GET['term']),
"\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />\n";
@@ -98,7 +128,6 @@
echo "</select>\n";
echo "<input type=\"submit\" value=\"{$lang['strfind']}\" />\n";
- echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"find\" /></p>\n";
echo "</form>\n";
@@ -112,49 +141,45 @@
function doDefault() {
global $PHP_SELF, $data, $misc;
global $lang, $conf;
-
+
if (!isset($_REQUEST['query'])) $_REQUEST['query'] = '';
-
+
+ $misc->printHeader($lang['strsql']);
+
+ // Bring to the front always
+ echo "<body onload=\"window.focus();\">\n";
+
$misc->printTabs($misc->getNavTabs('popup'), 'sql');
-
+
echo "<form action=\"sql.php\" method=\"post\" target=\"detail\">\n<p>";
-
- _printDatabases();
-
+ _printConnection();
+ echo "</p>\n";
if ($data->hasSchemas()) {
if (!isset($_REQUEST['search_path']))
$_REQUEST['search_path'] = implode(',',$data->getSearchPath());
- echo "\n<label>";
+ echo "<p><label>";
$misc->printHelp($lang['strsearchpath'], 'pg.schema.search_path');
- echo ": <input type=\"text\" name=\"search_path\" size=\"30\" value=\"",
- htmlspecialchars($_REQUEST['search_path']), "\" /></label>";
+ echo ": <input type=\"text\" name=\"search_path\" size=\"50\" value=\"",
+ htmlspecialchars($_REQUEST['search_path']), "\" /></label></p>\n";
}
- echo "</p>\n<textarea style=\"width: 100%;\" rows=\"10\" cols=\"50\" name=\"query\">",
+ echo "<textarea style=\"width: 100%;\" rows=\"10\" cols=\"50\" name=\"query\">",
htmlspecialchars($_REQUEST['query']), "</textarea>\n";
echo "<label><input type=\"checkbox\" name=\"paginate\"", (isset($_REQUEST['paginate']) ? ' checked="checked"' : ''), " />&nbsp;{$lang['strpaginate']}</label>\n";
-
+
echo "<p><input type=\"submit\" value=\"{$lang['strgo']}\" />\n";
if ($data->hasFullExplain()) {
echo "<input type=\"submit\" name=\"explain\" value=\"{$lang['strexplain']}\" />\n";
echo "<input type=\"submit\" name=\"explain_analyze\" value=\"{$lang['strexplainanalyze']}\" />\n";
}
echo "<input type=\"reset\" value=\"{$lang['strreset']}\" /></p>\n";
-
- echo $misc->form;
-
echo "</form>\n";
// Default focus
$misc->setFocus('forms[0].query');
}
- $misc->printHeader($lang['strsql']);
-
- // Bring to the front always
- echo "<body onLoad=\"window.focus();\">\n";
-
switch ($action) {
case 'find':
doFind();
@@ -165,6 +190,9 @@
break;
}
+ // Set the name of the window
+ $misc->setWindowName('sqledit');
+
$misc->printFooter();
?>
diff --git a/tables.php b/tables.php
index a04bedab..61bcbd5b 100644
--- a/tables.php
+++ b/tables.php
@@ -3,7 +3,7 @@
/**
* List tables in a database
*
- * $Id: tables.php,v 1.71 2005/03/18 19:51:56 xzilla Exp $
+ * $Id: tables.php,v 1.72 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -222,7 +222,7 @@
* Ask for select parameters and perform select
*/
function doSelectRows($confirm, $msg = '') {
- global $data, $misc;
+ global $data, $misc, $_no_output;
global $lang;
global $PHP_SELF;
@@ -311,7 +311,7 @@
}
if (sizeof($_POST['show']) == 0)
- doSelectRows(true, $lang['strselectneedscol']);
+ doSelectRows(true, $lang['strselectneedscol']);
else {
// Generate query SQL
$query = $data->getSelectSQL($_REQUEST['table'], array_keys($_POST['show']),
@@ -320,6 +320,7 @@
$_REQUEST['return_url'] = "tables.php?action=confselectrows&{$misc->href}&table={$_REQUEST['table']}";
$_REQUEST['return_desc'] = $lang['strback'];
+ $_no_output = true;
include('./display.php');
exit;
}
@@ -578,7 +579,7 @@
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => "redirect.php?section=table&amp;{$misc->href}&amp;",
+ 'url' => "redirect.php?subject=table&amp;{$misc->href}&amp;",
'vars' => array('table' => 'relname'),
),
'browse' => array(
@@ -620,6 +621,32 @@
echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$misc->href}\">{$lang['strcreatetable']}</a></p>\n";
}
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $tables = &$data->getTables();
+
+ $reqvars = $misc->getRequestVars('table');
+
+ $attrs = array(
+ 'text' => field('relname'),
+ 'icon' => 'tables',
+ 'toolTip'=> field('relcomment'),
+ 'action' => url('redirect.php',
+ $reqvars,
+ array('table' => field('relname'))
+ )
+ );
+
+ $misc->printTreeXML($tables, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strtables']);
$misc->printBody();
diff --git a/tablespaces.php b/tablespaces.php
index c31c3fbd..3c96590d 100755
--- a/tablespaces.php
+++ b/tablespaces.php
@@ -3,7 +3,7 @@
/**
* Manage tablespaces in a database cluster
*
- * $Id: tablespaces.php,v 1.6 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: tablespaces.php,v 1.7 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -35,6 +35,7 @@
if (!isset($_POST['owner'])) $_POST['owner'] = $tablespace->f['spcowner'];
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "<tr><th class=\"data left required\">{$lang['strname']}</th>\n";
echo "<td class=\"data1\">";
@@ -52,7 +53,6 @@
echo "</table>\n";
echo "<p><input type=\"hidden\" name=\"action\" value=\"save_edit\" />\n";
echo "<input type=\"hidden\" name=\"tablespace\" value=\"", htmlspecialchars($_REQUEST['tablespace']), "\" />\n";
- echo $misc->form;
echo "<input type=\"submit\" name=\"alter\" value=\"{$lang['stralter']}\" />\n";
echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
echo "</form>\n";
@@ -98,6 +98,7 @@
echo "<p>", sprintf($lang['strconfdroptablespace'], $misc->printVal($_REQUEST['tablespace'])), "</p>\n";
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"tablespace\" value=\"", htmlspecialchars($_REQUEST['tablespace']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
@@ -120,8 +121,10 @@
global $data, $misc, $spcname;
global $PHP_SELF, $lang;
+ $server_info = $misc->getServerInfo();
+
if (!isset($_POST['formSpcname'])) $_POST['formSpcname'] = '';
- if (!isset($_POST['formOwner'])) $_POST['formOwner'] = $_SESSION['webdbUsername'];
+ if (!isset($_POST['formOwner'])) $_POST['formOwner'] = $server_info['username'];
if (!isset($_POST['formLoc'])) $_POST['formLoc'] = '';
// Fetch all users
@@ -132,6 +135,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
echo "\t\t<td class=\"data1\"><input size=\"32\" name=\"formSpcname\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_POST['formSpcname']), "\" /></td>\n\t</tr>\n";
@@ -205,27 +209,29 @@
)
);
+ $href = $misc->getHREF('database');
+
$actions = array(
'alter' => array(
'title' => $lang['stralter'],
- 'url' => "{$PHP_SELF}?action=edit&amp;",
+ 'url' => "{$PHP_SELF}?action=edit&amp;{$href}&amp;",
'vars' => array('tablespace' => 'spcname')
),
'drop' => array(
'title' => $lang['strdrop'],
- 'url' => "{$PHP_SELF}?action=confirm_drop&amp;",
+ 'url' => "{$PHP_SELF}?action=confirm_drop&amp;{$href}&amp;",
'vars' => array('tablespace' => 'spcname')
),
'privileges' => array(
'title' => $lang['strprivileges'],
- 'url' => "privileges.php?subject=tablespace&amp;",
+ 'url' => "privileges.php?subject=tablespace&amp;{$href}&amp;",
'vars' => array('tablespace' => 'spcname')
)
);
$misc->printTable($tablespaces, $columns, $actions, $lang['strnotablespaces']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create\">{$lang['strcreatetablespace']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$href}\">{$lang['strcreatetablespace']}</a></p>\n";
}
diff --git a/tblproperties.php b/tblproperties.php
index a11982dd..29fbda33 100644
--- a/tblproperties.php
+++ b/tblproperties.php
@@ -3,7 +3,7 @@
/**
* List tables in a database
*
- * $Id: tblproperties.php,v 1.62 2004/11/02 03:33:35 chriskl Exp $
+ * $Id: tblproperties.php,v 1.63 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -70,7 +70,9 @@
echo "<td class=\"data1\">";
echo "<input name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
htmlspecialchars($_POST['name']), "\" /></td></tr>\n";
- if ($data->hasAlterTableOwner() && $data->isSuperUser($_SESSION['webdbUsername'])) {
+
+ $server_info = $misc->getServerInfo();
+ if ($data->hasAlterTableOwner() && $data->isSuperUser($server_info['username'])) {
echo "<tr><th class=\"data left required\">{$lang['strowner']}</th>\n";
echo "<td class=\"data1\"><select name=\"owner\">";
while (!$users->EOF) {
@@ -166,6 +168,7 @@
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
echo $misc->form;
+ echo "<input type=\"hidden\" name=\"subject\" value=\"table\" />\n";
echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
@@ -585,14 +588,14 @@
echo "<ul>\n";
$return_url = urlencode("tblproperties.php?{$misc->href}&table={$_REQUEST['table']}");
- echo "\t<li><a href=\"display.php?{$misc->href}&table=", urlencode($_REQUEST['table']), "&subject=table&return_url={$return_url}&return_desc=",
+ echo "\t<li><a href=\"display.php?{$misc->href}&amp;table=", urlencode($_REQUEST['table']), "&subject=table&amp;return_url={$return_url}&amp;return_desc=",
urlencode($lang['strback']), "\">{$lang['strbrowse']}</a></li>\n";
- echo "\t<li><a href=\"tables.php?action=confselectrows&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['strselect']}</a></li>\n";
- echo "\t<li><a href=\"tables.php?action=confinsertrow&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['strinsert']}</a></li>\n";
- echo "\t<li><a href=\"tables.php?action=confirm_empty&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['strempty']}</a></li>\n";
- echo "\t<li><a href=\"tables.php?action=confirm_drop&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['strdrop']}</a></li>\n";
- echo "\t<li><a href=\"{$PHP_SELF}?action=add_column&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['straddcolumn']}</a></li>\n";
- echo "\t<li><a href=\"{$PHP_SELF}?action=confirm_alter&{$misc->href}&table=", urlencode($_REQUEST['table']),"\">{$lang['stralter']}</a></li>\n";
+ echo "\t<li><a href=\"tables.php?action=confselectrows&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['strselect']}</a></li>\n";
+ echo "\t<li><a href=\"tables.php?action=confinsertrow&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['strinsert']}</a></li>\n";
+ echo "\t<li><a href=\"tables.php?action=confirm_empty&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['strempty']}</a></li>\n";
+ echo "\t<li><a href=\"tables.php?action=confirm_drop&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['strdrop']}</a></li>\n";
+ echo "\t<li><a href=\"{$PHP_SELF}?action=add_column&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['straddcolumn']}</a></li>\n";
+ echo "\t<li><a href=\"{$PHP_SELF}?action=confirm_alter&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']),"\">{$lang['stralter']}</a></li>\n";
echo "</ul>\n";
}
diff --git a/themes/default/global.css b/themes/default/global.css
index 1e0dbb63..495f9d26 100644
--- a/themes/default/global.css
+++ b/themes/default/global.css
@@ -1,7 +1,7 @@
/**
* Default style sheet
*
- * $Id: global.css,v 1.31 2004/11/02 11:46:53 soranzo Exp $
+ * $Id: global.css,v 1.32 2005/05/02 15:47:28 chriskl Exp $
*/
/** ELEMENTS */
@@ -15,14 +15,18 @@ body, td
font-size: smaller; /*0.8em;*/
}
-body.topbar
+img { border: none; }
+
+div.logo
{
background-color: #CECF9C;
margin: 0px;
padding: 0px;
font-family: arial, tahoma, verdana, helvetica, sans-serif, serif;
font-size: smaller; /* 1em; */
+ border: none;
border-bottom: 2px solid #000000;
+ margin-bottom: 2px;
}
body.browser
@@ -194,7 +198,7 @@ td.opbutton2
padding: 2px 1em;
}
-.trail
+.trail, .topbar
{
margin-bottom: 2px;
}
@@ -221,6 +225,19 @@ td.opbutton2
background-color: #E6E6CC;
}
+.topbar {
+ border: 2px solid #CECF9C;
+ padding: 2px 1em;
+}
+
+.topbar, .topbar td {
+ background-color: #CECF9C;
+}
+
+.topbar .platform, .topbar .host, .topbar .username {
+ font-weight: bold;
+}
+
a:active
{
color: #989973;
@@ -306,8 +323,42 @@ pre.data
font-size: 100%;
}
+.intro li
+{
+ font-weight: bold;
+}
+
/* Syntax highlighting */
.comment {color: #008080}
.keyword {color: #FF8000}
.literal {color: #808080}
+/* Browser Tree using XLoadTree 2 */
+.webfx-tree-row {
+ white-space: nowrap;
+ font: arial, tahoma, verdana, helvetica, sans-serif, serif;
+}
+
+.webfx-tree-children {
+ background-repeat: repeat-y;
+ background-position-y: 1px !important; /* IE only */
+}
+
+.webfx-tree-row img {
+ vertical-align: middle;
+ height: 20px;
+}
+
+.webfx-tree-icon {
+ width: 20px;
+ cursor: hand;
+ cursor: pointer;
+}
+
+.webfx-tree-expand-icon {
+ width: 20px;
+}
+
+.webfx-tree-hide-root {
+ display: none;
+}
diff --git a/topbar.php b/topbar.php
deleted file mode 100755
index c9a9d06d..00000000
--- a/topbar.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-
- /**
- * Top menu for phpPgAdmin
- *
- * $Id: topbar.php,v 1.25 2004/07/12 04:18:40 chriskl Exp $
- */
-
- // Include application functions
- include_once('./libraries/lib.inc.php');
-
- // To prevent SQL popup windows from conflicting
- $window_id = 'sqledit_' . urlencode($conf['servers'][$_SESSION['webdbServerID']]['host'] .'_' . $conf['servers'][$_SESSION['webdbServerID']]['port']);
-
- $misc->printHeader();
- $misc->printBody('topbar');
- $dbselected = isset($_REQUEST['database']) ? '&database=' . $_REQUEST['database'] : '';
-?>
-<table width="100%" border="0" cellspacing="0" cellpadding="0" class="topbar" dir="ltr">
- <tr>
- <td width="211" rowspan="2"><a href="intro.php" target="detail"><img style="border: none" src="images/themes/<?php echo $conf['theme'] ?>/title.png" width="211" height="50" alt="<?php echo htmlspecialchars($appName) ?>" title="<?php echo htmlspecialchars($appName) ?>" /></a></td>
- <td class="topbar" width="5" rowspan="2">&nbsp;</td>
- <td class="topbar">
- <?php echo sprintf($lang['strtopbar'], htmlspecialchars($conf['description']),
- htmlspecialchars($conf['servers'][$_SESSION['webdbServerID']]['host']),
- htmlspecialchars($conf['servers'][$_SESSION['webdbServerID']]['port']),
- htmlspecialchars($_SESSION['webdbUsername']),
- date($lang['strtimefmt'])) ?></td>
- </tr>
- <tr>
- <td class="topbar">
-<?php
- // For superuser, show user and group admin. For normal user, show change password.
- if ($data->isSuperUser($_SESSION['webdbUsername'])) :
-?>
- <a class="toplink" href="users.php" target="detail"><?php echo $lang['strusers'] ?></a> |
- <a class="toplink" href="groups.php" target="detail"><?php echo $lang['strgroups'] ?></a> |
-<?php
- endif;
-?>
- <a class="toplink" href="users.php?action=account" target="detail"><?php echo $lang['straccount'] ?></a> |
-<?php if ($data->hasTablespaces()) : ?>
- <a class="toplink" href="tablespaces.php" target="detail"><?php echo $lang['strtablespaces'] ?></a> |
-<?php endif; ?>
-<?php if ($conf['show_reports']) : ?>
- <a class="toplink" href="reports.php" target="detail"><?php echo $lang['strreports'] ?></a> |
-<?php endif; ?>
- <a class="toplink" href="sqledit.php" target="sqledit" onclick="window.open('sqledit.php?action=sql<?php echo $dbselected ?>&<?php echo SID ?>','<?php echo htmlspecialchars($window_id) ?>','toolbar=no,width=600,height=400,resizable=yes,scrollbars=no').focus(); return false;"><?php echo $lang['strsql'] ?></a> |
- <a class="toplink" href="sqledit.php" target="sqledit" onclick="window.open('sqledit.php?action=find<?php echo $dbselected ?>&<?php echo SID ?>','<?php echo htmlspecialchars($window_id) ?>','toolbar=no,width=600,height=400,resizable=yes,scrollbars=no').focus(); return false;"><?php echo $lang['strfind'] ?></a> |
- <a class="toplink" href="logout.php" target="_parent"><?php echo $lang['strlogout'] ?></a>
- </td>
- </tr>
-</table>
-<?php
- $misc->printFooter();
-?>
diff --git a/triggers.php b/triggers.php
index c88e9775..4194178a 100644
--- a/triggers.php
+++ b/triggers.php
@@ -3,7 +3,7 @@
/**
* List triggers on a table
*
- * $Id: triggers.php,v 1.25 2005/04/14 18:20:10 xzilla Exp $
+ * $Id: triggers.php,v 1.26 2005/05/02 15:47:24 chriskl Exp $
*/
// Include application functions
@@ -245,7 +245,7 @@
$misc->printTable($triggers, $columns, $actions, $lang['strnotriggers'], 'tgPre');
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&{$misc->href}&table=", urlencode($_REQUEST['table']), "\">{$lang['strcreatetrigger']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$misc->href}&amp;table=", urlencode($_REQUEST['table']), "\">{$lang['strcreatetrigger']}</a></p>\n";
}
$misc->printHeader($lang['strtables'] . ' - ' . $_REQUEST['table'] . ' - ' . $lang['strtriggers']);
diff --git a/types.php b/types.php
index eb1bb667..38466c2d 100644
--- a/types.php
+++ b/types.php
@@ -3,7 +3,7 @@
/**
* Manage types in a database
*
- * $Id: types.php,v 1.25 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: types.php,v 1.26 2005/05/02 15:47:25 chriskl Exp $
*/
// Include application functions
@@ -27,14 +27,14 @@
$misc->printTitle($lang['strproperties'], 'pg.type');
$misc->printMsg($msg);
+ function attPre(&$rowdata) {
+ global $data;
+ $rowdata->f['+type'] = $data->formatType($rowdata->f['type'], $rowdata->f['atttypmod']);
+ }
+
if ($typedata->recordCount() > 0) {
switch ($typedata->f['typtype']) {
case 'c':
- function attPre(&$rowdata) {
- global $data;
- $rowdata->f['+type'] = $data->formatType($rowdata->f['type'], $rowdata->f['atttypmod']);
- }
-
$attrs = &$data->getTableAttributes($_REQUEST['type']);
$columns = array(
@@ -76,8 +76,8 @@
echo "</table>\n";
}
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?{$misc->href}\">{$lang['strshowalltypes']}</a></p>\n"; }
- else
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?{$misc->href}\">{$lang['strshowalltypes']}</a></p>\n";
+ } else
doDefault($lang['strinvalidparam']);
}
@@ -457,7 +457,36 @@
echo "</p>\n";
}
-
+
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $types = &$data->getTypes();
+
+ $reqvars = $misc->getRequestVars('type');
+
+ $attrs = array(
+ 'text' => field('basename'),
+ 'icon' => 'types',
+ 'toolTip'=> field('typcomment'),
+ 'action' => url('types.php',
+ $reqvars,
+ array(
+ 'action' => 'properties',
+ 'type' => field('basename')
+ )
+ )
+ );
+
+ $misc->printTreeXML($types, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strtypes']);
$misc->printBody();
diff --git a/users.php b/users.php
index dea93ce5..ef8fba9b 100644
--- a/users.php
+++ b/users.php
@@ -3,7 +3,7 @@
/**
* Manage users in a database cluster
*
- * $Id: users.php,v 1.29 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: users.php,v 1.30 2005/05/02 15:47:25 chriskl Exp $
*/
// Include application functions
@@ -23,11 +23,13 @@
global $data, $misc;
global $PHP_SELF, $lang;
- $userdata = &$data->getUser($_SESSION['webdbUsername']);
- $_REQUEST['user'] = $_SESSION['webdbUsername'];
+ $server_info = $misc->getServerInfo();
+
+ $userdata = &$data->getUser($server_info['username']);
+ $_REQUEST['user'] = $server_info['username'];
$misc->printTrail('user');
- $misc->printTitle($lang['straccount'],'pg.user');
+ $misc->printTabs('server','account');
$misc->printMsg($msg);
if ($userdata->recordCount() > 0) {
@@ -46,7 +48,7 @@
}
else echo "<p>{$lang['strnodata']}</p>\n";
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=confchangepassword\">{$lang['strchangepassword']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=confchangepassword&amp;{$misc->href}\">{$lang['strchangepassword']}</a></p>\n";
}
/**
@@ -55,9 +57,11 @@
function doChangePassword($confirm, $msg = '') {
global $data, $misc;
global $PHP_SELF, $lang, $conf;
-
+
+ $server_info = $misc->getServerInfo();
+
if ($confirm) {
- $_REQUEST['user'] = $_SESSION['webdbUsername'];
+ $_REQUEST['user'] = $server_info['username'];
$misc->printTrail('user');
$misc->printTitle($lang['strchangepassword'],'pg.user.alter');
$misc->printMsg($msg);
@@ -66,6 +70,7 @@
if (!isset($_POST['confirm'])) $_POST['confirm'] = '';
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strpassword']}</th>\n";
echo "\t\t<td><input type=\"password\" name=\"password\" size=\"32\" value=\"",
@@ -86,7 +91,7 @@
elseif ($_POST['password'] != $_POST['confirm'])
doChangePassword(true, $lang['strpasswordconfirm']);
else {
- $status = $data->changePassword($_SESSION['webdbUsername'],
+ $status = $data->changePassword($server_info['username'],
$_POST['password']);
if ($status == 0)
doAccount($lang['strpasswordchanged']);
@@ -110,7 +115,8 @@
$userdata = &$data->getUser($_REQUEST['username']);
if ($userdata->recordCount() > 0) {
- $canRename = $data->hasUserRename() && ($_REQUEST['username'] != $_SESSION['webdbUsername']);
+ $server_info = $misc->getServerInfo();
+ $canRename = $data->hasUserRename() && ($_REQUEST['username'] != $server_info['username']);
$userdata->f['usesuper'] = $data->phpBool($userdata->f['usesuper']);
$userdata->f['usecreatedb'] = $data->phpBool($userdata->f['usecreatedb']);
@@ -123,6 +129,7 @@
}
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strusername']}</th>\n";
echo "\t\t<td class=\"data1\">", ($canRename ? "<input name=\"newname\" size=\"15\" value=\"" . htmlspecialchars($_POST['newname']) . "\" />" : $misc->printVal($userdata->f['usename'])), "</td>\n\t</tr>\n";
@@ -183,6 +190,7 @@
echo "<p>", sprintf($lang['strconfdropuser'], $misc->printVal($_REQUEST['username'])), "</p>\n";
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
echo "<input type=\"hidden\" name=\"username\" value=\"", htmlspecialchars($_REQUEST['username']), "\" />\n";
echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
@@ -215,6 +223,7 @@
$misc->printMsg($msg);
echo "<form action=\"$PHP_SELF\" method=\"post\">\n";
+ echo $misc->form;
echo "<table>\n";
echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strusername']}</th>\n";
echo "\t\t<td class=\"data1\"><input size=\"15\" name=\"formUsername\" value=\"", htmlspecialchars($_POST['formUsername']), "\" /></td>\n\t</tr>\n";
@@ -323,7 +332,7 @@
$misc->printTable($users, $columns, $actions, $lang['strnousers']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create\">{$lang['strcreateuser']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"{$PHP_SELF}?action=create&amp;{$misc->href}\">{$lang['strcreateuser']}</a></p>\n";
}
diff --git a/viewproperties.php b/viewproperties.php
index cb52ba94..9d0ccab7 100755
--- a/viewproperties.php
+++ b/viewproperties.php
@@ -3,7 +3,7 @@
/**
* List views in a database
*
- * $Id: viewproperties.php,v 1.13 2004/09/07 13:58:21 jollytoad Exp $
+ * $Id: viewproperties.php,v 1.14 2005/05/02 15:47:25 chriskl Exp $
*/
// Include application functions
@@ -119,7 +119,8 @@
echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
echo $misc->form;
- echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['view']), "\" />\n";
+ echo "<input type=\"hidden\" name=\"subject\" value=\"view\" />\n";
+ echo "<input type=\"hidden\" name=\"view\" value=\"", htmlspecialchars($_REQUEST['view']), "\" />\n";
echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
echo "</form>\n";
}
@@ -302,11 +303,11 @@
echo "<br />\n";
echo "<ul>\n";
- $return_url = urlencode("viewproperties.php?{$misc->href}&view=" . urlencode($_REQUEST['view']));
- echo "\t<li><a href=\"display.php?{$misc->href}&view=", urlencode($_REQUEST['view']), "&subject=view&return_url={$return_url}&return_desc=",
+ $return_url = urlencode("viewproperties.php?{$misc->href}&amp;view=" . urlencode($_REQUEST['view']));
+ echo "\t<li><a href=\"display.php?{$misc->href}&amp;view=", urlencode($_REQUEST['view']), "&amp;subject=view&amp;return_url={$return_url}&amp;return_desc=",
urlencode($lang['strback']), "\">{$lang['strbrowse']}</a></li>\n";
- echo "\t<li><a href=\"views.php?action=confselectrows&{$misc->href}&view=", urlencode($_REQUEST['view']),"\">{$lang['strselect']}</a></li>\n";
- echo "\t<li><a href=\"views.php?action=confirm_drop&{$misc->href}&view=", urlencode($_REQUEST['view']),"\">{$lang['strdrop']}</a></li>\n";
+ echo "\t<li><a href=\"views.php?action=confselectrows&amp;{$misc->href}&amp;view=", urlencode($_REQUEST['view']),"\">{$lang['strselect']}</a></li>\n";
+ echo "\t<li><a href=\"views.php?action=confirm_drop&amp;{$misc->href}&amp;view=", urlencode($_REQUEST['view']),"\">{$lang['strdrop']}</a></li>\n";
echo "</ul>\n";
}
diff --git a/views.php b/views.php
index dd8022d8..dde9d89c 100644
--- a/views.php
+++ b/views.php
@@ -3,7 +3,7 @@
/**
* Manage views in a database
*
- * $Id: views.php,v 1.52 2005/01/23 12:42:35 soranzo Exp $
+ * $Id: views.php,v 1.53 2005/05/02 15:47:25 chriskl Exp $
*/
// Include application functions
@@ -548,7 +548,7 @@
$actions = array(
'properties' => array(
'title' => $lang['strproperties'],
- 'url' => "redirect.php?section=view&amp;{$misc->href}&amp;",
+ 'url' => "redirect.php?subject=view&amp;{$misc->href}&amp;",
'vars' => array('view' => 'relname'),
),
'browse' => array(
@@ -578,11 +578,37 @@
$misc->printTable($views, $columns, $actions, $lang['strnoviews']);
- echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&{$misc->href}\">{$lang['strcreateview']}</a> |\n";
- echo "<a class=\"navlink\" href=\"$PHP_SELF?action=wiz_create&{$misc->href}\">{$lang['strcreateviewwiz']}</a></p>\n";
+ echo "<p><a class=\"navlink\" href=\"$PHP_SELF?action=create&amp;{$misc->href}\">{$lang['strcreateview']}</a> |\n";
+ echo "<a class=\"navlink\" href=\"$PHP_SELF?action=wiz_create&amp;{$misc->href}\">{$lang['strcreateviewwiz']}</a></p>\n";
}
-
+
+ /**
+ * Generate XML for the browser tree.
+ */
+ function doTree() {
+ global $misc, $data;
+
+ $views = &$data->getViews();
+
+ $reqvars = $misc->getRequestVars('view');
+
+ $attrs = array(
+ 'text' => field('relname'),
+ 'icon' => 'views',
+ 'toolTip'=> field('relcomment'),
+ 'action' => url('redirect.php',
+ $reqvars,
+ array('view' => field('relname'))
+ )
+ );
+
+ $misc->printTreeXML($views, $attrs);
+ exit;
+ }
+
+ if ($action == 'tree') doTree();
+
$misc->printHeader($lang['strviews']);
$misc->printBody();
diff --git a/xloadtree/xloadtree2.js b/xloadtree/xloadtree2.js
new file mode 100644
index 00000000..23461327
--- /dev/null
+++ b/xloadtree/xloadtree2.js
@@ -0,0 +1,534 @@
+/*----------------------------------------------------------------------------\
+| XLoadTree 2 PRE RELEASE |
+| |
+| This is a pre release and redistribution is discouraged. |
+| Watch http://webfx.eae.net for the final version |
+| |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson & Emil A Eklund |
+| (http://webfx.eae.net/contact.html#erik) |
+| (http://webfx.eae.net/contact.html#emil) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| A tree menu system for IE 5.5+, Mozilla 1.4+, Opera 7.5+ |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2004 Erik Arvidsson & Emil A Eklund |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2004-02-21 | Pre release distributed to a few selected tester |
+|-----------------------------------------------------------------------------|
+| Dependencies: xtree2.js Supplies the tree control |
+|-----------------------------------------------------------------------------|
+| Created 2003-??-?? | All changes are in the log above. | Updated 2004-02-21 |
+\----------------------------------------------------------------------------*/
+
+
+webFXTreeConfig.loadingText = "Loading...";
+webFXTreeConfig.loadingIcon = "images/loading.gif";
+webFXTreeConfig.errorIcon = "images/exclamation.16.gif";
+webFXTreeConfig.errorLoadingText = "Error Loading";
+webFXTreeConfig.reloadText = "Click to reload";
+
+
+function WebFXLoadTree(sText, sXmlSrc, oAction, sBehavior, sIcon, sOpenIcon)
+{
+ WebFXTree.call(this, sText, oAction, sBehavior, sIcon, sOpenIcon);
+
+ // setup default property values
+ this.src = sXmlSrc;
+ this.loading = !sXmlSrc;
+ this.loaded = !sXmlSrc;
+ this.errorText = "";
+
+ if (this.src)
+ {
+ /// add loading Item
+ this._loadingItem = WebFXLoadTree.createLoadingItem();
+ this.add(this._loadingItem);
+
+ if (this.getExpanded())
+ WebFXLoadTree.loadXmlDocument(this);
+ }
+}
+
+WebFXLoadTree.createLoadingItem = function ()
+{
+ return new WebFXTreeItem(webFXTreeConfig.loadingText, null, null,
+ webFXTreeConfig.loadingIcon);
+};
+
+WebFXLoadTree.prototype = new WebFXTree;
+
+WebFXLoadTree.prototype.setExpanded = function (b)
+{
+ WebFXTree.prototype.setExpanded.call(this, b);
+
+ if (this.src && b)
+ {
+ if (!this.loaded && !this.loading)
+ {
+ // load
+ WebFXLoadTree.loadXmlDocument(this);
+ }
+ }
+};
+
+function WebFXLoadTreeItem(sText, sXmlSrc, oAction, eParent, sIcon, sOpenIcon)
+{
+ WebFXTreeItem.call(this, sText, oAction, eParent, sIcon, sOpenIcon);
+
+// setup default property values
+ this.src = sXmlSrc;
+ this.loading = !sXmlSrc;
+ this.loaded = !sXmlSrc;
+ this.errorText = "";
+
+ if (this.src)
+ {
+ /// add loading Item
+ this._loadingItem = WebFXLoadTree.createLoadingItem();
+ this.add(this._loadingItem);
+
+ if (this.getExpanded())
+ WebFXLoadTree.loadXmlDocument(this);
+ }
+}
+
+WebFXLoadTreeItem.prototype = new WebFXTreeItem;
+
+WebFXLoadTreeItem.prototype.setExpanded = function (b)
+{
+ WebFXTreeItem.prototype.setExpanded.call(this, b);
+
+ if (this.src && b)
+ {
+ if (!this.loaded && !this.loading)
+ {
+ // load
+ WebFXLoadTree.loadXmlDocument(this);
+ }
+ }
+};
+
+// reloads the src file if already loaded
+WebFXLoadTree.prototype.reload =
+WebFXLoadTreeItem.prototype.reload = function ()
+{
+ // if loading do nothing
+ if (this.loaded)
+ {
+ var t = this.getTree();
+ var expanded = this.getExpanded();
+ var sr = t.getSuspendRedraw();
+ t.setSuspendRedraw(true);
+
+ // remove
+ while (this.childNodes.length > 0)
+ this.remove(this.childNodes[this.childNodes.length - 1]);
+
+ this.loaded = false;
+
+ this._loadingItem = WebFXLoadTree.createLoadingItem();
+ this.add(this._loadingItem);
+
+ if (expanded)
+ this.setExpanded(true);
+
+ t.setSuspendRedraw(sr);
+ this.update();
+ }
+ else if (this.open && !this.loading)
+ WebFXLoadTree.loadXmlDocument(this);
+};
+
+
+
+WebFXLoadTree.prototype.setSrc =
+WebFXLoadTreeItem.prototype.setSrc = function (sSrc)
+{
+ var oldSrc = this.src;
+ if (sSrc == oldSrc) return;
+
+ var expanded = this.getExpanded();
+
+ // remove all
+ this._callSuspended(function ()
+ {
+ // remove
+ while (this.childNodes.length > 0)
+ this.remove(this.childNodes[this.childNodes.length - 1]);
+ });
+ this.update();
+
+ this.loaded = false;
+ this.loading = false;
+ if (this._loadingItem)
+ {
+ this._loadingItem.dispose();
+ this._loadingItem = null;
+ }
+ this.src = sSrc;
+
+ if (sSrc)
+ {
+ this._loadingItem = WebFXLoadTree.createLoadingItem();
+ this.add(this._loadingItem);
+ }
+
+ this.setExpanded(expanded);
+};
+
+WebFXLoadTree.prototype.getSrc =
+WebFXLoadTreeItem.prototype.getSrc = function ()
+{
+ return this.src;
+};
+
+WebFXLoadTree.prototype.dispose = function ()
+{
+ WebFXTree.prototype.dispose.call(this);
+ if (this._xmlHttp)
+ {
+ if (this._xmlHttp.dispose)
+ this._xmlHttp.dispose();
+ try
+ {
+ this._xmlHttp.onreadystatechange = null;
+ this._xmlHttp.abort();
+ }
+ catch (ex) {}
+ this._xmlHttp = null;
+ }
+};
+
+WebFXLoadTreeItem.prototype.dispose = function ()
+{
+ WebFXTreeItem.prototype.dispose.call(this);
+ if (this._xmlHttp)
+ {
+ if (this._xmlHttp.dispose)
+ this._xmlHttp.dispose();
+ try
+ {
+ this._xmlHttp.onreadystatechange = null;
+ this._xmlHttp.abort();
+ }
+ catch (ex) {}
+ this._xmlHttp = null;
+ }
+};
+
+
+// The path is divided by '/' and the item is identified by the text
+WebFXLoadTree.prototype.openPath =
+WebFXLoadTreeItem.prototype.openPath = function (sPath, bSelect, bFocus)
+{
+ // remove any old pending paths to open
+ delete this._pathToOpen;
+ //delete this._pathToOpenById;
+ this._selectPathOnLoad = bSelect;
+ this._focusPathOnLoad = bFocus;
+
+ if (sPath == "")
+ {
+ if (bSelect)
+ this.select();
+ if (bFocus)
+ window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.getId() + "\")", 10);
+ return;
+ }
+
+ var parts = sPath.split("/");
+ var remainingPath = parts.slice(1).join("/");
+
+ if (sPath.charAt(0) == "/")
+ {
+ this.getTree().openPath(remainingPath, bSelect, bFocus);
+ }
+ else
+ {
+ // open
+ this.setExpanded(true);
+ if (this.loaded)
+ {
+ parts = sPath.split("/");
+ var ti = this.findChildByText(parts[0]);
+ if (!ti)
+ throw "Could not find child node with text \"" + parts[0] + "\"";
+
+ ti.openPath(remainingPath, bSelect, bFocus);
+ }
+ else
+ {
+ this._pathToOpen = sPath;
+ }
+ }
+};
+
+
+// Opera has some serious attribute problems. We need to use getAttribute
+// for certain attributes
+WebFXLoadTree._attrs = ["text", "src", "action", "id", "target"];
+
+WebFXLoadTree.createItemFromElement = function (oNode)
+{
+ var jsAttrs = {};
+ var domAttrs = oNode.attributes;
+ var i, l;
+
+ l = domAttrs.length;
+ for (i = 0; i < l; i++)
+ {
+ if (domAttrs[i] == null)
+ {
+ continue;
+ }
+ jsAttrs[domAttrs[i].nodeName] = domAttrs[i].nodeValue;
+ }
+
+
+ var name, val;
+ for (i = 0; i < WebFXLoadTree._attrs.length; i++)
+ {
+ name = WebFXLoadTree._attrs[i];
+ value = oNode.getAttribute(name);
+ if (value)
+ jsAttrs[name] = value;
+ }
+
+ var action;
+ if (jsAttrs.onaction)
+ action = new Function(jsAttrs.onaction);
+ else if (jsAttrs.action)
+ action = jsAttrs.action;
+ var jsNode = new WebFXLoadTreeItem(jsAttrs.html || "", jsAttrs.src, action,
+ null, jsAttrs.icon, jsAttrs.openIcon);
+ if (jsAttrs.text)
+ jsNode.setText(jsAttrs.text);
+
+ if (jsAttrs.target)
+ jsNode.target = jsAttrs.target;
+ if (jsAttrs.id)
+ jsNode.setId(jsAttrs.id);
+ if (jsAttrs.toolTip)
+ jsNode.toolTip = jsAttrs.toolTip;
+ if (jsAttrs.expanded)
+ jsNode.setExpanded(jsAttrs.expanded != "false");
+ if (jsAttrs.onload)
+ jsNode.onload = new Function(jsAttrs.onload);
+ if (jsAttrs.onerror)
+ jsNode.onerror = new Function(jsAttrs.onerror);
+
+ jsNode.attributes = jsAttrs;
+
+ // go through childNodes
+ var cs = oNode.childNodes;
+ l = cs.length;
+ for (i = 0; i < l; i++)
+ {
+ if (cs[i].tagName == "tree")
+ jsNode.add(WebFXLoadTree.createItemFromElement(cs[i]));
+ }
+
+ return jsNode;
+};
+
+WebFXLoadTree.loadXmlDocument = function (jsNode)
+{
+ if (jsNode.loading || jsNode.loaded)
+ return;
+ jsNode.loading = true;
+ var id = jsNode.getId();
+ jsNode._xmlHttp = XmlHttp.create();
+ jsNode._xmlHttp.open("GET", jsNode.src, true); // async
+ jsNode._xmlHttp.onreadystatechange = new Function("WebFXLoadTree._onload(\"" + id + "\")");
+
+ // call in new thread to allow ui to update
+ window.setTimeout("WebFXLoadTree._ontimeout(\"" + id + "\")", 10);
+};
+
+WebFXLoadTree._onload = function (sId)
+{
+ var jsNode = webFXTreeHandler.all[sId];
+ if (jsNode._xmlHttp.readyState == 4)
+ {
+ WebFXLoadTree.documentLoaded(jsNode);
+ webFXLoadTreeQueue.remove(jsNode);
+ if (jsNode._xmlHttp.dispose)
+ jsNode._xmlHttp.dispose();
+ jsNode._xmlHttp = null;
+ }
+};
+
+WebFXLoadTree._ontimeout = function (sId)
+{
+ var jsNode = webFXTreeHandler.all[sId];
+ webFXLoadTreeQueue.add(jsNode);
+};
+
+
+
+// Inserts an xml document as a subtree to the provided node
+WebFXLoadTree.documentLoaded = function (jsNode)
+{
+ if (jsNode.loaded)
+ return;
+
+ jsNode.errorText = "";
+ jsNode.loaded = true;
+ jsNode.loading = false;
+
+ var t = jsNode.getTree();
+ var oldSuspend = t.getSuspendRedraw();
+ t.setSuspendRedraw(true);
+
+ var doc = jsNode._xmlHttp.responseXML;
+
+ // check that the load of the xml file went well
+ if(!doc || doc.parserError && doc.parseError.errorCode != 0 || !doc.documentElement)
+ {
+ if (!doc || doc.parseError.errorCode == 0)
+ {
+ jsNode.errorText = webFXTreeConfig.errorLoadingText + " " + jsNode.src + " (" + jsNode._xmlHttp.status + ": " + jsNode._xmlHttp.statusText + ")";
+ }
+ else
+ {
+ jsNode.errorText = webFXTreeConfig.errorLoadingText + " " + jsNode.src + " (" + doc.parseError.reason + ")";
+ }
+ }
+ else
+ {
+ // there is one extra level of tree elements
+ var root = doc.documentElement;
+
+ // loop through all tree children
+ var count = 0;
+ var cs = root.childNodes;
+ var l = cs.length;
+ for (var i = 0; i < l; i++)
+ {
+ if (cs[i].tagName == "tree")
+ {
+ jsNode.add(WebFXLoadTree.createItemFromElement(cs[i]));
+ count++;
+ }
+ }
+
+ // if no children we got an error
+ if (count == 0)
+ {
+ jsNode.errorText = webFXTreeConfig.errorLoadingText + " " + jsNode.src + " (???)";
+ }
+ }
+
+ if (jsNode.errorText != "")
+ {
+ jsNode._loadingItem.icon = webFXTreeConfig.errorIcon;
+ jsNode._loadingItem.text = jsNode.errorText;
+ jsNode._loadingItem.action = WebFXLoadTree._reloadParent;
+ jsNode._loadingItem.toolTip = webFXTreeConfig.reloadText;
+
+ t.setSuspendRedraw(oldSuspend);
+
+ jsNode._loadingItem.update();
+
+ if (typeof jsNode.onerror == "function")
+ jsNode.onerror();
+ }
+ else
+ {
+ // remove dummy
+ if (jsNode._loadingItem != null)
+ jsNode.remove(jsNode._loadingItem);
+
+ if (jsNode._pathToOpen)
+ jsNode.openPath(jsNode._pathToOpen, jsNode._selectPathOnLoad, jsNode._focusPathOnLoad);
+
+ t.setSuspendRedraw(oldSuspend);
+ jsNode.update();
+ if (typeof jsNode.onload == "function")
+ jsNode.onload();
+ }
+};
+
+WebFXLoadTree._reloadParent = function ()
+{
+ this.getParent().reload();
+};
+
+
+
+
+
+
+
+var webFXLoadTreeQueue = {
+ _nodes: [],
+ _ie: /msie/i.test(navigator.userAgent),
+ _opera: /opera/i.test(navigator.userAgent),
+
+ add: function (jsNode)
+ {
+ if (this._ie || this._opera)
+ {
+ this._nodes.push(jsNode);
+ if (this._nodes.length == 1)
+ this._send();
+ }
+ else
+ {
+ jsNode._xmlHttp.send(null);
+ }
+ },
+
+
+ remove: function (jsNode)
+ {
+ if (this._ie || this._opera)
+ {
+ arrayHelper.remove(this._nodes, jsNode);
+ if (this._nodes.length > 0)
+ this._send();
+ }
+ },
+
+ // IE only
+ _send: function ()
+ {
+ var id = this._nodes[0].getId();
+ var jsNode = webFXTreeHandler.all[id];
+ if (!jsNode)
+ return;
+ // if no _xmlHttp then remove it
+ if (!jsNode._xmlHttp)
+ this.remove(jsNode);
+ else
+ jsNode._xmlHttp.send(null);
+ }
+};
diff --git a/xloadtree/xmlextras.js b/xloadtree/xmlextras.js
new file mode 100644
index 00000000..6a675121
--- /dev/null
+++ b/xloadtree/xmlextras.js
@@ -0,0 +1,232 @@
+/*----------------------------------------------------------------------------\
+| XML Extras 1.01 |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson |
+| (http://webfx.eae.net/contact.html#erik) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| A library that makes working with XML documents in Mozilla more similar to |
+| working with MSXML. |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2003 Erik Arvidsson |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| ????-??-?? | Original Version Posted. |
+| 2003-09-25 | Added support for parseError getters. Also changed to extend |
+| | only XMLDocument instead of Document |
+|-----------------------------------------------------------------------------|
+| Created ????-??-?? | All changes are in the log above. | Updated 2003-09-25 |
+\----------------------------------------------------------------------------*/
+
+
+//////////////////
+// Helper Stuff //
+//////////////////
+
+// used to find the Automation server name
+function getDomDocumentPrefix() {
+ if (getDomDocumentPrefix.prefix)
+ return getDomDocumentPrefix.prefix;
+
+ var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+ var o;
+ for (var i = 0; i < prefixes.length; i++) {
+ try {
+ // try to create the objects
+ o = new ActiveXObject(prefixes[i] + ".DomDocument");
+ return getDomDocumentPrefix.prefix = prefixes[i];
+ }
+ catch (ex) {};
+ }
+
+ throw new Error("Could not find an installed XML parser");
+}
+
+function getXmlHttpPrefix() {
+ if (getXmlHttpPrefix.prefix)
+ return getXmlHttpPrefix.prefix;
+
+ var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+ var o;
+ for (var i = 0; i < prefixes.length; i++) {
+ try {
+ // try to create the objects
+ o = new ActiveXObject(prefixes[i] + ".XmlHttp");
+ return getXmlHttpPrefix.prefix = prefixes[i];
+ }
+ catch (ex) {};
+ }
+
+ throw new Error("Could not find an installed XML parser");
+}
+
+//////////////////////////
+// Start the Real stuff //
+//////////////////////////
+
+
+// XmlHttp factory
+function XmlHttp() {}
+
+XmlHttp.create = function () {
+ try {
+ if (window.XMLHttpRequest) {
+ var req = new XMLHttpRequest();
+
+ // some versions of Moz do not support the readyState property
+ // and the onreadystate event so we patch it!
+ if (req.readyState == null) {
+ req.readyState = 1;
+ req.addEventListener("load", function () {
+ req.readyState = 4;
+ if (typeof req.onreadystatechange == "function")
+ req.onreadystatechange();
+ }, false);
+ }
+
+ return req;
+ }
+ if (window.ActiveXObject) {
+ return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
+ }
+ }
+ catch (ex) {}
+ // fell through
+ throw new Error("Your browser does not support XmlHttp objects");
+};
+
+// XmlDocument factory
+function XmlDocument() {}
+
+XmlDocument.create = function () {
+ try {
+ // DOM2
+ if (document.implementation && document.implementation.createDocument) {
+ var doc = document.implementation.createDocument("", "", null);
+
+ // some versions of Moz do not support the readyState property
+ // and the onreadystate event so we patch it!
+ if (doc.readyState == null) {
+ doc.readyState = 1;
+ doc.addEventListener("load", function () {
+ doc.readyState = 4;
+ if (typeof doc.onreadystatechange == "function")
+ doc.onreadystatechange();
+ }, false);
+ }
+
+ return doc;
+ }
+ if (window.ActiveXObject)
+ return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
+ }
+ catch (ex) {}
+ throw new Error("Your browser does not support XmlDocument objects");
+};
+
+// Create the loadXML method and xml getter for Mozilla
+if (window.DOMParser &&
+ window.XMLSerializer &&
+ window.Node && Node.prototype && Node.prototype.__defineGetter__) {
+
+ // XMLDocument did not extend the Document interface in some versions
+ // of Mozilla. Extend both!
+ //XMLDocument.prototype.loadXML =
+ XMLDocument.prototype.loadXML = function (s) {
+
+ // parse the string to a new doc
+ var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+
+ // remove all initial children
+ while (this.hasChildNodes())
+ this.removeChild(this.lastChild);
+
+ // insert and import nodes
+ for (var i = 0; i < doc2.childNodes.length; i++) {
+ this.appendChild(this.importNode(doc2.childNodes[i], true));
+ }
+ };
+
+
+ /*
+ * xml getter
+ *
+ * This serializes the DOM tree to an XML String
+ *
+ * Usage: var sXml = oNode.xml
+ *
+ */
+
+ // Node, should really be XMLNode but there is no such interface
+ Node.prototype.__defineGetter__("xml", function () {
+ return (new XMLSerializer()).serializeToString(this);
+ });
+
+ XMLDocument.prototype.__defineGetter__("parseError", function () {
+ var hasError = !this.documentElement ||
+ this.documentElement.localName == "parsererror" &&
+ this.documentElement.getAttribute("xmlns") == "http://www.mozilla.org/newlayout/xml/parsererror.xml";
+ var res = {
+ errorCode: 0,
+ filepos: 0, // not supported
+ line: 0,
+ linepos: 0,
+ reason: "",
+ srcText: "",
+ url: ""
+ };
+ if (hasError) {
+ res.errorCode = -1;
+ try {
+ res.srcText = this.getElementsByTagName("sourcetext")[0].firstChild.data;
+ res.srcText = res.srcText.replace( /\n\-\^$/, "");
+ }
+ catch (ex) {
+ res.srcText = "";
+ }
+
+ try {
+ // now we need to parse the first text node
+ var s = this.documentElement.firstChild.data;
+
+ var re = /XML Parsing Error\: (.+)\nLocation\: (.+)\nLine Number (\d+)\, Column (\d+)/;
+ var a = re.exec( s );
+ res.reason = a[1];
+ res.url = a[2];
+ res.line = a[3];
+ res.linepos = a[4];
+ }
+ catch (ex) {
+ res.reason = "Uknown";
+ }
+ }
+
+ return res;
+ });
+} \ No newline at end of file
diff --git a/xloadtree/xtree2.js b/xloadtree/xtree2.js
new file mode 100644
index 00000000..26244bae
--- /dev/null
+++ b/xloadtree/xtree2.js
@@ -0,0 +1,1664 @@
+/*----------------------------------------------------------------------------\
+| XTree 2 PRE RELEASE |
+| |
+| This is a pre release and redistribution is discouraged. |
+| Watch http://webfx.eae.net for the final version |
+| |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson & Emil A Eklund |
+| (http://webfx.eae.net/contact.html#erik) |
+| (http://webfx.eae.net/contact.html#emil) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| A tree menu system for IE 5.5+, Mozilla 1.4+, Opera 7, KHTML |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2004 Erik Arvidsson & Emil A Eklund |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2004-02-21 | Pre release distributed to a few selected tester |
+|-----------------------------------------------------------------------------|
+| Dependencies: xtree2.css Used to define the look and feel |
+|-----------------------------------------------------------------------------|
+| Created 2003-??-?? | All changes are in the log above. | Updated 2004-02-21 |
+\----------------------------------------------------------------------------*/
+
+
+//
+// WebFXTreePersisitance
+function WebFXTreePersistence() {}
+WebFXTreePersistence.prototype.getExpanded = function (oNode) { return false; };
+WebFXTreePersistence.prototype.setExpanded = function (oNode, bOpen) {};
+
+
+
+// Cookie handling
+function WebFXCookie() {}
+
+WebFXCookie.prototype.setCookie = function (sName, sValue, nDays)
+{
+ var expires = "";
+ if (typeof nDays == "number")
+ {
+ var d = new Date();
+ d.setTime(d.getTime() + nDays * 24 * 60 * 60 * 1000);
+ expires = "; expires=" + d.toGMTString();
+ }
+
+ document.cookie = sName + "=" + escape(sValue) + expires + "; path=/";
+};
+
+WebFXCookie.prototype.getCookie = function (sName)
+{
+ var re = new RegExp("(\;|^)[^;]*(" + sName + ")\=([^;]*)(;|$)");
+ var res = re.exec(document.cookie);
+ return res != null ? unescape(res[3]) : null;
+};
+
+WebFXCookie.prototype.removeCookie = function (name)
+{
+ this.setCookie(name, "", -1);
+};
+
+
+//
+// persistence using cookies
+//
+// This is uses one cookie with the ids of the expanded nodes separated using '+'
+//
+function WebFXTreeCookiePersistence()
+{
+ this._openedMap = {};
+ this._cookies = new WebFXCookie;
+ var s = this._cookies.getCookie(this.cookieName);
+ if (s)
+ {
+ var a = s.split("+");
+ for (var i = a.length - 1; i >= 0; i--)
+ this._openedMap[a[i]] = true;
+ }
+}
+
+WebFXTreeCookiePersistence.prototype = new WebFXTreePersistence;
+
+WebFXTreeCookiePersistence.prototype.cookieName = "webfx-tree-cookie-persistence"
+
+WebFXTreeCookiePersistence.prototype.getExpanded = function (oNode)
+{
+ return oNode.id in this._openedMap;
+};
+
+WebFXTreeCookiePersistence.prototype.setExpanded = function (oNode, bOpen)
+{
+ var old = this.getExpanded(oNode);
+ if (old != bOpen)
+ {
+ if (bOpen)
+ this._openedMap[oNode.id] = true;
+ else
+ delete this._openedMap[oNode.id];
+
+ var res = [];
+ var i = 0;
+ for (var id in this._openedMap)
+ res[i++] = id;
+ this._cookies.setCookie(this.cookieName, res.join("+"));
+ }
+};
+
+
+
+// this object provides a few useful methods when working with arrays
+var arrayHelper =
+{
+ indexOf: function (a, o)
+ {
+ for (var i = 0; i < a.length; i++)
+ {
+ if (a[i] == o)
+ return i;
+ }
+ return -1;
+ },
+
+ insertBefore: function (a, o, o2)
+ {
+ var i = this.indexOf(a, o2);
+ if (i == -1)
+ a.push(o);
+ else
+ a.splice(i, 0, o);
+ },
+
+ remove: function (a, o)
+ {
+ var i = this.indexOf(a, o);
+ if (i != -1)
+ a.splice(i, 1);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// WebFX Tree Config object //
+///////////////////////////////////////////////////////////////////////////////
+var webFXTreeConfig = {
+ rootIcon : 'images/folder.png',
+ openRootIcon : 'images/openfolder.png',
+ folderIcon : 'images/folder.png',
+ openFolderIcon : 'images/openfolder.png',
+ fileIcon : 'images/file.png',
+ iIcon : 'images/I.png',
+ lIcon : 'images/L.png',
+ lMinusIcon : 'images/Lminus.png',
+ lPlusIcon : 'images/Lplus.png',
+ tIcon : 'images/T.png',
+ tMinusIcon : 'images/Tminus.png',
+ tPlusIcon : 'images/Tplus.png',
+ plusIcon : 'images/plus.png',
+ minusIcon : 'images/minus.png',
+ blankIcon : 'images/blank.png',
+ defaultText : 'Tree Item',
+ defaultAction : null,
+ defaultBehavior : 'classic',
+ usePersistence : true
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// WebFX Tree Handler object //
+///////////////////////////////////////////////////////////////////////////////
+
+var webFXTreeHandler = {
+ ie: /msie/i.test(navigator.userAgent),
+ idCounter : 0,
+ idPrefix : "wfxt-",
+ getUniqueId: function ()
+ {
+ return this.idPrefix + this.idCounter++;
+ },
+ all : {},
+ getNodeById: function (sId)
+ {
+ return all[sId];
+ },
+ addNode: function (oNode)
+ {
+ this.all[oNode.id] = oNode;
+ },
+ removeNode: function (oNode)
+ {
+ delete this.all[oNode.id];
+ },
+
+ handleEvent: function (e)
+ {
+ var el = e.target || e.srcElement;
+ while (el != null && !this.all[el.id])
+ el = el.parentNode;
+
+ if (el == null)
+ return false;
+ var node = this.all[el.id];
+ switch (e.type)
+ {
+ case "mousedown":
+ return node._onMouseDown(e);
+ case "click":
+ return node._onClick(e);
+ case "dblclick":
+ return node._onDblClick(e);
+ case "focus":
+ return node._onFocus(e);
+ case "blur":
+ return node._onBlur(e);
+ case "keydown":
+ return node._onKeyDown(e);
+ case "keypress":
+ return node._onKeyPress(e);
+ }
+ return false;
+ },
+
+ dispose: function ()
+ {
+ if (this.disposed) return;
+ for (var id in this.all)
+ this.all[id].dispose();
+ this.disposed = true;
+ },
+
+ opera: /opera/i.test(navigator.userAgent),
+
+ htmlToText: function (s)
+ {
+ return String(s).replace(/\s+|<([^>])+>|&amp;|&lt;|&gt;|&quot;|&nbsp;/gi, this._htmlToText);
+ },
+
+ _htmlToText: function (s)
+ {
+ switch (s)
+ {
+ case "&amp;":
+ return "&";
+ case "&lt;":
+ return "<";
+ case "&gt;":
+ return ">";
+ case "&quot;":
+ return "\"";
+ case "&nbsp;":
+ return String.fromCharCode(160);
+ default:
+ if (/\s+/.test(s))
+ return " ";
+ if (/^<BR/gi.test(s))
+ return "\n";
+ return "";
+ }
+ },
+
+ textToHtml: function (s)
+ {
+ return String(s).replace(/&|<|>|\n|\"\u00A0/g, this._textToHtml);
+ },
+
+ _textToHtml: function (s)
+ {
+ switch (s)
+ {
+ case "&":
+ return "&amp;";
+ case "<":
+ return "&lt;";
+ case ">":
+ return "&gt;";
+ case "\n":
+ return "<BR>";
+ case "\"":
+ return "&quot;"; // so we can use this in attributes
+ default:
+ return "&nbsp;";
+ }
+ },
+
+ persistenceManager: new WebFXTreeCookiePersistence()
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WebFXTreeAbstractNode
+///////////////////////////////////////////////////////////////////////////////
+
+function WebFXTreeAbstractNode(sText, oAction)
+{
+ this.childNodes = [];
+ if (sText) this.text = sText;
+ if (oAction) this.action = oAction;
+ this.id = webFXTreeHandler.getUniqueId();
+ if (webFXTreeConfig.usePersistence)
+ this.open = webFXTreeHandler.persistenceManager.getExpanded(this);
+ webFXTreeHandler.addNode(this);
+}
+
+
+var _p = WebFXTreeAbstractNode.prototype;
+_p._selected = false;
+_p.indentWidth = 19;
+_p.open = false;
+_p.text = webFXTreeConfig.defaultText;
+_p.action = null;
+_p.target = null;
+_p.toolTip = null;
+_p._focused = false;
+
+/* begin tree model */
+
+_p.add = function (oChild, oBefore)
+{
+ var oldLast;
+ var emptyBefore = this.childNodes.length == 0;
+ var p = oChild.parentNode;
+
+ if (oBefore == null)
+ { // append
+ if (p != null)
+ p.remove(oChild);
+ oldLast = this.getLastChild();
+ this.childNodes.push(oChild);
+ }
+ else
+ { // insertBefore
+ if (oBefore.parentNode != this)
+ throw new Error("Can only add nodes before siblings");
+ if (p != null)
+ p.remove(oChild);
+
+ arrayHelper.insertBefore(this.childNodes, oChild, oBefore);
+ }
+
+ oChild.parentNode = this;
+ var t = this.getTree();
+ if (t)
+ oChild.tree = t;
+ var d = this.getDepth();
+ if (d != null)
+ oChild.depth = d + 1;
+
+ if (this.getCreated() && !t.getSuspendRedraw())
+ {
+ var el = this.getChildrenElement();
+ var newEl = oChild.create();
+ var refEl = oBefore ? oBefore.getElement() : null;
+ el.insertBefore(newEl, refEl);
+
+ if (oldLast)
+ {
+ oldLast.updateExpandIcon();
+ }
+ if (emptyBefore)
+ {
+ this.setExpanded(this.getExpanded());
+ // if we are using classic expand will not update icon
+ if (t && t.getBehavior() != "classic")
+ this.updateIcon();
+ }
+ }
+
+ return oChild;
+};
+
+
+
+_p.remove = function (oChild)
+{
+ // backwards compatible. If no argument remove the node
+ if (arguments.length == 0)
+ {
+ if (this.parentNode)
+ return this.parentNode.remove(this);
+ return null;
+ }
+
+ // if we remove selected or tree with the selected we should select this
+ var t = this.getTree();
+ var si = t ? t.getSelected() : null;
+ if (si == oChild || oChild.contains(si))
+ {
+ if (si.getFocused())
+ {
+ this.select();
+ window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
+ }
+ else
+ this.select();
+ }
+
+ var wasLast = oChild.isLastSibling();
+
+ if (oChild.parentNode != this)
+ throw new Error("Can only remove children");
+ arrayHelper.remove(this.childNodes, oChild);
+
+ oChild.parentNode = null;
+ oChild.tree = null;
+ oChild.depth = null;
+
+ if (t && this.getCreated() && !t.getSuspendRedraw())
+ {
+ var el = this.getChildrenElement();
+ var childEl = oChild.getElement();
+ el.removeChild(childEl);
+ if (wasLast)
+ {
+ var newLast = this.getLastChild();
+ if (newLast)
+ newLast.updateExpandIcon();
+ }
+ if (!this.hasChildren())
+ {
+ //this.setExpanded(this.getExpanded());
+ el.style.display = "none";
+ this.updateExpandIcon();
+ this.updateIcon();
+ }
+ }
+
+ return oChild;
+};
+
+WebFXTreeAbstractNode._onTimeoutFocus = function (sId)
+{
+ var jsNode = webFXTreeHandler.all[sId];
+ jsNode.focus();
+};
+
+_p.getId = function ()
+{
+ return this.id;
+};
+
+_p.getTree = function ()
+{
+ throw new Error("getTree called on Abstract Node");
+};
+
+_p.getDepth = function ()
+{
+ throw new Error("getDepth called on Abstract Node");
+};
+
+_p.getCreated = function ()
+{
+ var t = this.getTree();
+ return t && t.rendered;
+};
+
+_p.getParent = function ()
+{
+ return this.parentNode;
+};
+
+_p.contains = function (oDescendant)
+{
+ if (oDescendant == null) return false;
+ if (oDescendant == this) return true;
+ var p = oDescendant.parentNode;
+ return this.contains(p);
+};
+
+_p.getChildren = _p.getChildNodes = function ()
+{
+ return this.childNodes;
+};
+
+_p.getFirstChild = function ()
+{
+ return this.childNodes[0];
+};
+
+_p.getLastChild = function ()
+{
+ return this.childNodes[this.childNodes.length - 1];
+};
+
+_p.getPreviousSibling = function ()
+{
+ var p = this.parentNode;
+ if (p == null) return null;
+ var cs = p.childNodes;
+ return cs[arrayHelper.indexOf(cs, this) - 1]
+};
+
+_p.getNextSibling = function ()
+{
+ var p = this.parentNode;
+ if (p == null) return null;
+ var cs = p.childNodes;
+ return cs[arrayHelper.indexOf(cs, this) + 1]
+};
+
+_p.hasChildren = function ()
+{
+ return this.childNodes.length > 0;
+};
+
+
+_p.isLastSibling = function ()
+{
+ return this.parentNode && this == this.parentNode.getLastChild();
+};
+
+_p.findChildByText = function (s, n)
+{
+ if (!n)
+ n = 0;
+ var isRe = s instanceof RegExp;
+ for (var i = 0; i < this.childNodes.length; i++)
+ {
+ if (isRe && s.test(this.childNodes[i].getText()) || this.childNodes[i].getText() == s)
+ {
+ if (n == 0)
+ return this.childNodes[i];
+ n--;
+ }
+ }
+ return null;
+};
+
+_p.findNodeByText = function (s, n)
+{
+ if (!n)
+ n = 0;
+ var isRe = s instanceof RegExp;
+
+ if (isRe && s.test(this.getText()) || this.getText() == s)
+ {
+ if (n == 0)
+ return this.childNodes[i];
+ n--;
+ }
+
+ var res;
+ for (var i = 0; i < this.childNodes.length; i++)
+ {
+ res = this.childNodes[i].findNodeByText(s, n);
+ if (res)
+ return res;
+ }
+ return null;
+};
+
+/* end tree model */
+
+_p.setId = function (sId)
+{
+ var el = this.getElement();
+ webFXTreeHandler.removeNode(this);
+ this.id = sId;
+ if (el)
+ el.id = sId;
+ webFXTreeHandler.addNode(this);
+};
+
+_p.isSelected = function ()
+{
+ return this._selected;
+};
+
+_p.select = function () { this._setSelected(true); };
+_p.deselect = function () { this._setSelected(false); };
+
+_p._setSelected = function (b)
+{
+ var t = this.getTree();
+ if (!t) return;
+ if (this._selected != b)
+ {
+ this._selected = b;
+
+ var wasFocused = false; // used to keep focus state
+ var si = t.getSelected();
+ if (b && si != null && si != this)
+ {
+ var oldFireChange = t._fireChange;
+ wasFocused = si._focused;
+ t._fireChange = false;
+ si._setSelected(false);
+ t._fireChange = oldFireChange;
+ }
+
+ var el = this.getRowElement();
+ if (el)
+ {
+ el.className = this.getRowClassName();
+ }
+ if (b)
+ {
+ t._selectedItem = this;
+ t._fireOnChange();
+ t.setSelected(this);
+ if (wasFocused)
+ this.focus();
+ }
+
+ if (t.getBehavior() != "classic")
+ this.updateIcon();
+ }
+};
+
+
+_p.getExpanded = function ()
+{
+ return this.open;
+};
+
+_p.setExpanded = function (b)
+{
+ var ce;
+ this.open = b;
+ var t = this.getTree();
+ if (this.hasChildren())
+ {
+ var si = t ? t.getSelected() : null;
+ if (!b && this.contains(si))
+ this.select();
+
+ var el = this.getElement();
+ if (el)
+ {
+ ce = this.getChildrenElement();
+ if (ce)
+ ce.style.display = b ? "block" : "none";
+ var eie = this.getExpandIconElement();
+ if (eie)
+ eie.src = this.getExpandIconSrc();
+ }
+
+ if (webFXTreeConfig.usePersistence)
+ webFXTreeHandler.persistenceManager.setExpanded(this, b);
+ }
+ else
+ {
+ ce = this.getChildrenElement();
+ if (ce)
+ ce.style.display = "none";
+ }
+ if (t && t.getBehavior() == "classic")
+ this.updateIcon();
+};
+
+_p.toggle = function ()
+{
+ this.setExpanded(!this.getExpanded());
+};
+
+_p.expand = function ()
+{
+ this.setExpanded(true);
+};
+
+_p.collapse = function ()
+{
+ this.setExpanded(false);
+};
+
+_p.collapseChildren = function()
+{
+ var cs = this.childNodes;
+ for (var i = 0; i < cs.length; i++)
+ cs[i].collapseAll();
+};
+
+_p.collapseAll = function()
+{
+ this.collapseChildren();
+ this.collapse();
+};
+
+_p.expandChildren = function()
+{
+ var cs = this.childNodes;
+ for (var i = 0; i < cs.length; i++)
+ cs[i].expandAll();
+};
+
+_p.expandAll = function ()
+{
+ this.expandChildren();
+ this.expand();
+};
+
+_p.reveal = function ()
+{
+ var p = this.getParent();
+ if (p)
+ {
+ p.setExpanded(true);
+ p.reveal();
+ }
+};
+
+_p.openPath = function (sPath, bSelect, bFocus)
+{
+ if (sPath == "")
+ {
+ if (bSelect)
+ this.select();
+ if (bFocus)
+ window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
+ return;
+ }
+
+ var parts = sPath.split("/");
+ var remainingPath = parts.slice(1).join("/");
+ var t = this.getTree();
+ if (sPath.charAt(0) == "/")
+ {
+ if (t)
+ t.openPath(remainingPath, bSelect, bFocus);
+ else
+ throw "Invalid path";
+ }
+ else
+ {
+ // open
+ this.setExpanded(true);
+ parts = sPath.split("/");
+ var ti = this.findChildByText(parts[0]);
+ if (!ti)
+ throw "Could not find child node with text \"" + parts[0] + "\"";
+ ti.openPath(remainingPath, bSelect, bFocus);
+ }
+};
+
+_p.focus = function ()
+{
+ var el = this.getLabelElement();
+ if (el)
+ el.focus();
+};
+
+_p.getFocused = function ()
+{
+ return this._focused;
+};
+
+// HTML generation
+
+_p.toHtml = function ()
+{
+ var childrenSb = [];
+ var cs = this.childNodes;
+ var l = cs.length;
+ for (var y = 0; y < l; y++)
+ childrenSb[y] = cs[y].toHtml();
+
+ var t = this.getTree();
+ var hideLines = !t.getShowLines() || t == this.parentNode && !t.getShowRootLines();
+
+ var childrenHtml = "<div class=\"webfx-tree-children" +
+ (hideLines ? "-nolines" : "") + "\" style=\"" +
+ this.getLineStyle() +
+ (this.getExpanded() && this.hasChildren() ? "" : "display:none;") +
+ "\">" +
+ childrenSb.join("") +
+ "</div>";
+
+ return "<div class=\"webfx-tree-item\" id=\"" +
+ this.id + "\"" + this.getEventHandlersHtml() + ">" +
+ this.getRowHtml() +
+ childrenHtml +
+ "</div>";
+};
+
+_p.getRowHtml = function ()
+{
+ var t = this.getTree();
+ return "<div class=\"" + this.getRowClassName() + "\" style=\"padding-left:" +
+ (this.getDepth() - 1) * this.indentWidth + "px\">" +
+ this.getExpandIconHtml() +
+ //"<span class=\"webfx-tree-icon-and-label\">" +
+ this.getIconHtml() +
+ this.getLabelHtml() +
+ //"</span>" +
+ "</div>";
+};
+
+_p.getRowClassName = function ()
+{
+ return "webfx-tree-row" + (this.isSelected() ? " selected" : "") +
+ (this.action ? "" : " no-action");
+};
+
+_p.getLabelHtml = function ()
+{
+ var toolTip = this.getToolTip();
+ var target = this.getTarget();
+ return "<a href=\"" + webFXTreeHandler.textToHtml(this._getHref()) +
+ "\" class=\"webfx-tree-item-label\"" +
+ (toolTip ? " title=\"" + webFXTreeHandler.textToHtml(toolTip) + "\"" : "") +
+ (target ? " target=\"" + target + "\"" : "") +
+ " onfocus=\"webFXTreeHandler.handleEvent(event)\"" +
+ " onblur=\"webFXTreeHandler.handleEvent(event)\">" +
+ this.getHtml() + "</a>";
+};
+
+_p._getHref = function ()
+{
+ if (typeof this.action == "string")
+ return this.action;
+ else
+ return "#";
+};
+
+_p.getEventHandlersHtml = function ()
+{
+ return "";
+};
+
+_p.getIconHtml = function ()
+{
+ // here we are not using textToHtml since the file names rarerly contains
+ // HTML...
+ return "<img class=\"webfx-tree-icon\" src=\"" + this.getIconSrc() + "\">";
+};
+
+_p.getIconSrc = function ()
+{
+ throw new Error("getIconSrc called on Abstract Node");
+};
+
+_p.getExpandIconHtml = function ()
+{
+ // here we are not using textToHtml since the file names rarerly contains
+ // HTML...
+ return "<img class=\"webfx-tree-expand-icon\" src=\"" +
+ this.getExpandIconSrc() + "\">";
+};
+
+
+_p.getExpandIconSrc = function ()
+{
+ var src;
+ var t = this.getTree();
+ var hideLines = !t.getShowLines() || t == this.parentNode && !t.getShowRootLines();
+
+ if (this.hasChildren())
+ {
+ var bits = 0;
+ /*
+ Bitmap used to determine which icon to use
+ 1 Plus
+ 2 Minus
+ 4 T Line
+ 8 L Line
+ */
+
+ if (t && t.getShowExpandIcons())
+ {
+ if (this.getExpanded())
+ bits = 2;
+ else
+ bits = 1;
+ }
+
+ if (t && !hideLines)
+ {
+ if (this.isLastSibling())
+ bits += 4;
+ else
+ bits += 8;
+ }
+
+ switch (bits)
+ {
+ case 1:
+ return webFXTreeConfig.plusIcon;
+ case 2:
+ return webFXTreeConfig.minusIcon;
+ case 4:
+ return webFXTreeConfig.lIcon;
+ case 5:
+ return webFXTreeConfig.lPlusIcon;
+ case 6:
+ return webFXTreeConfig.lMinusIcon;
+ case 8:
+ return webFXTreeConfig.tIcon;
+ case 9:
+ return webFXTreeConfig.tPlusIcon;
+ case 10:
+ return webFXTreeConfig.tMinusIcon;
+ default: // 0
+ return webFXTreeConfig.blankIcon;
+ }
+ }
+ else
+ {
+ if (t && hideLines)
+ return webFXTreeConfig.blankIcon;
+ else if (this.isLastSibling())
+ return webFXTreeConfig.lIcon;
+ else
+ return webFXTreeConfig.tIcon;
+ }
+};
+
+_p.getLineStyle = function ()
+{
+ return "background-position:" + this.getLineStyle2() + ";";
+};
+
+_p.getLineStyle2 = function ()
+{
+ return (this.isLastSibling() ? "-100" : (this.getDepth() - 1) * this.indentWidth) + "px 0";
+};
+
+// End HTML generation
+
+// DOM
+// this returns the div for the tree node
+_p.getElement = function ()
+{
+ return document.getElementById(this.id);
+};
+
+// the row is the div that is used to draw the node without the children
+_p.getRowElement = function ()
+{
+ var el = this.getElement();
+ if (!el) return null;
+ return el.firstChild;
+};
+
+// plus/minus image
+_p.getExpandIconElement = function ()
+{
+ var el = this.getRowElement();
+ if (!el) return null;
+ return el.firstChild;
+};
+
+_p.getIconElement = function ()
+{
+ var el = this.getRowElement();
+ if (!el) return null;
+ return el.childNodes[1];
+};
+
+// anchor element
+_p.getLabelElement = function ()
+{
+ var el = this.getRowElement();
+ if (!el) return null;
+ return el.lastChild;
+};
+
+// the div containing the children
+_p.getChildrenElement = function ()
+{
+ var el = this.getElement();
+ if (!el) return null;
+ return el.lastChild;
+};
+
+
+// IE uses about:blank if not attached to document and this can cause Win2k3
+// to fail
+if (webFXTreeHandler.ie)
+{
+ _p.create = function ()
+ {
+ var dummy = document.createElement("div");
+ dummy.style.display = "none";
+ document.body.appendChild(dummy);
+ dummy.innerHTML = this.toHtml();
+ var res = dummy.removeChild(dummy.firstChild);
+ document.body.removeChild(dummy);
+ return res;
+ };
+}
+else
+{
+ _p.create = function ()
+ {
+ var dummy = document.createElement("div");
+ dummy.innerHTML = this.toHtml();
+ return dummy.removeChild(dummy.firstChild);
+ };
+
+}
+
+// Getters and setters for some common fields
+
+_p.setIcon = function (s)
+{
+ this.icon = s;
+ if (this.getCreated())
+ this.updateIcon();
+};
+
+_p.getIcon = function ()
+{
+ return this.icon;
+};
+
+_p.setOpenIcon = function (s)
+{
+ this.openIcon = s;
+ if (this.getCreated())
+ this.updateIcon();
+};
+
+_p.getOpenIcon = function ()
+{
+ return this.openIcon;
+};
+
+_p.setText = function (s)
+{
+ this.setHtml(webFXTreeHandler.textToHtml(s));
+};
+
+_p.getText = function ()
+{
+ return webFXTreeHandler.htmlToText(this.getHtml());
+};
+
+_p.setHtml = function (s)
+{
+ this.text = s;
+ var el = this.getLabelElement();
+ if (el)
+ el.innerHTML = s;
+};
+
+_p.getHtml = function ()
+{
+ return this.text;
+};
+
+_p.setTarget = function (s)
+{
+ this.target = s;
+};
+
+_p.getTarget = function ()
+{
+ return this.target;
+};
+
+_p.setToolTip = function (s)
+{
+ this.toolTip = s;
+ var el = this.getLabelElement();
+ if (el)
+ el.title = s;
+};
+
+_p.getToolTip = function ()
+{
+ return this.toolTip;
+};
+
+_p.setAction = function (oAction)
+{
+ this.action = oAction;
+ var el = this.getLabelElement();
+ if (el)
+ el.href = this._getHref();
+ el = this.getRowElement();
+ if (el)
+ el.className = this.getRowClassName();
+};
+
+_p.getAction = function ()
+{
+ return this.action;
+};
+
+// update methods
+
+_p.update = function ()
+{
+ var t = this.getTree();
+ if (t.suspendRedraw) return;
+ var el = this.getElement();
+ if (!el || !el.parentNode) return;
+ var newEl = this.create();
+ el.parentNode.replaceChild(newEl, el);
+
+ var si = t.getSelected();
+ if (si && si.getFocused())
+ si.focus();
+};
+
+_p.updateExpandIcon = function ()
+{
+ var t = this.getTree();
+ if (t.suspendRedraw) return;
+ var img = this.getExpandIconElement();
+ img.src = this.getExpandIconSrc();
+ var cel = this.getChildrenElement();
+ cel.style.backgroundPosition = this.getLineStyle2();
+};
+
+_p.updateIcon = function ()
+{
+ var t = this.getTree();
+ if (t.suspendRedraw) return;
+ var img = this.getIconElement();
+ img.src = this.getIconSrc();
+};
+
+// End DOM
+
+
+_p._callSuspended = function (f)
+{
+ var t = this.getTree();
+ var sr = t.getSuspendRedraw();
+ t.setSuspendRedraw(true);
+ f.call(this);
+ t.setSuspendRedraw(sr);
+};
+
+// Event handlers
+
+_p._onMouseDown = function (e)
+{
+ var el = e.target || e.srcElement;
+ // expand icon
+ if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren())
+ {
+ this.toggle();
+ if ( webFXTreeHandler.ie )
+ window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
+ return false;
+ }
+
+ this.select();
+ if (!/webfx-tree-item-label/.test(el.className) && !webFXTreeHandler.opera) // opera cancels the click if focus is called
+ {
+ // in case we are not clicking on the label
+ if (webFXTreeHandler.ie)
+ window.setTimeout("WebFXTreeAbstractNode._onTimeoutFocus(\"" + this.id + "\")", 10);
+ else
+ this.focus();
+ }
+ var rowEl = this.getRowElement();
+ if (rowEl)
+ rowEl.className = this.getRowClassName();
+
+ return false;
+};
+
+_p._onClick = function (e)
+{
+ var el = e.target || e.srcElement;
+ // expand icon
+ if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren())
+ return false;
+
+ if (typeof this.action == "function")
+ this.action();
+ else if (this.action != null)
+ window.open(this.action, this.target || "_self");
+ return false;
+};
+
+
+_p._onDblClick = function (e)
+{
+ var el = e.target || e.srcElement;
+ // expand icon
+ if (/webfx-tree-expand-icon/.test(el.className) && this.hasChildren())
+ return;
+
+ this.toggle();
+};
+
+_p._onFocus = function (e)
+{
+ this.select();
+ this._focused = true;
+};
+
+_p._onBlur = function (e)
+{
+ this._focused = false;
+};
+
+_p._onKeyDown = function (e)
+{
+ var n;
+ var rv = true;
+ switch (e.keyCode)
+ {
+ case 39: // RIGHT
+ if (e.altKey)
+ {
+ rv = true;
+ break;
+ }
+ if (this.hasChildren())
+ {
+ if (!this.getExpanded())
+ this.setExpanded(true);
+ else
+ {
+ this.getFirstChild().focus();
+ }
+ }
+ rv = false;
+ break;
+ case 37: // LEFT
+ if (e.altKey)
+ {
+ rv = true;
+ break;
+ }
+ if (this.hasChildren() && this.getExpanded())
+ this.setExpanded(false);
+ else
+ {
+ var p = this.getParent();
+ var t = this.getTree();
+ // don't go to root if hidden
+ if (p && (t.showRootNode || p != t))
+ {
+ p.focus();
+ }
+ }
+ rv = false;
+ break;
+
+ case 40: // DOWN
+ n = this.getNextShownNode();
+ if (n)
+ {
+ n.focus();
+ }
+ rv = false;
+ break;
+ case 38: // UP
+ n = this.getPreviousShownNode()
+ if (n)
+ {
+ n.focus();
+ }
+ rv = false;
+ break;
+ }
+
+ if (!rv && e.preventDefault)
+ e.preventDefault();
+ e.returnValue = rv;
+ return rv;
+};
+
+_p._onKeyPress = function (e)
+{
+ if (!e.altKey && e.keyCode >= 37 && e.keyCode <= 40)
+ {
+ if (e.preventDefault)
+ e.preventDefault();
+ e.returnValue = false;
+ return false;
+ }
+};
+
+// End event handlers
+
+_p.dispose = function ()
+{
+ if (this.disposed) return;
+ for (var i = this.childNodes.length - 1; i >= 0; i--)
+ this.childNodes[i].dispose();
+ this.tree = null;
+ this.parentNode = null;
+ this.childNodes = null;
+ this.disposed = true;
+};
+
+// Some methods that are usable when navigating the tree using the arrows
+_p.getLastShownDescendant = function ()
+{
+ if (!this.getExpanded() || !this.hasChildren())
+ return this;
+ // we know there is at least 1 child
+ return this.getLastChild().getLastShownDescendant();
+};
+
+_p.getNextShownNode = function ()
+{
+ if (this.hasChildren() && this.getExpanded())
+ return this.getFirstChild();
+ else
+ {
+ var p = this;
+ var next;
+ while (p != null)
+ {
+ next = p.getNextSibling();
+ if (next != null)
+ return next;
+ p = p.getParent();
+ }
+ return null;
+ }
+};
+
+_p.getPreviousShownNode = function ()
+{
+ var ps = this.getPreviousSibling();
+ if (ps != null)
+ {
+ return ps.getLastShownDescendant();
+ }
+ var p = this.getParent();
+ var t = this.getTree();
+ if (!t.showRootNode && p == t)
+ return null;
+ return p;
+};
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WebFXTree
+///////////////////////////////////////////////////////////////////////////////
+
+function WebFXTree(sText, oAction, sBehavior, sIcon, sOpenIcon)
+{
+ WebFXTreeAbstractNode.call(this, sText, oAction);
+
+ if (sIcon)
+ this.icon = sIcon;
+ if (sOpenIcon)
+ this.openIcon = sOpenIcon;
+ if (sBehavior)
+ this.behavior = sBehavior;
+}
+
+_p = WebFXTree.prototype = new WebFXTreeAbstractNode;
+_p.indentWidth = 19;
+_p.open = true;
+_p._selectedItem = null;
+_p._fireChange = true;
+_p.rendered = false;
+_p.suspendRedraw = false;
+_p.showLines = true;
+_p.showExpandIcons = true;
+_p.showRootNode = true;
+_p.showRootLines = true;
+
+_p.getTree = function ()
+{
+ return this;
+};
+
+_p.getDepth = function ()
+{
+ return 0;
+};
+
+_p.getCreated = function ()
+{
+ return this.rendered;
+};
+
+
+/* end tree model */
+
+_p.getExpanded = function ()
+{
+ return !this.showRootNode || WebFXTreeAbstractNode.prototype.getExpanded.call(this);
+};
+
+_p.setExpanded = function (b)
+{
+ if (!this.showRootNode)
+ this.open = b;
+ else
+ WebFXTreeAbstractNode.prototype.setExpanded.call(this, b);
+};
+
+_p.getExpandIconHtml = function ()
+{
+ return "";
+};
+
+// we don't have an expand icon here
+_p.getIconElement = function ()
+{
+ var el = this.getRowElement();
+ if (!el) return null;
+ return el.firstChild;
+};
+
+// no expand icon for root element
+_p.getExpandIconElement = function (oDoc)
+{
+ return null;
+};
+
+_p.updateExpandIcon = function ()
+{
+ // no expand icon
+};
+
+_p.getRowClassName = function ()
+{
+ return WebFXTreeAbstractNode.prototype.getRowClassName.call(this) +
+ (this.showRootNode ? "" : " webfx-tree-hide-root");
+};
+
+
+// if classic then the openIcon is used for expanded, otherwise openIcon is used
+// for selected
+
+_p.getIconSrc = function ()
+{
+ var behavior = this.getTree() ? this.getTree().getBehavior() : webFXTreeConfig.defaultBehavior;
+ var open = behavior == "classic" && this.getExpanded() ||
+ behavior != "classic" && this.isSelected();
+ if (open && this.openIcon)
+ return this.openIcon;
+ if (!open && this.icon)
+ return this.icon;
+ // fall back on default icons
+ return open ? webFXTreeConfig.openRootIcon : webFXTreeConfig.rootIcon;
+};
+
+_p.getEventHandlersHtml = function ()
+{
+ return " onclick=\"return webFXTreeHandler.handleEvent(event)\" " +
+ "onmousedown=\"return webFXTreeHandler.handleEvent(event)\" " +
+ "ondblclick=\"return webFXTreeHandler.handleEvent(event)\" " +
+ "onkeydown=\"return webFXTreeHandler.handleEvent(event)\" " +
+ "onkeypress=\"return webFXTreeHandler.handleEvent(event)\"";
+};
+
+_p.setSelected = function (o)
+{
+ if (this._selectedItem != o)
+ {
+ if (o)
+ o._setSelected(true);
+ }
+};
+
+_p._fireOnChange = function ()
+{
+ if (this._fireChange && typeof this.onchange == "function")
+ this.onchange();
+};
+
+_p.getSelected = function ()
+{
+ return this._selectedItem;
+};
+
+_p.setBehavior = function (s)
+{
+ this.behavior = s;
+};
+
+_p.getBehavior = function ()
+{
+ return this.behavior || webFXTreeConfig.defaultBehavior;
+};
+
+_p.setShowLines = function (b)
+{
+ if (this.showLines != b)
+ {
+ this.showLines = b;
+ if (this.rendered)
+ this.update();
+ }
+};
+
+_p.getShowLines = function ()
+{
+ return this.showLines;
+};
+
+_p.setShowRootLines = function (b)
+{
+ if (this.showRootLines != b)
+ {
+ this.showRootLines = b;
+ if (this.rendered)
+ this.update();
+ }
+};
+
+_p.getShowRootLines = function ()
+{
+ return this.showRootLines;
+};
+
+_p.setShowExpandIcons = function (b)
+{
+ if (this.showExpandIcons != b)
+ {
+ this.showExpandIcons = b;
+ if (this.rendered)
+ this.getTree().update();
+ }
+};
+
+_p.getShowExpandIcons = function ()
+{
+ return this.showExpandIcons;
+};
+
+_p.setShowRootNode = function (b)
+{
+ if (this.showRootNode != b)
+ {
+ this.showRootNode = b;
+ if (this.rendered)
+ this.getTree().update();
+ }
+};
+
+_p.getShowRoootNode = function ()
+{
+ return this.showRootNode;
+};
+
+_p.onchange = function () {};
+
+_p.create = function ()
+{
+ var el = WebFXTreeAbstractNode.prototype.create.call(this);
+ this.rendered = true;
+ return el;
+};
+
+_p.write = function ()
+{
+ document.write(this.toHtml());
+ this.rendered = true;
+};
+
+_p.setSuspendRedraw = function (b)
+{
+ this.suspendRedraw = b;
+};
+
+_p.getSuspendRedraw = function ()
+{
+ return this.suspendRedraw;
+};
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// WebFXTreeItem
+///////////////////////////////////////////////////////////////////////////////
+
+function WebFXTreeItem(sText, oAction, eParent, sIcon, sOpenIcon)
+{
+ WebFXTreeAbstractNode.call(this, sText, oAction);
+ if (sIcon)
+ this.icon = sIcon;
+ if (sOpenIcon)
+ this.openIcon = sOpenIcon;
+ if (eParent)
+ eParent.add(this);
+}
+
+_p = WebFXTreeItem.prototype = new WebFXTreeAbstractNode;
+_p.tree = null;
+
+/* tree model */
+
+_p.getDepth = function ()
+{
+ if (this.depth != null)
+ return this.depth;
+ if (this.parentNode)
+ {
+ var pd = this.parentNode.getDepth();
+ return this.depth = (pd != null ? pd + 1 : null);
+ }
+ return null;
+};
+
+_p.getTree = function ()
+{
+ if (this.tree)
+ return this.tree;
+ if (this.parentNode)
+ return this.tree = this.parentNode.getTree();
+ return null;
+};
+
+_p.getCreated = function ()
+{
+ var t = this.getTree();
+ return t && t.getCreated();
+};
+
+// if classic then the openIcon is used for expanded, otherwise openIcon is used
+// for selected
+_p.getIconSrc = function ()
+{
+ var behavior = this.getTree() ? this.getTree().getBehavior() : webFXTreeConfig.defaultBehavior;
+ var open = behavior == "classic" && this.getExpanded() ||
+ behavior != "classic" && this.isSelected();
+ if (open && this.openIcon)
+ return this.openIcon;
+ if (!open && this.icon)
+ return this.icon;
+
+ // fall back on default icons
+ if (this.hasChildren())
+ return open ? webFXTreeConfig.openFolderIcon : webFXTreeConfig.folderIcon;
+ return webFXTreeConfig.fileIcon;
+};
+
+/* end tree model */
+
+
+
+
+if (window.attachEvent)
+{
+ window.attachEvent("onunload", function ()
+ {
+ for (var id in webFXTreeHandler.all)
+ webFXTreeHandler.all[id].dispose();
+ });
+}