├── wwwroot ├── pix │ ├── 1x1t.gif │ ├── slb.png │ ├── 8021q.png │ ├── checked.png │ ├── favicon.ico │ ├── files.png │ ├── link-up.png │ ├── racks.png │ ├── report.png │ ├── router.png │ ├── server.png │ ├── download.png │ ├── link-down.png │ ├── unchecked.png │ ├── addressspace.png │ ├── ajax-loader.gif │ ├── bg_selection.gif │ ├── checkbox_yes.png │ ├── download-big.png │ ├── kterm-16x16.png │ ├── loadbalancer.png │ ├── mitsudragon.png │ ├── patch_cables.png │ ├── pencil-icon.png │ ├── serverpool.png │ ├── servicesign.png │ ├── tango-go-up.png │ ├── addressspacev6.png │ ├── bracket-16x16.png │ ├── bracket-32x32.png │ ├── configuration.png │ ├── link-disabled.png │ ├── node-collapsed.png │ ├── node-expanded.png │ ├── smiley_knight.png │ ├── tango-computer.png │ ├── tango-go-next.png │ ├── tango-list-add.png │ ├── crystal-ok-32x32.png │ ├── pgadmin3-viewdata.png │ ├── tango-edit-clear.png │ ├── tango-go-previous.png │ ├── tango-list-remove.png │ ├── tango-text-html.png │ ├── virtualresources.png │ ├── tango-dialog-error.png │ ├── tango-document-new.png │ ├── tango-emblem-system.png │ ├── tango-list-add-big.png │ ├── tango-network-wired.png │ ├── tango-system-search.png │ ├── node-expanded-static.png │ ├── tango-dialog-error-big.png │ ├── tango-document-new-big.png │ ├── tango-edit-clear-big.png │ ├── tango-edit-copy-16x16.png │ ├── tango-edit-copy-32x32.png │ ├── tango-edit-cut-16x16.png │ ├── tango-edit-cut-22x22.png │ ├── tango-edit-cut-32x32.png │ ├── tango-emblem-favorite.png │ ├── tango-internet-32x32.png │ ├── tango-user-trash-16x16.png │ ├── tango-user-trash-32x32.png │ ├── crystal-edit-user-32x32.png │ ├── crystal-file-empty-32x32.png │ ├── crystal-file-image-32x32.png │ ├── crystal-file-text-32x32.png │ ├── tango-appointment-32x32.png │ ├── tango-go-prev-next-32x32.png │ ├── tango-list-remove-32x32.png │ ├── tango-list-remove-shadow.png │ ├── tango-view-refresh-16x16.png │ ├── tango-view-refresh-32x32.png │ ├── crystal-network_local-16x16.png │ ├── crystal-network_local-32x32.png │ ├── pgadmin3-viewdata-grayscale.png │ ├── pgadmin3-viewfiltereddata.png │ ├── tango-document-save-16x16.png │ ├── tango-document-save-32x32.png │ ├── tango-edit-clear-gray-32x32.png │ ├── tango-edit-cut-22x22-gray.png │ ├── tango-edit-cut-32x32-gray.png │ ├── tango-emblem-readonly-32x32.png │ ├── tango-emblem-system-32x32.png │ ├── tango-mail-attachment-16x16.png │ ├── tango-mail-attachment-22x22.png │ ├── tango-mail-attachment-32x32.png │ ├── tango-system-search-22x22.png │ ├── tango-text-x-generic-16x16.png │ ├── tango-user-trash-16x16-gray.png │ ├── tango-user-trash-32x32-gray.png │ ├── tango-view-fullscreen-22x22.png │ ├── crystal-actions-unlock-32x32.png │ ├── tango-emblem-important-32x32.png │ ├── tango-emblem-unreadable-32x32.png │ ├── tango-go-prev-next-gray-32x32.png │ ├── tango-document-save-32x32-gray.png │ ├── crystal-mimetypes-shellscript-218x200.png │ ├── pgadmin3-viewfiltereddata-grayscale.png │ └── jquery-ui-1.8.22.redmond │ │ ├── ui-icons_217bc0_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_469bdd_256x240.png │ │ ├── ui-icons_6da8d5_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-icons_d8e7f3_256x240.png │ │ ├── ui-icons_f9bd01_256x240.png │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_55_fbec88_40x100.png │ │ ├── ui-bg_glass_75_d0e5f5_1x400.png │ │ ├── ui-bg_glass_85_dfeffc_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_gloss-wave_55_5c9ccc_500x100.png │ │ ├── ui-bg_inset-hard_100_f5f8f9_1x100.png │ │ └── ui-bg_inset-hard_100_fcfdfd_1x100.png ├── js │ ├── tabindex_auto.js │ ├── net-usage.js │ ├── codemirror │ │ └── rackcode.js │ ├── vst_editor.js │ ├── racktables.js │ ├── slb_editor.js │ ├── tag-cb.js │ ├── inplace-edit.js │ ├── jquery.thumbhover.js │ ├── live_validation.js │ ├── portinfo.js │ ├── jquery.optionTree.js │ └── jquery.contextmenu.js ├── css │ ├── codemirror │ │ ├── rackcode.css │ │ └── codemirror.css │ ├── tagit.css │ └── jquery.contextmenu.css ├── inc │ ├── config.php │ ├── breed-ios15.php │ ├── caching.php │ ├── pre-init.php │ ├── init.php │ ├── triggers.php │ ├── interface-cables.php │ └── ajax-interface.php └── index.php ├── .editorconfig ├── scripts ├── cleanup_ldap_cache.php ├── reload_dictionary.php └── syncdomain.php ├── gateways ├── ssh ├── netcat ├── telnet ├── ucssdk ├── sshnokey └── git-commit ├── plugins └── README ├── Makefile ├── README.Fedora └── COPYING /wwwroot/pix/1x1t.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/1x1t.gif -------------------------------------------------------------------------------- /wwwroot/pix/slb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/slb.png -------------------------------------------------------------------------------- /wwwroot/pix/8021q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/8021q.png -------------------------------------------------------------------------------- /wwwroot/pix/checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/checked.png -------------------------------------------------------------------------------- /wwwroot/pix/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/favicon.ico -------------------------------------------------------------------------------- /wwwroot/pix/files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/files.png -------------------------------------------------------------------------------- /wwwroot/pix/link-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/link-up.png -------------------------------------------------------------------------------- /wwwroot/pix/racks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/racks.png -------------------------------------------------------------------------------- /wwwroot/pix/report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/report.png -------------------------------------------------------------------------------- /wwwroot/pix/router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/router.png -------------------------------------------------------------------------------- /wwwroot/pix/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/server.png -------------------------------------------------------------------------------- /wwwroot/pix/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/download.png -------------------------------------------------------------------------------- /wwwroot/pix/link-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/link-down.png -------------------------------------------------------------------------------- /wwwroot/pix/unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/unchecked.png -------------------------------------------------------------------------------- /wwwroot/pix/addressspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/addressspace.png -------------------------------------------------------------------------------- /wwwroot/pix/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/ajax-loader.gif -------------------------------------------------------------------------------- /wwwroot/pix/bg_selection.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/bg_selection.gif -------------------------------------------------------------------------------- /wwwroot/pix/checkbox_yes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/checkbox_yes.png -------------------------------------------------------------------------------- /wwwroot/pix/download-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/download-big.png -------------------------------------------------------------------------------- /wwwroot/pix/kterm-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/kterm-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/loadbalancer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/loadbalancer.png -------------------------------------------------------------------------------- /wwwroot/pix/mitsudragon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/mitsudragon.png -------------------------------------------------------------------------------- /wwwroot/pix/patch_cables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/patch_cables.png -------------------------------------------------------------------------------- /wwwroot/pix/pencil-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/pencil-icon.png -------------------------------------------------------------------------------- /wwwroot/pix/serverpool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/serverpool.png -------------------------------------------------------------------------------- /wwwroot/pix/servicesign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/servicesign.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-go-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-go-up.png -------------------------------------------------------------------------------- /wwwroot/pix/addressspacev6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/addressspacev6.png -------------------------------------------------------------------------------- /wwwroot/pix/bracket-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/bracket-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/bracket-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/bracket-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/configuration.png -------------------------------------------------------------------------------- /wwwroot/pix/link-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/link-disabled.png -------------------------------------------------------------------------------- /wwwroot/pix/node-collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/node-collapsed.png -------------------------------------------------------------------------------- /wwwroot/pix/node-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/node-expanded.png -------------------------------------------------------------------------------- /wwwroot/pix/smiley_knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/smiley_knight.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-computer.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-go-next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-go-next.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-list-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-list-add.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-ok-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-ok-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/pgadmin3-viewdata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/pgadmin3-viewdata.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-clear.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-go-previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-go-previous.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-list-remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-list-remove.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-text-html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-text-html.png -------------------------------------------------------------------------------- /wwwroot/pix/virtualresources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/virtualresources.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-dialog-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-dialog-error.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-document-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-document-new.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-system.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-list-add-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-list-add-big.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-network-wired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-network-wired.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-system-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-system-search.png -------------------------------------------------------------------------------- /wwwroot/pix/node-expanded-static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/node-expanded-static.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-dialog-error-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-dialog-error-big.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-document-new-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-document-new-big.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-clear-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-clear-big.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-copy-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-copy-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-copy-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-copy-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-cut-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-cut-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-cut-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-cut-22x22.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-cut-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-cut-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-favorite.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-internet-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-internet-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-user-trash-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-user-trash-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-user-trash-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-user-trash-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-edit-user-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-edit-user-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-file-empty-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-file-empty-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-file-image-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-file-image-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-file-text-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-file-text-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-appointment-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-appointment-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-go-prev-next-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-go-prev-next-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-list-remove-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-list-remove-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-list-remove-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-list-remove-shadow.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-view-refresh-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-view-refresh-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-view-refresh-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-view-refresh-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-network_local-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-network_local-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-network_local-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-network_local-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/pgadmin3-viewdata-grayscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/pgadmin3-viewdata-grayscale.png -------------------------------------------------------------------------------- /wwwroot/pix/pgadmin3-viewfiltereddata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/pgadmin3-viewfiltereddata.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-document-save-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-document-save-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-document-save-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-document-save-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-clear-gray-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-clear-gray-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-cut-22x22-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-cut-22x22-gray.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-edit-cut-32x32-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-edit-cut-32x32-gray.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-readonly-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-readonly-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-system-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-system-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-mail-attachment-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-mail-attachment-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-mail-attachment-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-mail-attachment-22x22.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-mail-attachment-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-mail-attachment-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-system-search-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-system-search-22x22.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-text-x-generic-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-text-x-generic-16x16.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-user-trash-16x16-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-user-trash-16x16-gray.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-user-trash-32x32-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-user-trash-32x32-gray.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-view-fullscreen-22x22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-view-fullscreen-22x22.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-actions-unlock-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-actions-unlock-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-important-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-important-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-emblem-unreadable-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-emblem-unreadable-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-go-prev-next-gray-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-go-prev-next-gray-32x32.png -------------------------------------------------------------------------------- /wwwroot/pix/tango-document-save-32x32-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/tango-document-save-32x32-gray.png -------------------------------------------------------------------------------- /wwwroot/pix/crystal-mimetypes-shellscript-218x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/crystal-mimetypes-shellscript-218x200.png -------------------------------------------------------------------------------- /wwwroot/pix/pgadmin3-viewfiltereddata-grayscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/pgadmin3-viewfiltereddata-grayscale.png -------------------------------------------------------------------------------- /wwwroot/js/tabindex_auto.js: -------------------------------------------------------------------------------- 1 | // insert tabindex to input elements 2 | $(document).ready(function() 3 | { 4 | $(":input, a[name=submit], a.input").attr("tabindex", 1); 5 | }); 6 | -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_217bc0_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_217bc0_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_469bdd_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_469bdd_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_6da8d5_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_6da8d5_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_d8e7f3_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_d8e7f3_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_f9bd01_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-icons_f9bd01_256x240.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_flat_55_fbec88_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_flat_55_fbec88_40x100.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_75_d0e5f5_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_75_d0e5f5_1x400.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_85_dfeffc_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_85_dfeffc_1x400.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_gloss-wave_55_5c9ccc_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_gloss-wave_55_5c9ccc_500x100.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_inset-hard_100_f5f8f9_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_inset-hard_100_f5f8f9_1x100.png -------------------------------------------------------------------------------- /wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_inset-hard_100_fcfdfd_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RackTables/racktables/HEAD/wwwroot/pix/jquery-ui-1.8.22.redmond/ui-bg_inset-hard_100_fcfdfd_1x100.png -------------------------------------------------------------------------------- /wwwroot/css/codemirror/rackcode.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { height: 500px; } 2 | .cm-s-rackcode span.cm-comment { font-style: italic; color: gray; } 3 | .cm-s-rackcode span.cm-operator { color: blue; } 4 | .cm-s-rackcode span.cm-variable { color: orange; } 5 | .cm-s-rackcode span.cm-def { color: magenta; } 6 | .cm-s-rackcode span.cm-keyword { font-weight: bold; } 7 | .cm-s-rackcode span.cm-atom { font-weight: normal; color: brown; } 8 | -------------------------------------------------------------------------------- /wwwroot/js/net-usage.js: -------------------------------------------------------------------------------- 1 | $(document).ready (function () { 2 | $('div.net-usage.pending').click(function(e) { 3 | var div = this; 4 | $.get( 5 | 'index.php', 6 | { 7 | module: 'ajax', 8 | ac: 'net-usage', 9 | net_id: div.id 10 | }, 11 | function (data, textStatus, jqXHR) { 12 | $(div) 13 | .removeClass('pending') 14 | .unbind(e) 15 | .replaceWith(data); 16 | } 17 | ) 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /wwwroot/inc/config.php: -------------------------------------------------------------------------------- 1 | \$op_help, 15 | 'sudo-user:s' => \$op_as_user, 16 | ); 17 | if ($op_help) { 18 | &display_help; 19 | exit; 20 | } 21 | 22 | &become_user; 23 | exec ('ssh', @ARGV) or die "exec ssh: $!"; 24 | 25 | sub display_help { 26 | print <] [ -- ] [ ssh params ] 31 | --sudo-user sudo self as specified username 32 | END 33 | } 34 | 35 | sub become_user { 36 | if (defined $op_as_user) { 37 | my $uid = getpwnam ($op_as_user); 38 | if (! defined $uid) { 39 | die "getpwnam $op_as_user: $!"; 40 | } 41 | if ($uid != $>) { 42 | exec ('sudo', '-u', "#$uid", $0, '--', @ARGV) or die "exec sudo: $!"; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /wwwroot/js/codemirror/rackcode.js: -------------------------------------------------------------------------------- 1 | (function(mod) { 2 | if (typeof exports == "object" && typeof module == "object") // CommonJS 3 | mod(require("../../lib/codemirror")); 4 | else if (typeof define == "function" && define.amd) // AMD 5 | define(["../../lib/codemirror"], mod); 6 | else // Plain browser env 7 | mod(CodeMirror); 8 | })(function(CodeMirror) { 9 | "use strict"; 10 | CodeMirror.defineMode('rackcode', function() 11 | { 12 | return { 13 | token: function (stream) 14 | { 15 | const WORDS = 16 | { 17 | 'allow': 'keyword positive', 18 | 'deny': 'keyword negative', 19 | 'define': 'keyword', 20 | 'context': 'keyword', 21 | 'clear': 'keyword', 22 | 'insert': 'keyword', 23 | 'remove': 'keyword', 24 | 'on': 'keyword', 25 | 'true': 'atom', 26 | 'false': 'atom', 27 | 'and': 'operator', 28 | 'or': 'operator', 29 | 'not': 'operator', 30 | }; 31 | return stream.eatSpace() ? null : 32 | stream.eat ('(') ? 'bracket' : 33 | stream.eat (')') ? 'bracket' : 34 | stream.match (/^#.*$/) ? 'comment' : 35 | stream.match (/^{[^{}]+}/) ? 'variable' : // a tag 36 | stream.match (/^\[[^\[\]]+\]/) ? 'def' : // a predicate 37 | stream.eatWhile (/\S/) ? WORDS[stream.current()] : 38 | null; 39 | } 40 | }; 41 | }); 42 | 43 | CodeMirror.defineMIME("text/x-rackcode", "rackcode"); 44 | }); 45 | -------------------------------------------------------------------------------- /plugins/README: -------------------------------------------------------------------------------- 1 | *** New Plugin Architecture *** 2 | 3 | Each plugin should reside in its own directory and contain a file named 4 | plugin.php housing certain mandatory functions. 5 | 6 | Refer to https://wiki.racktables.org/index.php/Plugins 7 | for more information. 8 | 9 | *** Old Plugin Architecture *** 10 | 11 | Put your custom RackTables add-ons into this folder. 12 | 13 | Old local.php file is the sample of such add-ons and should be put here 14 | to continue working. 15 | 16 | Files should be named with .php extension to be loaded automatically. 17 | Files are loaded in alphabetical order. 18 | 19 | It is recommended to override existing tabhandlers and ophandlers using 20 | registerTabHandler and registerOpHandler functions, respectively. 21 | This is preferred over overwriting of items in $tabhandler and $ophandler, 22 | because allows overriding the same tab or operation in multiple plugins. 23 | 24 | Consider the following sample: 25 | 26 | 44 | -------------------------------------------------------------------------------- /scripts/reload_dictionary.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | beginTransaction(); 23 | foreach ($qlist as $query) 24 | { 25 | try 26 | { 27 | $success = $dbxlink->exec ($query) !== FALSE; 28 | } 29 | catch (PDOException $e) 30 | { 31 | $success = FALSE; 32 | } 33 | if (! $success) 34 | $flist[] = $query; 35 | } 36 | 37 | if (count ($flist)) 38 | { 39 | $dbxlink->rollBack(); 40 | foreach ($flist as $query) 41 | fprintf (STDERR, "FAILED: %s\n", $query); 42 | fprintf (STDERR, "Dictionary reload has been rolled back due to errors (%u queries failed out of %u).\n", 43 | count ($flist), count ($qlist)); 44 | exit (1); 45 | } 46 | else 47 | { 48 | $dbxlink->commit(); 49 | printf ("Dictionary reload complete (%u SQL queries).\n", count ($qlist)); 50 | exit (0); 51 | } 52 | -------------------------------------------------------------------------------- /gateways/netcat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | # This file is a part of RackTables, a datacenter and server room management 4 | # framework. See accompanying file "COPYING" for the full copyright and 5 | # licensing information. 6 | 7 | use strict; 8 | use Getopt::Long; 9 | use POSIX ":sys_wait_h"; 10 | 11 | # fetch command-line parameters 12 | my $op_help; 13 | my $op_port = 23; 14 | my $op_ncbin = 'nc'; 15 | my $op_timeout = 30; 16 | GetOptions ( 17 | 'h' => \$op_help, 18 | 'port|p:i' => \$op_port, 19 | 'ncbin|b:s' => \$op_ncbin, 20 | 'timeout|w:i' => \$op_timeout, 21 | ); 22 | if ($op_help) { 23 | &display_help; 24 | exit; 25 | } 26 | my $op_host = $ARGV[0]; 27 | defined $op_host or die "ERROR: missing hostname argument (-h for help)"; 28 | 29 | sub display_help { 30 | print < [-b ] [-p ] [--connect-timeout=] 34 | -p, --port TCP port number to connect to (defaults to 23) 35 | -b, --ncbin Full path to netcat binary (defaults to $op_ncbin) 36 | -w, --connect-timeout netcat timeout (defaults to $op_timeout) 37 | 38 | END 39 | } 40 | 41 | my @params = ('-w', $op_timeout, '-v'); 42 | 43 | pipe (RD, WR); 44 | my $child_pid = fork(); 45 | defined $child_pid or die "fork: $!"; 46 | if (! $child_pid) { 47 | close RD; 48 | open (STDERR, ">&WR") or die "open: $!"; 49 | exec ($op_ncbin, $op_host, $op_port, @params) or die "exec $op_ncbin: $!"; 50 | } 51 | close WR; 52 | 53 | # suppress error output if nc returns 0 54 | my $error_buff = ''; 55 | while () { 56 | $error_buff .= $_; 57 | } 58 | waitpid $child_pid, 0; 59 | if ($?) { 60 | print STDERR $error_buff; 61 | $? = $? >> 8; 62 | exit $? ? $? : 1; 63 | } 64 | -------------------------------------------------------------------------------- /wwwroot/js/vst_editor.js: -------------------------------------------------------------------------------- 1 | // var new_vst_row is set through inline JS script 2 | 3 | $(document).ready(function() { 4 | $('a.vst-add-rule').click(AddVSTRule) 5 | $('a.vst-del-rule').click(RemoveVSTRule) 6 | $('form#upd') 7 | .submit(VSTSubmit) 8 | .change(highlightUnsavedVST); 9 | }); 10 | 11 | function AddVSTRule(event) { 12 | var tr = $(this).closest('tr'); 13 | var new_tr; 14 | if ($(event.target).parents('.vst-add-rule.initial').length) 15 | new_tr = $('').html(new_vst_row); 16 | else 17 | new_tr = tr.clone(); 18 | tr.after(new_tr); 19 | new_tr.find('a.vst-add-rule').click(AddVSTRule); 20 | new_tr.find('a.vst-del-rule').click(RemoveVSTRule); 21 | 22 | highlightUnsavedVST(); 23 | return false; 24 | } 25 | 26 | function RemoveVSTRule(event) { 27 | $(this).closest('tr').remove(); 28 | highlightUnsavedVST(); 29 | return false; 30 | } 31 | 32 | function VSTSubmit() { 33 | var result = []; 34 | $('table.template-rules tr').each(function(i, item) { 35 | var line = {}; 36 | $(item).find('input , select').each(function(i, item) { line[item.name] = $(item).val(); }); 37 | if (line['rule_no'] != undefined) 38 | result.push(line); 39 | }); 40 | if (! result.length && ! confirm('The template is empty. Do you really want to save it?')) 41 | return false; 42 | $(this).find('input[name|="template_json"]').val(JSON.stringify(result)); 43 | return true; 44 | } 45 | 46 | function highlightUnsavedVST() { 47 | // highlight only on first call of this function 48 | if ( typeof highlightUnsavedVST.isAlreadyCalled == 'undefined' ) { 49 | highlightUnsavedVST.isAlreadyCalled = true; 50 | $('form#upd input[name|="submit"]').before('
Template is unsaved. Click here to save it
'); 51 | console.log('a'); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DESTDIR ?= 2 | prefix ?= /usr/local 3 | docdir ?= $(prefix)/share/doc/RackTables 4 | datadir ?= $(prefix)/share 5 | # Default values reproduce the layout present in tar.gz, which concurs with 6 | # the default values of $racktables_gwdir and $racktables_staticdir. But 7 | # once the latter are patched for a shared deploy, it is enough to execute 8 | # "make install" with appropriate arguments to split the filesystem. 9 | staticdir ?= $(datadir)/RackTables/wwwroot 10 | applibdir ?= $(datadir)/RackTables/wwwroot/inc 11 | indexdir ?= $(datadir)/RackTables/wwwroot 12 | scriptdir ?= $(datadir)/RackTables 13 | 14 | INSTALL := install 15 | INSTALL_DATA := $(INSTALL) -m 644 16 | INSTALL_DIR := $(INSTALL) -m 755 -d 17 | INSTALL_PROGRAM := $(INSTALL) -m 755 18 | 19 | install-docs: COPYING ChangeLog LICENSE README.md 20 | $(INSTALL_DIR) $(DESTDIR)$(docdir) 21 | $(INSTALL_DATA) $^ $(DESTDIR)$(docdir) 22 | 23 | install-helpers: scripts gateways 24 | $(INSTALL_DIR) $(DESTDIR)$(scriptdir) 25 | cp -r $^ $(DESTDIR)$(scriptdir) 26 | find $(DESTDIR)$(scriptdir)/scripts -type d -a -name '.git' -exec rm -rf \{\} \; -prune 27 | find $(DESTDIR)$(scriptdir)/gateways -type d -a -name '.git' -exec rm -rf \{\} \; -prune 28 | 29 | install-static: wwwroot/css wwwroot/js wwwroot/pix 30 | $(INSTALL_DIR) $(DESTDIR)$(staticdir) 31 | cp -r $^ $(DESTDIR)$(staticdir) 32 | find $(DESTDIR)$(staticdir) -type d -a -name '.git' -exec rm -rf \{\} \; -prune 33 | 34 | install-applib: wwwroot/inc 35 | $(INSTALL_DIR) $(DESTDIR)$(applibdir)/inc 36 | $(INSTALL_DATA) wwwroot/inc/*.php $(DESTDIR)$(applibdir) 37 | 38 | install-index: wwwroot/index.php 39 | $(INSTALL_DIR) $(DESTDIR)$(indexdir) 40 | $(INSTALL_DATA) wwwroot/index.php $(DESTDIR)$(indexdir) 41 | 42 | install: install-helpers install-static install-applib install-index 43 | -------------------------------------------------------------------------------- /wwwroot/js/racktables.js: -------------------------------------------------------------------------------- 1 | // JavaScript functions 2 | 3 | // Used for (un)checking an entire row of rackspace atoms 4 | function toggleRowOfAtoms (rackId, rowId) { 5 | var toSet; 6 | var element; 7 | toSet = null; 8 | for (var columnId=0; columnId<=2; columnId++) { 9 | element = document.getElementById("atom_" + rackId + "_" + rowId + "_" + columnId); 10 | if (element != null && ! element.disabled) { 11 | if (toSet == null) 12 | toSet = !element.checked; 13 | element.checked = toSet; 14 | } 15 | } 16 | } 17 | 18 | // Used for (un)checking an entire column of rackspace atoms 19 | function toggleColumnOfAtoms (rackId, columnId, numRows) { 20 | var toSet; 21 | var element; 22 | toSet = null; 23 | for (var rowId=1; rowId').addClass ('popup-box').appendTo ('body').append (new_form); 15 | // confirmation box on port/vip deletion 16 | $('a.del-used-slb').click (function (e) { 17 | return confirm ('This entity is used. Please confirm the deletion'); 18 | }); 19 | 20 | $(this).thumbPopup (form, { event: e }); 21 | return false; 22 | }); 23 | 24 | // confirmation box on triplet deletion 25 | $('form#del input').click (function (e) { 26 | return confirm ('Please confirm the deletion of triplet'); 27 | }); 28 | 29 | // new triplet form stage1 handler 30 | var forms = $('form#addLink'); 31 | forms.submit (function() { return false }); 32 | forms.find('input[name="submit"]').click (function (e) { 33 | var form = $(this).parents('form'); 34 | $.ajax ({ 35 | type: 'POST', 36 | url: 'index.php', 37 | data: { 38 | 'module': 'ajax', 39 | 'ac': 'get-slb-form', 40 | 'form': form.serialize(), 41 | 'action': form.attr('action') 42 | }, 43 | 'success': function (data) { 44 | form.replaceWith (data); 45 | } 46 | }); 47 | 48 | return false; 49 | }); 50 | }); 51 | 52 | function slb_config_preview (e, object_id, vs_id, rspool_id) { 53 | $.ajax ({ 54 | type: 'POST', 55 | url: 'index.php', 56 | data: { 57 | module: 'ajax', 58 | ac: 'triplet-preview', 59 | object_id: object_id, 60 | vs_id: vs_id, 61 | rspool_id: rspool_id 62 | }, 63 | success: function (data) { 64 | var div = $('
').addClass('popup-box').appendTo('body'); 65 | div.html(data); 66 | $(this).thumbPopup (div, { event: e }); 67 | } 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /wwwroot/inc/breed-ios15.php: -------------------------------------------------------------------------------- 1 | $ret['current']['sys_name'], 44 | 'port' => $port, 45 | ); 46 | } 47 | unset ($ret['current']); 48 | break; 49 | default: 50 | } 51 | } 52 | unset ($ret['current']); 53 | return $ret; 54 | } 55 | 56 | // most of the commands are compatible with IOS12, so are generated by ios12TranslatePushQueue 57 | // Only ios15-specific commands are generated here (eg., lldp) 58 | function ios15TranslatePushQueue ($dummy_object_id, $queue, $dummy_vlan_names) 59 | { 60 | $ret = ''; 61 | foreach ($queue as $cmd) 62 | switch ($cmd['opcode']) 63 | { 64 | case 'getlldpstatus': 65 | $ret .= "show lldp neighbors detail | i Local Intf:|Chassis id:|Port id:|Port Description:|System Name:\n"; 66 | break; 67 | default: 68 | $ret .= ios12TranslatePushQueue ($dummy_object_id, array ($cmd), $dummy_vlan_names); 69 | break; 70 | } 71 | return $ret; 72 | } 73 | -------------------------------------------------------------------------------- /README.Fedora: -------------------------------------------------------------------------------- 1 | RUNNING RACKTABLES ON A FEDORA SYSTEM 2 | ===================================== 3 | 4 | Most files in Fedora package of RackTables application reside in the 5 | /usr/share/RackTables directory regardless of package version. It is 6 | assumed that this directory is never directly used in httpd's "document 7 | root" setting. Instead a symlink or a PHP "require" construct should be 8 | used for the index.php (and ONLY index.php) file based on some other 9 | directory that is the actual wwwroot. This greatly improves 10 | security and allows for the two use cases described below. 11 | 12 | 1. Single RackTables instance per server. By default the application 13 | expects its configuration file (secret.php) in /etc/RackTables directory, 14 | which is a part of the RPM. In a fresh installation the files is missing, 15 | no MySQL database is setup and there is no symlink. 16 | 17 | Setting up the symlink is simple: one needs to decide on the URL of the 18 | RackTables system and map it to filesystem path. For example, the commands 19 | below are likely to enable access through "http://localhost/racktables/": 20 | 21 | # mkdir /var/www/html/racktables 22 | # ln -s /usr/share/RackTables/wwwroot/index.php /var/www/html/racktables 23 | 24 | After that opening the URL in a browser will bring up RackTables installer, 25 | which will fill in /etc/RackTables/secret.php file and the contents of the 26 | MySQL database. After that the setup is complete. 27 | 28 | 29 | 2. Multiple RackTables instances per server. The application is designed 30 | to be able to serve many independent MySQL databases with the same 31 | codebase, but different configuration files. This requires a separate 32 | config directory per each instance. Each of the directories will feature 33 | an own secret.php file configured for its own MySQL database. 34 | 35 | For example, 3 virtual hosts should provide an independent RackTables 36 | application each. It is assumed that httpd is already configured for the 37 | virtual hosts using respective directories: 38 | 39 | /var/www/vhosts/racktables.example1.com 40 | /var/www/vhosts/racktables.example2.com 41 | /var/www/vhosts/racktables.example3.com 42 | 43 | The configuration directories could be: 44 | 45 | # mkdir /etc/RackTables/example[123] 46 | 47 | The "wwwroot" directories will require a short PHP wrapper file each. The 48 | wrappers will differ only in the value of $racktables_confdir setting: 49 | 50 | # cat > /var/www/vhosts/racktables.example1.com/index.php < \$op_help, 22 | 'port:i' => \$op_port, 23 | 'connect-timeout:i' => \$op_connect_timeout, 24 | 'timeout:i' => \$op_timeout, 25 | 'prompt-delay:f' => \$op_delay, 26 | 'prompt:s' => \$op_prompt, 27 | '4' => \$op_ipv4, 28 | '6' => \$op_ipv6, 29 | ); 30 | if ($op_help) { 31 | &display_help; 32 | exit; 33 | } 34 | my $op_host = $ARGV[0]; 35 | defined $op_host or die "ERROR: please specify remote host (-h for help)"; 36 | defined $op_prompt or die "ERROR: please specify prompt regexp (-h for help)"; 37 | my $prompt_re = qr/$op_prompt/; 38 | 39 | sub display_help { 40 | print <new ( 69 | Host => $op_host, 70 | Port => $port, 71 | Family => $family, 72 | Timeout => $op_connect_timeout, 73 | ); 74 | 75 | use IO::Select; 76 | my $sel = new IO::Select($session); 77 | 78 | $|=1; 79 | my $buff = ''; 80 | my $nohang_read; 81 | until ($session->eof) { 82 | # read output from the device 83 | eval { 84 | my $chunk = $session->get (Timeout => $nohang_read ? 0 : $op_timeout, Errmode => $nohang_read ? 'return' : 'die'); 85 | $buff .= $chunk; 86 | print $chunk; 87 | }; 88 | if ($@) { 89 | # check if there is something else in 90 | if (defined ) { 91 | die $@; 92 | } 93 | else { 94 | last; # no more input, seems like session was closed remotely by our last command 95 | } 96 | } 97 | $nohang_read = 0; 98 | $buff =~ s/(.*\n)//s; 99 | 100 | next unless ($buff =~ $prompt_re); 101 | # send pending commands to the device 102 | if ($op_delay and IO::Select->select ($sel, undef, undef, $op_delay)) { 103 | # something is received, no prompt detection at this time 104 | # set NOHANG options for next reading, cause it can be telnet control sequence 105 | $nohang_read = 1; 106 | } 107 | elsif (defined ($_ = )) { 108 | # replace all CR and LF symbols with single trailing LF 109 | s/[\015\012]//g; 110 | $session->put($_ . "\012"); 111 | } 112 | else { 113 | # no more commands in input 114 | last; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /wwwroot/inc/caching.php: -------------------------------------------------------------------------------- 1 | = $creation_ts && // not modified since 29 | (! $expire || $client_time + $expire >= $server_time) // expiration timeout is not set, or not expired 30 | ); 31 | $last_modified = $creation_ts > 0 ? $creation_ts : ($client_time > 0 ? $client_time : $server_time); 32 | 33 | header ("Cache-Control: private, max-age=$expire, pre-check=$expire"); 34 | if ($result) 35 | header ('Last-Modified: ' . gmdate (DATE_RFC1123, $last_modified), TRUE, 304); 36 | else 37 | header ('Last-Modified: ' . gmdate (DATE_RFC1123, $last_modified)); 38 | return $result; 39 | } 40 | 41 | function HTTPDateToUnixTime ($string) 42 | { 43 | // Written per RFC 2616 3.3.1 - Full Date 44 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html 45 | $month_number = array 46 | ( 47 | 'Jan' => 1, 48 | 'Feb' => 2, 49 | 'Mar' => 3, 50 | 'Apr' => 4, 51 | 'May' => 5, 52 | 'Jun' => 6, 53 | 'Jul' => 7, 54 | 'Aug' => 8, 55 | 'Sep' => 9, 56 | 'Oct' => 10, 57 | 'Nov' => 11, 58 | 'Dec' => 12, 59 | ); 60 | 61 | $formats = array(); 62 | // RFC2616 dictates exchanged timestamps to be in GMT TZ, and RFC822 63 | // (which RFC1123 relies on) explicitly defines that "GMT" is equivalent 64 | // to "-0000" and "+0000". 65 | $formats['rfc1123'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/'; 66 | $formats['rfc850'] = '/^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/'; 67 | $formats['asctime'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}| \d{1}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/'; 68 | 69 | $matches = array(); 70 | if (preg_match ($formats['rfc1123'], $string, $matches)) 71 | { 72 | $hours = $matches[5]; 73 | $minutes = $matches[6]; 74 | $seconds = $matches[7]; 75 | $month = $month_number[$matches[3]]; 76 | $day = $matches[2]; 77 | $year = $matches[4]; 78 | } 79 | elseif (preg_match ($formats['rfc850'], $string, $matches)) 80 | { 81 | $hours = $matches[5]; 82 | $minutes = $matches[6]; 83 | $seconds = $matches[7]; 84 | $month = $month_number[$matches[3]]; 85 | $day = $matches[2]; 86 | $year = $matches[4]; 87 | } 88 | elseif (preg_match ($formats['asctime'], $string, $matches)) 89 | { 90 | $hours = $matches[4]; 91 | $minutes = $matches[5]; 92 | $seconds = $matches[6]; 93 | $month = $month_number[$matches[2]]; 94 | $day = $matches[3]; 95 | $year = $matches[7]; 96 | } 97 | else 98 | return FALSE; 99 | if ($hours > 23 || $minutes > 59 || $seconds > 59 || ! checkdate ($month, $day, $year)) 100 | return FALSE; 101 | return gmmktime ($hours, $minutes, $seconds, $month, $day, $year); 102 | } 103 | -------------------------------------------------------------------------------- /wwwroot/js/tag-cb.js: -------------------------------------------------------------------------------- 1 | var tag_cb = new function () { // singletone class 2 | 3 | var self = this; 4 | this.enableNegation = function() { enableNegation = true; }; 5 | var enableNegation = false; 6 | 7 | // called from interface.php:renderCellFilterPortlet() if SHRINK_TAG_TREE_ON_CLICK is set 8 | this.enableSubmitOnClick = function() { enableSubmitOnClick = true; }; 9 | var enableSubmitOnClick = false; 10 | 11 | this.setTagShortList = function(list) { tagShortList = list; }; 12 | var tagShortList = {}; 13 | 14 | $(document).ready (function () { 15 | if (! enableNegation) 16 | return; 17 | $('.tag-cb').click(function (event) { 18 | cbClick(event, false); 19 | }); 20 | $('.tag-cb').closest('label') 21 | .mousedown(function(){return false}) 22 | .click(function (event) { 23 | cbClick(event, true); 24 | return false; 25 | }); 26 | $('input[name=andor]').click(function (event) { 27 | if ($('.tag-cb:checked').size() != 0 && event.target.value == 'and') { 28 | $(event.target).closest('form')[0].submit(); 29 | } 30 | }); 31 | }); 32 | 33 | // this is a handler for both checkbox click and label click 34 | // suppresses the default action, sets cb checked state and brings input focus on int 35 | // changes the name of checkbox if it is negated 36 | // submits form if this feature is enabled, and filter combination function is 'and' 37 | function cbClick (event, bInvert) { 38 | event.stopImmediatePropagation(); 39 | var td = $(event.target).closest('td'); 40 | var cb = td.find('.tag-cb'); 41 | if (cb.length != 1) 42 | return; 43 | var tagId = cb.attr('value'); 44 | var checked = cb.attr('checked'); 45 | if (bInvert) 46 | checked = ! checked; 47 | if ((event.ctrlKey || event.metaKey) && ! td.hasClass('inverted') && checked) { 48 | var name = cb.attr('name'); 49 | if (name.match(/^cf([tp]\[\])$/)) 50 | cb.attr('name', 'nf' + RegExp.$1); 51 | td.addClass ('inverted'); 52 | } 53 | else { 54 | var name = cb.attr('name'); 55 | if (name.match(/^nf([tp]\[\])$/)) 56 | cb.attr('name', 'cf' + RegExp.$1); 57 | td.removeClass('inverted'); 58 | } 59 | if (bInvert) 60 | cb.attr('checked', checked ? 'checked' : ''); 61 | cb.focus(); 62 | 63 | if (enableSubmitOnClick) { 64 | var and_check = $('input[name=andor][value=and]')[0]; 65 | if (and_check.checked) 66 | $(event.target).closest('form')[0].submit(); 67 | } 68 | } 69 | 70 | this.compactTreeMode = function() { 71 | // reconfigure toggle link 72 | var link = $('a.toggleTreeMode')[0]; 73 | if ($(link).filter(':visible')) { 74 | $(link).after('

'); 75 | } 76 | link.onclick = function () {self.fullTreeMode(); return false;}; 77 | $(link).html('show full tree').show(); 78 | 79 | $('.tagtree').addClass('compact'); // disable hierarchical padding 80 | 81 | var separator = false; // next visible row is separator 82 | var bPrevSeparator = true; // prev visible row was separator 83 | $('input.tag-cb').each(function (i, item) { 84 | var tr = $(item).closest('tr'); 85 | 86 | if ($(item).hasClass('root')) 87 | separator = true; 88 | 89 | if (! item.checked && ! tagShortList[item.value]) { 90 | tr.hide(); 91 | return; 92 | } 93 | 94 | if (separator && ! bPrevSeparator) { // do not draw two separators together or very first separator 95 | tr.addClass('separator'); 96 | bPrevSeparator = true; 97 | } 98 | else { 99 | tr.removeClass('separator'); 100 | bPrevSeparator = false; 101 | } 102 | separator = false; 103 | }); 104 | } 105 | 106 | this.fullTreeMode = function() { 107 | // reconfigure toggle link 108 | var link = $('a.toggleTreeMode')[0]; 109 | link.onclick = function () {self.compactTreeMode(); return false;}; 110 | $(link).html('show compact tree').show(); 111 | 112 | $('.tagtree').removeClass('compact'); // restore hierarchical padding 113 | 114 | var bPrevSeparator = true; // prev visible row was separator 115 | $('input.tag-cb').each(function (i, item) { // // do not draw two separators together or very first separator 116 | var tr = $(item).closest('tr'); 117 | tr.removeClass('separator'); 118 | 119 | var separator = $(item).hasClass('root'); 120 | if (separator && ! bPrevSeparator) 121 | tr.addClass('separator'); 122 | bPrevSeparator = separator; 123 | 124 | tr.show(); 125 | }); 126 | } 127 | 128 | }; 129 | -------------------------------------------------------------------------------- /gateways/ucssdk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file is a part of RackTables, a datacenter and server room management 4 | # framework. See accompanying file "COPYING" for the full copyright and 5 | # licensing information. 6 | 7 | # Requires Cisco ucsmsdk 0.9.1.0 or higher - https://communities.cisco.com/docs/DOC-64378 8 | # This script provides an online stdin/stdout interface to the list of an UCS 9 | # domain components. This is done through Python ucsmsdk interfacing with the UCS 10 | # manager (domain controller) instance, a virtual service provided by physical 11 | # UCS Fabric Interconnect switches. The list is output in a text format and is 12 | # eventually available as PHP array through queryDevice() RackTables function. 13 | # 14 | # Script stdin is a multiline text in the following format: 15 | # 16 | # login 17 | # getmo 18 | # 19 | # Script stdout is also a multiline text consisting of OK/ERR lines optionally 20 | # preceded with other content. In the case of enumeration the content is a 21 | # series of COLUMNS and ROW lines with CSV data. 22 | 23 | import sys 24 | try: 25 | from ucsmsdk import * 26 | from ucsmsdk.ucshandle import * 27 | from ucsmsdk.mometa.network.NetworkElement import NetworkElement 28 | from ucsmsdk.mometa.equipment.EquipmentChassis import EquipmentChassis 29 | from ucsmsdk.mometa.compute.ComputeBlade import ComputeBlade 30 | from ucsmsdk.mometa.vnic.VnicFc import VnicFc 31 | from ucsmsdk.mometa.vnic.VnicEther import VnicEther 32 | from ucsmsdk.mometa.compute.ComputeRackUnit import ComputeRackUnit 33 | except Exception, err: 34 | sys.stderr.write('UCS Python SDK is missing %s (Path: %s)\n' % (str(err), sys.path)) 35 | sys.stderr.write('

Available at https://communities.cisco.com/docs/DOC-64378

\n') 36 | sys.exit(2) 37 | 38 | loggedin = 0 39 | while 1: 40 | try: 41 | line = sys.stdin.readline() 42 | except KeyboardInterrupt: 43 | break 44 | 45 | if not line: 46 | break 47 | 48 | words = line.split() 49 | if len(words) == 0: 50 | continue 51 | elif len(words) >= 1 and words[0] == "help": 52 | print "HELP: login " 53 | print "HELP: Immediately try to log into specified UCS manager instance with given credentials." 54 | print "HELP: getmo" 55 | print "HELP: Retrieve lists of managed objects and output as a set of tables (requires active login)." 56 | print "OK" 57 | # endif "help" 58 | elif len(words) == 4 and words[0] == "login": 59 | try: 60 | if loggedin == 1: 61 | print "INFO Closing previous connection..." 62 | handle.Logout() 63 | handle=UcsHandle(words[1], words[2], words[3]) 64 | if (handle.login() == False): 65 | loggedin = 0 66 | print "ERR could not log into " + words[1] 67 | sys.exit(0) 68 | loggedin = 1 69 | print "OK logged into " + words[1] 70 | except Exception, err: 71 | loggedin = 0 72 | print "ERR could not log into " + words[1] 73 | # endif "login" 74 | elif len(words) == 1 and words[0] == "getmo": 75 | if (loggedin != 1): 76 | print "ERR not logged in" 77 | else: 78 | try: 79 | print "COLUMNS type,serial,DN,model,OOB" 80 | for mo in handle.query_classid(class_id="NetworkElement"): 81 | print "ROW NetworkElement," + mo.serial + "," + mo.dn + "," + mo.model + "," + mo.oob_if_ip 82 | print "COLUMNS type,serial,DN,model" 83 | for ch in handle.query_classid(class_id="EquipmentChassis"): 84 | print "ROW EquipmentChassis," + ch.serial + "," + ch.dn + "," + ch.model 85 | print "COLUMNS type,serial,DN,model,assigned,slot" 86 | for bl in handle.query_classid(class_id="ComputeBlade"): 87 | print "ROW ComputeBlade," + bl.serial + "," + bl.dn + "," + bl.model + "," + bl.assigned_to_dn + "," + bl.slot_id 88 | print "COLUMNS type,DN,name,addr" 89 | for po in handle.query_classid(class_id="VnicEther") + handle.query_classid(class_id="VnicFc"): 90 | if (po.addr != "derived"): 91 | print "ROW VnicPort," + po.dn + "," + po.name + "," + po.addr 92 | print "COLUMNS type,serial,DN,model,assigned" 93 | for rm in handle.query_classid(class_id="ComputeRackUnit"): 94 | print "ROW ComputeRackUnit," + rm.serial + "," + rm.dn + "," + rm.model + "," + rm.assigned_to_dn 95 | print "OK enumeration complete" 96 | except Exception, err: 97 | print "ERR exception occurred, logging out" 98 | loggedin = 0 99 | # endif "getmo" 100 | else: 101 | print "ERR command not supported (type \"help\" for help)" 102 | # endfor 103 | sys.exit(0) 104 | 105 | -------------------------------------------------------------------------------- /gateways/sshnokey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # This file is a part of RackTables, a datacenter and server room management 3 | # framework. See accompanying file "COPYING" for the full copyright and 4 | # licensing information. 5 | # 6 | # NOTE: Logging in via ssh using a password, whilst better then doing 7 | # the same via telnet/netcat, is still a bad idea when your network is 8 | # not properly secured. If you try to login to a compromised system 9 | # using a password, this password is now in the hands of the attackers. 10 | # 11 | # If possible, use the public key authenticated version instead. In case 12 | # that is not an option, consider different passwords for every system. 13 | # 14 | # To summarize, treat this as a slightly better telnet client and make 15 | # sure the network this runs in is secure. 16 | 17 | use strict; 18 | use Getopt::Long; 19 | use Net::Telnet; 20 | use Net::OpenSSH; 21 | 22 | # fetch command-line parameters 23 | my $op_help; 24 | my $op_port; 25 | my $op_username; 26 | my $op_password; 27 | my $op_connect_timeout = 2; 28 | my $op_timeout = 10; 29 | my $op_prompt; 30 | my $op_delay = 0.01; 31 | GetOptions ( 32 | 'h' => \$op_help, 33 | 'port:i' => \$op_port, 34 | 'connect-timeout:i' => \$op_connect_timeout, 35 | 'timeout:i' => \$op_timeout, 36 | 'prompt-delay:f' => \$op_delay, 37 | 'prompt:s' => \$op_prompt, 38 | 'username:s' => \$op_username, 39 | 'password:s' => \$op_password 40 | ); 41 | if ($op_help) { 42 | &display_help; 43 | exit; 44 | } 45 | my $op_host = $ARGV[0]; 46 | defined $op_host or die "ERROR: please specify remote host (-h for help)"; 47 | defined $op_prompt or die "ERROR: please specify prompt regexp (-h for help)"; 48 | my $prompt_re = qr/$op_prompt/; 49 | 50 | sub display_help { 51 | print <new( 70 | $op_host, 71 | 'port' => $op_port, 72 | 'user' => $op_username, 73 | 'password' => $op_password 74 | ); 75 | $ssh->error and 76 | die "Couldn't establish SSH connection: ". $ssh->error; 77 | 78 | my ($pty, $pid) = $ssh->open2pty({stderr_to_stdout => 1}) 79 | or die "unable to start remote shell: " . $ssh->error; 80 | 81 | my $session = Net::Telnet->new ( 82 | Fhopen => $pty, 83 | # Host => $op_host, 84 | # Port => $port, 85 | # Timeout => $op_connect_timeout, 86 | Prompt => "/$op_prompt/", 87 | Telnetmode => 0, 88 | Cmd_remove_mode => 1, 89 | Output_record_separator => "\r" 90 | ); 91 | 92 | #$session->cmd("term len 0"); 93 | 94 | 95 | use IO::Select; 96 | my $sel = new IO::Select($session); 97 | 98 | my $buff = ''; 99 | my $nohang_read; 100 | until ($session->eof) { 101 | # read output from the device 102 | eval { 103 | $buff .= $session->get (Timeout => $nohang_read ? 0 : $op_timeout, Errmode => $nohang_read ? 'return' : 'die'); 104 | }; 105 | if ($@) { 106 | # check if there is something else in 107 | if (defined ) { 108 | die $@; 109 | } 110 | else { 111 | last; # no more input, seems like session was closed remotely by our last command 112 | } 113 | } 114 | $nohang_read = 0; 115 | print $1 if ($buff =~ s/(.*\n)//s); 116 | 117 | next unless ($buff =~ $prompt_re); 118 | # send pending commands to the device 119 | if ($op_delay and IO::Select->select ($sel, undef, undef, $op_delay)) { 120 | # something is received, no prompt detection at this time 121 | # set NOHANG options for next reading, cause it can be telnet control sequence 122 | $nohang_read = 1; 123 | } 124 | elsif (defined ($_ = )) { 125 | # replace all CR and LF symbols with single trailing LF 126 | s/[\015\012]//g; 127 | $session->put($_ . "\012"); 128 | } 129 | else { 130 | # no more commands in input 131 | last; 132 | } 133 | } 134 | print $buff; 135 | -------------------------------------------------------------------------------- /wwwroot/js/inplace-edit.js: -------------------------------------------------------------------------------- 1 | (function ($) { //unnamed singletone class 2 | 3 | var editMode = false; 4 | var visible_pen = $(); 5 | var stop_propagation = false; 6 | var waiting_response = false; 7 | var editable_filter = 'span.editable'; 8 | 9 | var span = null; 10 | var group = null; 11 | var input = null; 12 | var btn = null; 13 | 14 | $(document).ready (function() { 15 | $(editable_filter).not('.initdone').each (function (i, iSpan) { 16 | var container = $('

') 17 | .mouseover(onSpanMouseOver); 18 | $(iSpan) 19 | .after (container) 20 | .detach() 21 | .addClass('initdone') 22 | .appendTo (container); 23 | container 24 | .append 25 | ( 26 | $('
') 27 | .click(onPencilClick) 28 | ); 29 | }); 30 | $(document).mouseover(onBodyMouseOver); 31 | }); 32 | 33 | function onSpanMouseOver (event) { 34 | if (editMode) 35 | return; 36 | stop_propagation = true; 37 | var pen = $(event.target).closest('.edit-container').find('.edit-btn'); 38 | if (! visible_pen.length || visible_pen[0] != pen[0]) { 39 | visible_pen.hide(); 40 | visible_pen = pen; 41 | visible_pen.show(); 42 | } 43 | } 44 | 45 | function onBodyMouseOver () { 46 | if (!editMode && !stop_propagation) { 47 | visible_pen.hide(); 48 | visible_pen = $(); 49 | } 50 | stop_propagation = false; 51 | } 52 | 53 | function hideEditForm () { 54 | input = null; 55 | btn = null; 56 | group.remove(); 57 | span.show(); 58 | editMode = false; 59 | }; 60 | 61 | function onPencilClick (event) { 62 | // hide original plain text comment 63 | span = $(event.target).closest('.edit-container').find(editable_filter); 64 | var width = span[0].offsetWidth + 50; 65 | if (width < 150) 66 | width = 150; 67 | span.hide(); 68 | 69 | // hide pencil 70 | onBodyMouseOver(); 71 | editMode = true; 72 | 73 | // construct editor form 74 | group = $(''); 75 | input = $('') 76 | .val(span.html().replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')) 77 | .css('width', '' + width + 'px') 78 | .keydown( 79 | function (event) { 80 | var code = event.keyCode ? event.keyCode : event.which; 81 | if (code == 13) { 82 | onFormSubmit(); 83 | return false; 84 | } 85 | else if (code == 27) 86 | hideEditForm(); 87 | }) 88 | .appendTo(group); 89 | group.append(' '); 90 | btn = $('') 91 | .css('cursor', 'pointer') 92 | .click( onFormSubmit ) 93 | .appendTo(group); 94 | span.after(group); 95 | input[0].focus(); 96 | doSetCaretPosition (input[0], input[0].value.length); 97 | 98 | group.click(function(event) { event.stopPropagation(); }); 99 | $(document).one('click', 100 | function (event) { 101 | if (! waiting_response) 102 | hideEditForm(); 103 | onSpanMouseOver(event); 104 | }); 105 | event.stopPropagation(); // prevent the initial click to immediately close edit form 106 | } 107 | 108 | function doSetCaretPosition (input, iCaretPos) { 109 | if (input.setSelectionRange) { 110 | input.setSelectionRange(iCaretPos, iCaretPos); 111 | } 112 | else if (input.createTextRange) { 113 | var range = input.createTextRange(); 114 | range.moveEnd("character", iCaretPos); 115 | range.moveStart("character", iCaretPos); 116 | range.select(); 117 | } 118 | } 119 | 120 | function onFormSubmit () { 121 | var text = input.val(); 122 | input.attr('disabled', 'true'); 123 | btn.replaceWith(''); 124 | waiting_response = true; 125 | 126 | var data = { 127 | 'module': 'ajax', 128 | 'text': text 129 | }; 130 | var list = span[0].className.split (/\s+/); 131 | for (var i in list) { 132 | var cn = list[i]; 133 | var m; 134 | if (m = cn.match (/^(.+?)-(.*)/)) { 135 | data[m[1]] = m[2]; 136 | } 137 | } 138 | if (! ('ac' in data)) 139 | data['ac'] = data['op']; 140 | 141 | $.ajax({ 142 | type: 'POST', 143 | url: 'index.php', 144 | data: data, 145 | success: function(data, textStatus, XMLHttpRequest) { 146 | if (data == 'OK') 147 | span.html(text); 148 | else 149 | alert ('Error updating port: ' + data); 150 | }, 151 | error: function(jqXHR, textStatus, errorThrown) { 152 | alert ('Error updating port: ' + textStatus); 153 | }, 154 | complete: function() { 155 | hideEditForm(); 156 | waiting_response = false; 157 | } 158 | }); 159 | } 160 | 161 | })(jQuery); 162 | -------------------------------------------------------------------------------- /wwwroot/js/jquery.thumbhover.js: -------------------------------------------------------------------------------- 1 | // This library is based on jquery.thumbhover.js from unknown author. 2 | // Far and away modified for using in RackTables. 3 | // Usage: jquery_object_a.thumbPopup(jquery_object_b, [options]) 4 | // after that call, object_b will be hidden 5 | // object_a, when hovered, will show object_b floating and moving by the cursor. 6 | // When clicked on object_a, object_b will stay visible until outside click 7 | (function($) { 8 | $.fn.thumbPopup = function(popup, options) 9 | { 10 | //Combine the passed in options with the default settings 11 | var settings = jQuery.extend({ 12 | //popupId: "thumbPopup", 13 | cursorTopOffset: 15, 14 | cursorLeftOffset: 15, 15 | event: null, // if set, the popup will be displayed immediately, and no mouse handlers will be binded to target 16 | showFreezeHint: true 17 | }, options); 18 | 19 | var freezeHint = null; 20 | var timeout_id = null; 21 | var hintHeight = 0; 22 | if (! freezeHint && settings.showFreezeHint && settings.event == null) { 23 | freezeHint = $('
').html('click to freeze').css('position', 'absolute').css('border', '1px solid black').css('background-color', 'white').appendTo('body'); 24 | hintHeight = freezeHint[0].offsetHeight; 25 | freezeHint.hide(); 26 | } 27 | 28 | if (! popup.length) 29 | return false; 30 | popup.css("position", "absolute").hide(); 31 | $(this).css("cursor", "pointer"); 32 | 33 | //Attach hover events that manage the popup 34 | if (settings.event != null) 35 | { 36 | setPopup (settings.event); 37 | stickPopup (settings.event); 38 | } 39 | else { 40 | $(this) 41 | .bind('mouseenter', setPopup) 42 | .bind('mousemove', updatePopupPosition) 43 | .bind('mouseleave', hidePopup) 44 | .click(stickPopup); 45 | } 46 | 47 | function stickPopup(event) { 48 | popup.data("sticked", true); 49 | if (freezeHint) 50 | freezeHint.hide(); 51 | $('body').bind('click', function(event) { 52 | if (! (event.target == popup[0] || $(event.target).parents().filter(popup).length)) 53 | { 54 | popup.data("sticked", false); 55 | hidePopup (event); 56 | } 57 | return true; 58 | }); 59 | return false; 60 | } 61 | 62 | function ShowFreezeHint() { 63 | freezeHint.show(); 64 | } 65 | 66 | function setPopup(event) { 67 | if (popup.data("sticked")) 68 | return; 69 | popup.data("hovered", true); 70 | updatePopupPosition(event); 71 | $(popup).show(); 72 | } 73 | 74 | function updatePopupPosition(event) { 75 | var windowSize = getWindowSize(); 76 | var popupSize = getPopupSize(); 77 | var bPopupShownAbove = windowSize.height + windowSize.scrollTop < event.pageY + popupSize.height + settings.cursorTopOffset; 78 | if (freezeHint) { 79 | var deltaHint = bPopupShownAbove ? 20 : - 5 - hintHeight; 80 | freezeHint.hide(); 81 | freezeHint.css('top', event.pageY + deltaHint).css('left', event.pageX); 82 | clearTimeout(timeout_id); 83 | timeout_id = setTimeout(ShowFreezeHint, 1000); 84 | } 85 | if (popup.data("sticked")) 86 | return; 87 | var left; 88 | if (windowSize.width + windowSize.scrollLeft < event.pageX + popupSize.width + settings.cursorLeftOffset){ 89 | left = event.pageX - popupSize.width - settings.cursorLeftOffset; 90 | } else { 91 | left = event.pageX + settings.cursorLeftOffset; 92 | } 93 | // center pop-up if it does not fit entirely into window 94 | if ( 95 | left < windowSize.scrollLeft || 96 | left + popupSize.width > windowSize.scrollLeft + windowSize.width 97 | ) { 98 | left = (windowSize.width - popupSize.width) / 2; 99 | } 100 | $(popup).css("left", left); 101 | 102 | if (bPopupShownAbove) { 103 | $(popup).css("top", event.pageY - popupSize.height - settings.cursorTopOffset); 104 | } else { 105 | $(popup).css("top", event.pageY + settings.cursorTopOffset); 106 | } 107 | } 108 | 109 | function hidePopup(event) { 110 | popup.data("hovered", false); 111 | if (freezeHint) { 112 | freezeHint.hide(); 113 | clearTimeout(timeout_id); 114 | } 115 | if (popup.data("sticked")) 116 | return; 117 | $(popup).hide(); 118 | if (settings.event != null) 119 | $(popup).remove(); 120 | } 121 | 122 | function getWindowSize() { 123 | return { 124 | scrollLeft: $(window).scrollLeft(), 125 | scrollTop: $(window).scrollTop(), 126 | width: $(window).width(), 127 | height: $(window).height() 128 | }; 129 | } 130 | 131 | function getPopupSize() { 132 | return { 133 | width: $(popup).width(), 134 | height: $(popup).height() 135 | }; 136 | } 137 | 138 | //Return original selection for chaining 139 | return this; 140 | }; 141 | })(jQuery); 142 | -------------------------------------------------------------------------------- /wwwroot/inc/pre-init.php: -------------------------------------------------------------------------------- 1 | PDO::ERRMODE_EXCEPTION, 67 | // Cancel one specific SQL mode option that RackTables has been non-compliant 68 | // with, but which used to be off by default until MySQL 5.7. As soon as 69 | // respective SQL queries and table columns become compliant with those options 70 | // stop changing @@SQL_MODE but still keep SET NAMES in place. 71 | // RackTables requires the strict SQL mode, which is not enabled by default 72 | // in MariaDB <= 10.2.3. 73 | PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8", @@SQL_MODE = CONCAT("STRICT_ALL_TABLES,", REPLACE(@@SQL_MODE, "NO_ZERO_DATE", ""))', 74 | ); 75 | if (isset ($pdo_bufsize)) 76 | $drvoptions[PDO::MYSQL_ATTR_MAX_BUFFER_SIZE] = $pdo_bufsize; 77 | if (isset ($pdo_ssl_key)) 78 | $drvoptions[PDO::MYSQL_ATTR_SSL_KEY] = $pdo_ssl_key; 79 | if (isset ($pdo_ssl_cert)) 80 | $drvoptions[PDO::MYSQL_ATTR_SSL_CERT] = $pdo_ssl_cert; 81 | if (isset ($pdo_ssl_ca)) 82 | $drvoptions[PDO::MYSQL_ATTR_SSL_CA] = $pdo_ssl_ca; 83 | try 84 | { 85 | $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password, $drvoptions); 86 | } 87 | catch (PDOException $e) 88 | { 89 | throw new RackTablesError ("Database connection failed:\n\n" . $e->getMessage(), RackTablesError::INTERNAL); 90 | } 91 | } 92 | 93 | // tries to guess the existence of the file before the php's include using the same searching method. 94 | // in addition to calling file_exists, searches the current file's directory if the path is not looks 95 | // like neither absolute nor relative. 96 | function fileSearchExists ($filename) 97 | { 98 | if (! preg_match ('@^(\.+)?/@', $filename)) 99 | { 100 | $this_file_dir = dirname (__FILE__); 101 | if (file_exists ($this_file_dir . '/' . $filename)) 102 | return TRUE; 103 | } 104 | return file_exists ($filename); 105 | } 106 | -------------------------------------------------------------------------------- /wwwroot/js/live_validation.js: -------------------------------------------------------------------------------- 1 | // This file has been downloaded from the following URL: 2 | // http://www.openjs.com/scripts/forms/live_validation/ 3 | // (Live Validator 1.00.A Beta) 4 | // It was declared as released under BSD license at that moment. 5 | // The content below is a verbatim copy. 6 | 7 | var Validate = { 8 | elements:[], 9 | //Some General purpose functions 10 | hasClass:function(ele,cls) { 11 | return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); 12 | }, 13 | addClass:function (ele,cls) { 14 | if (!this.hasClass(ele,cls)) ele.className += " "+cls; 15 | }, 16 | removeClass:function (ele,cls) { 17 | if (this.hasClass(ele,cls)) { 18 | var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); 19 | ele.className=ele.className.replace(reg,' '); 20 | } 21 | }, 22 | stopEvent:function(e) { 23 | //e.cancelBubble is supported by IE - this will kill the bubbling process. 24 | e.cancelBubble = true; 25 | e.returnValue = false; 26 | //e.stopPropagation works in Mozilla. 27 | if (e.stopPropagation) { 28 | e.stopPropagation(); 29 | e.preventDefault(); 30 | } 31 | }, 32 | success:function(ele) { 33 | this.removeClass(ele,"validation-error"); 34 | this.addClass(ele,"validation-success"); 35 | }, 36 | failure:function(ele) { 37 | this.removeClass(ele,"validation-success"); 38 | this.addClass(ele,"validation-error"); 39 | }, 40 | //Logic starts here... 41 | //Deny keyboard input for some specific chars. 42 | validateKeys : function(e,ele) { 43 | //Find Which key is pressed 44 | if (e.keyCode) code = e.keyCode; 45 | else if (e.which) code = e.which; 46 | var character = String.fromCharCode(code); 47 | 48 | //We need only valid keypresses - not stuff like shift, Enter, Backspace etc. 49 | if( e.ctrlKey || 50 | code == 46 //Delete Key 51 | ) return; 52 | if(e.shiftKey) { 53 | if(!(code >= 37 && code <= 40)) return; //Up,Down,Right and Left - same keycode as %,&,' and ( 54 | } else { 55 | if(!(code >= 41 && code <= 126)) return; 56 | } 57 | 58 | if(ele.getAttribute("allowedkeys")) { 59 | var allowed_chars = new RegExp(ele.getAttribute("allowedkeys")); 60 | if(!allowed_chars.test(character)) { //If a character was entered that is not allowed. 61 | this.stopEvent(e); 62 | } 63 | } 64 | }, 65 | //See if the match is made - this is called on every keyup event. 66 | testMatch : function(ele) { 67 | if(ele.getAttribute("match")) { 68 | var match_reg = new RegExp(ele.getAttribute("match")); 69 | if(match_reg.test(ele.value)) this.success(ele); 70 | else { 71 | this.failure(ele); 72 | return false;//Don't continue if it is a faluire 73 | } 74 | } 75 | if(ele.getAttribute("equals")) { 76 | if(ele.value == eval(ele.getAttribute("equals"))) this.success(ele);//Yes I know, 'evil eval'. 77 | else { 78 | this.failure(ele); 79 | return false; 80 | } 81 | } 82 | if(ele.getAttribute("istrue")) { 83 | if(eval(ele.getAttribute("istrue"))) this.success(ele);//Again, eval. 84 | else { 85 | this.failure(ele); 86 | return false; 87 | } 88 | } 89 | return true; 90 | }, 91 | //Show error message on form submission 92 | attachForm : function(form_id) { 93 | var ths = this;//Closure 94 | $(form_id).onsubmit=function(e) { 95 | if(!e) var e = window.event; 96 | var ele = this; 97 | var err = 0; 98 | for(var i=0,len=ths.elements.length; i\n"; 15 | echo "Options:\n"; 16 | echo "\t\t--vdid=\n"; 17 | echo "\t\t--mode=pull\n"; 18 | echo "\t\t--mode=pullall\n"; 19 | echo "\t\t--mode=push\n"; 20 | echo "\t\t[--max=]\n"; 21 | echo "\t\t[--verbose]\n"; 22 | echo "\t\t[--nolock]\n"; 23 | echo "\t\t[--stderr]\n"; 24 | echo "\t\t--help\n"; 25 | exit ($rc); 26 | } 27 | 28 | define ('PML_VERBOSE', 1 << 0); // display message only if --verbose option specified 29 | define ('PML_NOTICE', 1 << 1); // the message is informational, do not write to STDERR 30 | function print_message_line($text, $flags = 0) 31 | { 32 | global $options; 33 | if (! array_key_exists ('verbose', $options) and $flags & PML_VERBOSE) 34 | return; 35 | $buff = date (DATE_RFC1123) . ": ${text}\n"; 36 | echo $buff; 37 | if (array_key_exists ('stderr', $options) and ! ($flags & PML_NOTICE)) 38 | fwrite (STDERR, $buff); 39 | } 40 | 41 | $options = getopt ('', array ('vdid:', 'max::', 'mode:', 'verbose', 'nolock', 'stderr', 'help')); 42 | if (array_key_exists ('help', $options)) 43 | usage (0); 44 | if (!array_key_exists ('mode', $options)) 45 | usage (1); 46 | 47 | switch ($options['mode']) 48 | { 49 | case 'pullall': 50 | $do_push = FALSE; 51 | break; 52 | case 'pull': 53 | $do_push = FALSE; 54 | break; 55 | case 'push': 56 | $do_push = TRUE; 57 | break; 58 | default: 59 | usage (1); 60 | } 61 | 62 | $max = array_fetch ($options, 'max', 0); 63 | $nolock = array_key_exists ('nolock', $options); 64 | 65 | $todo = array 66 | ( 67 | 'pull' => array ('sync_ready', 'resync_ready'), 68 | 'push' => array ('sync_ready', 'resync_ready'), 69 | 'pullall' => array ('sync_ready', 'resync_ready', 'sync_aging', 'resync_aging', 'done'), 70 | ); 71 | 72 | if (! $nolock) 73 | { 74 | $domain_key = isset ($options['vdid']) ? $options['vdid'] : 0; 75 | $filename = '/var/tmp/RackTables-syncdomain-' . $domain_key . '.pid'; 76 | if (FALSE === $fp = @fopen ($filename, 'c+')) 77 | { 78 | print_message_line ("Failed to open ${filename}"); 79 | exit (1); 80 | } 81 | $wouldblock = 0; 82 | if (! flock ($fp, LOCK_EX|LOCK_NB, $wouldblock) || $wouldblock) 83 | { 84 | $current_time = time(); 85 | $stat = fstat ($fp); 86 | if (! isset ($stat['mtime'])) 87 | { 88 | print_message_line ("Failed to obtain mtime of ${filename}"); 89 | exit (1); 90 | } 91 | $pidfile_mtime = $stat['mtime']; 92 | if ($current_time < $pidfile_mtime) 93 | { 94 | print_message_line ("Warning: pidfile ${filename} mtime is in future!"); 95 | exit (1); 96 | } 97 | // don't indicate failure unless the pidfile is 15 minutes or more old 98 | if ($current_time < $pidfile_mtime + 15 * 60) 99 | exit (0); 100 | print_message_line ("Failed to lock ${filename}, already locked by PID " . trim (fgets ($fp, 10))); 101 | exit (1); 102 | } 103 | 104 | ftruncate ($fp, 0); 105 | fwrite ($fp, getmypid() . "\n"); 106 | // don't close $fp yet: we need to keep an flock 107 | } 108 | 109 | // fetch all the needed data from DB (preparing for DB connection loss) 110 | $vswitch_filter = array(); 111 | if (isset ($options['vdid'])) 112 | $vswitch_filter['domain_id'] = $options['vdid']; 113 | $switch_list = getVLANSwitchInfoRows ($vswitch_filter); 114 | $enabled_switches = listConstraint ('object', 'SYNC_8021Q_LISTSRC'); 115 | 116 | $switch_queue = array(); 117 | foreach ($switch_list as $vswitch) 118 | { 119 | $object_id = $vswitch['object_id']; 120 | $new_disabled = ! isset ($enabled_switches[$object_id]); 121 | $queue = detectVLANSwitchQueue ($vswitch); 122 | if ($queue != 'disabled' && $new_disabled) 123 | { 124 | setVLANSwitchError ($object_id, E_8021Q_SYNC_DISABLED); 125 | continue; 126 | } 127 | elseif ($queue == 'disabled' && ! $new_disabled) 128 | { 129 | $vswitch['last_errno'] = E_8021Q_NOERROR; 130 | setVLANSwitchError ($object_id, $vswitch['last_errno']); 131 | $queue = detectVLANSwitchQueue ($vswitch); 132 | } 133 | 134 | if (in_array ($queue, $todo[$options['mode']])) 135 | $switch_queue[] = spotEntity ('object', $object_id); 136 | } 137 | 138 | // YOU SHOULD NOT USE DB FUNCTIONS BELOW IN THE PARENT PROCESS 139 | // THE PARENT'S DB CONNECTION IS LOST DUE TO RECONNECTING IN THE CHILD 140 | $fork_slots = getConfigVar ('SYNCDOMAIN_MAX_PROCESSES'); 141 | $do_fork = ($fork_slots > 1) and extension_loaded ('pcntl'); 142 | if ($fork_slots > 1 and ! $do_fork) 143 | throw new RackTablesError ('PHP extension \'pcntl\' not found, can not use childs', RackTablesError::MISCONFIGURED); 144 | $switches_working = 0; 145 | $switchesdone = 0; 146 | foreach ($switch_queue as $object) 147 | { 148 | if ($do_fork) 149 | { 150 | // wait for the next free slot 151 | while ($fork_slots <= $switches_working) 152 | { 153 | pcntl_waitpid (-1, $wait_status); 154 | --$switches_working; 155 | } 156 | $i_am_child = (0 === $fork_res = pcntl_fork()); 157 | } 158 | if (! $do_fork || $i_am_child) 159 | { 160 | try 161 | { 162 | // make a separate DB connection for correct concurrent transactions handling 163 | if ($i_am_child) 164 | connectDB(); 165 | $portsdone = exec8021QDeploy ($object['id'], $do_push); 166 | $flags = PML_NOTICE; 167 | if (! $portsdone) 168 | $flags |= PML_VERBOSE; 169 | print_message_line ("Done '${object['dname']}': ${portsdone}", $flags); 170 | } 171 | catch (RackTablesError $e) 172 | { 173 | print_message_line ("FAILED '${object['dname']}': " . $e->getMessage()); 174 | } 175 | if ($i_am_child) 176 | exit (0); 177 | } 178 | if (isset ($fork_res) and $fork_res > 0) 179 | ++$switches_working; 180 | 181 | if (++$switchesdone == $max) 182 | { 183 | print_message_line ("Maximum of ${max} items reached, terminating", PML_NOTICE|PML_VERBOSE); 184 | break; 185 | } 186 | } 187 | 188 | // wait for all childs to exit 189 | while ($switches_working > 0) 190 | { 191 | --$switches_working; 192 | pcntl_waitpid (-1, $wait_status); 193 | } 194 | 195 | if (! $nolock) 196 | { 197 | flock ($fp, LOCK_UN); // explicitly unlock file as PHP 5.3.2 made it mandatory 198 | if (FALSE === unlink ($filename)) 199 | { 200 | print_message_line ("Failed removing pidfile ${filename}"); 201 | exit (1); 202 | } 203 | } 204 | exit (0); 205 | -------------------------------------------------------------------------------- /wwwroot/inc/init.php: -------------------------------------------------------------------------------- 1 | ${path_to_secret_php}).
" . 35 | "The configuration file is usually generated by RackTables installer, which " . 36 | "can be launched here.", 37 | RackTablesError::MISCONFIGURED 38 | ); 39 | 40 | connectDB(); 41 | transformRequestData(); 42 | $configCache = loadConfigDefaults(); 43 | 44 | if (getConfigVar ('DB_VERSION') != CODE_VERSION) 45 | { 46 | echo '

This Racktables installation seems to be ' . 47 | 'just upgraded to version ' . CODE_VERSION . ', while the '. 48 | 'database version is ' . getConfigVar ('DB_VERSION') . '.
No user will be ' . 49 | 'either authenticated or shown any page until the upgrade is ' . 50 | "finished.
Follow this link and " . 51 | 'authenticate as administrator to finish the upgrade.

'; 52 | exit (1); 53 | } 54 | 55 | if (!mb_internal_encoding ('UTF-8')) 56 | throw new RackTablesError ('Failed setting multibyte string encoding to UTF-8', RackTablesError::INTERNAL); 57 | 58 | $rackCodeCache = loadScript ('RackCodeCache'); 59 | if ($rackCodeCache == NULL || $rackCodeCache == '') 60 | { 61 | $rackCode = getRackCode (loadScript ('RackCode')); 62 | saveScript ('RackCodeCache', base64_encode (serialize ($rackCode))); 63 | } 64 | else 65 | { 66 | $rackCode = unserialize (base64_decode ($rackCodeCache)); 67 | if ($rackCode === FALSE) // invalid cache 68 | { 69 | saveScript ('RackCodeCache', ''); 70 | $rackCode = getRackCode (loadScript ('RackCode')); 71 | } 72 | elseif (! isset ($rackCode['ABI_ver']) || $rackCode['ABI_ver'] != PARSER_ABI_VER) 73 | { 74 | // Re-calculate rackCode locally, keep unsupported cache in place. 75 | // This helps transition between version on master-slave installations. 76 | $rackCode = getRackCode (loadScript ('RackCode')); 77 | } 78 | } 79 | 80 | // avoid notices being thrown 81 | date_default_timezone_set (getConfigVar ('DATETIME_ZONE')); 82 | 83 | // Depending on the 'result' value the 'load' carries either the 84 | // parse tree or error message. The latter case is a bug, because 85 | // RackCode saving function was supposed to validate its input. 86 | if ($rackCode['result'] != 'ACK') 87 | throw new RackTablesError ($rackCode['load'], RackTablesError::INTERNAL); 88 | $rackCode = $rackCode['load']; 89 | // Only call buildPredicateTable() once and save the result, because it will remain 90 | // constant during one execution for constraints processing. 91 | $pTable = buildPredicateTable ($rackCode); 92 | // Constraints parse trees aren't cached in the database, so the least to keep 93 | // things running is to maintain application cache for them. 94 | $entityCache = array(); 95 | // used by getExplicitTagsOnly() 96 | $tagRelCache = array(); 97 | 98 | $taglist = addTraceToNodes (getTagList()); 99 | 100 | $auto_tags = array(); 101 | if (! isCLIMode() && isset ($_SERVER['REMOTE_ADDR'])) 102 | $auto_tags[] = array ('tag' => '$client_' . $_SERVER['REMOTE_ADDR']); 103 | 104 | // Initial chain for the current user. 105 | $user_given_tags = array(); 106 | 107 | // List of additional regexps for checkAutotagName(). Add your site-local regexps 108 | // here to manage false positive 'Martian autotag' warnings about the permissions 109 | // text that uses autotags generated by local plugins. 110 | $user_defined_atags = array(); 111 | 112 | // Initial the HTML header array used by addJSxxx() and addCSSxxx() functions 113 | // FIXME: For some reason without this global declaration this variable does 114 | // not exist for addPageHeader() in PHPUnit. 115 | global $html_headers; 116 | $html_headers = array(); 117 | 118 | // This also can be modified in local.php. 119 | $pageheaders = array 120 | ( 121 | 100 => "", 122 | ); 123 | addCSSInternal ('css/pi.css'); 124 | 125 | if (! isset ($script_mode) || $script_mode !== TRUE) 126 | { 127 | // A successful call to authenticate() always generates autotags and somethimes 128 | // even given/implicit tags. It also sets remote_username and remote_displayname. 129 | authenticate(); 130 | // Authentication passed. 131 | // Note that authorization does not happen here as every CLI script, HTTP module and 132 | // page does it differently, e.g. by calling authorize() after fixContext(). 133 | } 134 | elseif (! isset ($remote_username)) 135 | { 136 | // Some functions require remote_username to be set to something to act correctly, 137 | // even though they don't use the value itself. 138 | $admin_account = spotEntity ('user', 1); 139 | if (isCLIMode() && FALSE !== $env_user = getenv('USER')) 140 | // use USER env var if running in CLI mode 141 | $remote_username = $env_user; 142 | else 143 | $remote_username = $admin_account['user_name']; 144 | unset ($env_user); 145 | unset ($admin_account); 146 | } 147 | 148 | $virtual_obj_types = explode (',', getConfigVar ('VIRTUAL_OBJ_CSV')); 149 | 150 | alterConfigWithUserPreferences(); 151 | $op = ''; 152 | 153 | // load v1 plugins 154 | ob_start(); 155 | if (FALSE !== $plugin_files = glob ("${racktables_plugins_dir}/*.php")) 156 | foreach ($plugin_files as $plugin_file) 157 | require_once $plugin_file; 158 | // display plugins output if it contains something but newlines 159 | $tmp = ob_get_clean(); 160 | if ($tmp != '' && ! preg_match ("/^\n+$/D", $tmp)) 161 | echo $tmp; 162 | unset ($tmp); 163 | 164 | // load v2 plugins that are enabled 165 | $plugins = getPlugins ('enabled'); 166 | foreach (array_keys ($plugins) as $plugin) 167 | if (function_exists ("plugin_${plugin}_init")) 168 | call_user_func ("plugin_${plugin}_init"); 169 | 170 | // These will be filled in by fixContext() 171 | $expl_tags = array(); 172 | $impl_tags = array(); 173 | // Initial chain for the current target. 174 | $target_given_tags = array(); 175 | 176 | // Now we've finished let plugins know 177 | callHook ('initFinished'); 178 | -------------------------------------------------------------------------------- /wwwroot/css/jquery.contextmenu.css: -------------------------------------------------------------------------------- 1 | /* Classic Windows Theme (default) */ 2 | /* =============================== */ 3 | .context-menu-theme-default { 4 | border:2px outset white; 5 | background-color:#D4D0C8; 6 | } 7 | .context-menu-theme-default .context-menu-item { 8 | text-align:left; 9 | cursor:pointer; 10 | padding:4px 28px 4px 16px; 11 | color:black; 12 | font-family:Tahoma,Arial; 13 | font-size:11px; 14 | } 15 | .context-menu-theme-default .context-menu-separator { 16 | margin:4px 2px; 17 | font-size:0px; 18 | border-top:1px solid #808080; 19 | border-bottom:1px solid white; 20 | } 21 | .context-menu-theme-default .context-menu-item-disabled { 22 | color:#808080; 23 | } 24 | .context-menu-theme-default .context-menu-item .context-menu-item-inner { 25 | background:none no-repeat fixed 999px 999px; /* Make sure icons don't appear */ 26 | } 27 | .context-menu-theme-default .context-menu-item-hover { 28 | background-color:#0A246A; 29 | color:white; 30 | } 31 | .context-menu-theme-default .context-menu-item-disabled-hover { 32 | background-color:#0A246A; 33 | } 34 | 35 | /* Windows XP Theme */ 36 | /* ================ */ 37 | .context-menu-theme-xp { 38 | border:1px solid #666; 39 | padding:1px; 40 | background:#F9F8F7 repeat-y top left; 41 | } 42 | .context-menu-theme-xp .context-menu-separator { 43 | margin:4px 2px; 44 | font-size:0px; 45 | border-top:1px solid #808080; 46 | border-bottom:1px solid white; 47 | } 48 | .context-menu-theme-xp .context-menu-item { 49 | text-align:left; 50 | color:black; 51 | font-family:arial; 52 | font-size:11px; 53 | cursor:pointer; 54 | } 55 | .context-menu-theme-xp .context-menu-item .context-menu-item-inner { 56 | background:none no-repeat 2px center; 57 | padding:4px 10px 4px 30px; 58 | } 59 | .context-menu-theme-xp .context-menu-item-hover .context-menu-item-inner { 60 | background:#B6BDD2 none no-repeat 2px center; 61 | padding:3px 9px 3px 29px; 62 | border:1px solid #0A246A; 63 | } 64 | 65 | /* Windows Vista Theme */ 66 | /* =================== */ 67 | .context-menu-theme-vista { 68 | background:#FAFAFA repeat-y left top; 69 | border:1px solid #868686; 70 | } 71 | .context-menu-theme-vista .context-menu-item { 72 | text-align:left; 73 | cursor:pointer; 74 | color:black; 75 | font-family:Tahoma,Arial; 76 | font-size:11px; 77 | } 78 | .context-menu-theme-vista .context-menu-separator { 79 | margin:0px 0px 0px 32px; 80 | font-size:0px; 81 | border-top:1px solid #C5C5C5; 82 | border-bottom:1px solid #F5F5F5; 83 | } 84 | .context-menu-theme-vista .context-menu-item-hover { 85 | background:transparent repeat-x left center; 86 | border:1px solid #D7D0B3; 87 | } 88 | .context-menu-theme-vista .context-menu-item .context-menu-item-inner { 89 | padding:4px 16px 4px 35px; 90 | margin-left:1px; 91 | background-color:none; 92 | background-repeat:no-repeat; 93 | background-position:3px center; 94 | background-image:none; 95 | } 96 | .context-menu-theme-vista .context-menu-item-hover .context-menu-item-inner { 97 | padding:3px 15px 3px 35px; 98 | margin-left:0px; 99 | } 100 | .context-menu-theme-vista .context-menu-item-disabled { 101 | color:#A7A7A7; 102 | } 103 | 104 | /* OSX Theme */ 105 | /* ========= */ 106 | .context-menu-theme-osx { 107 | background-color:white; 108 | opacity: .93; 109 | filter: alpha(opacity=93); 110 | zoom:1.0; 111 | border:1px solid #b2b2b2; 112 | } 113 | .context-menu-theme-osx .context-menu-item { 114 | text-align:left; 115 | cursor:pointer; 116 | color:black; 117 | font-family:Lucida Grande,Arial; 118 | font-weight:700; 119 | font-size:12px; 120 | opacity: 1.0; 121 | filter: alpha(opacity=100); 122 | z-index:1; 123 | } 124 | .context-menu-theme-osx .context-menu-separator { 125 | margin:5px 1px 4px 1px; 126 | font-size:0px; 127 | border-top:1px solid #e4e4e4; 128 | } 129 | .context-menu-theme-osx .context-menu-item-hover { 130 | background-color:#1C44F2; 131 | color:white; 132 | } 133 | .context-menu-theme-osx .context-menu-item .context-menu-item-inner { 134 | padding:2px 10px 2px 22px; 135 | background-color:none; 136 | background-repeat:no-repeat; 137 | background-position:4px center; 138 | background-image:none; 139 | } 140 | .context-menu-theme-osx .context-menu-item-disabled { 141 | color:#939393; 142 | } 143 | 144 | /* Linux Human Theme */ 145 | /* ================= */ 146 | .context-menu-theme-human { 147 | background:#F9F5F2; 148 | border:1px solid #963; 149 | } 150 | .context-menu-theme-human .context-menu-item { 151 | text-align:left; 152 | cursor:pointer; 153 | color:black; 154 | font-family:Helvetica,DejaVu Sans,Arial; 155 | font-size:12px; 156 | line-height:20px; 157 | height:28px; 158 | border:1px solid #F9F5F2; 159 | border-left:0; 160 | border-right:0; 161 | } 162 | .context-menu-theme-human .context-menu-separator { 163 | margin:0px 0px 0px 32px; 164 | font-size:0px; 165 | border-top:1px solid #C5C5C5; 166 | border-bottom:1px solid #F5F5F5; 167 | } 168 | .context-menu-theme-human .context-menu-item-hover { 169 | background:transparent repeat-x left center; 170 | border-color:#963; 171 | } 172 | .context-menu-theme-human .context-menu-item .context-menu-item-inner { 173 | padding:4px 16px 4px 35px; 174 | margin-left:0px; 175 | background-color:none; 176 | background-repeat:no-repeat; 177 | background-position:3px center; 178 | background-image:none; 179 | } 180 | .context-menu-theme-human .context-menu-item-hover .context-menu-item-inner { 181 | } 182 | .context-menu-theme-human .context-menu-item-disabled { 183 | color:#A7A7A7; 184 | } 185 | 186 | /* Gloss Theme */ 187 | /* =========== */ 188 | .context-menu-theme-gloss { 189 | background:#f4f4f4 repeat-y left center; 190 | border:1px solid #f4f4f4; 191 | padding:1px; 192 | padding-right:0; 193 | } 194 | .context-menu-theme-gloss .context-menu-item { 195 | text-align:left; 196 | cursor:pointer; 197 | color:black; 198 | font-family:Helvetica,DejaVu Sans,Arial; 199 | font-size:12px; 200 | line-height:20px; 201 | height:27px; 202 | border:1px solid transparent; 203 | } 204 | .context-menu-theme-gloss .context-menu-separator { 205 | margin:0px 0px 0px 32px; 206 | font-size:0px; 207 | border-top:1px solid #C5C5C5; 208 | border-bottom:1px solid #F5F5F5; 209 | } 210 | .context-menu-theme-gloss .context-menu-item-hover { 211 | background:transparent repeat-x left center; 212 | color:#fff; 213 | border-color:#000; 214 | border-radius: 3px; 215 | -webkit-border-radius: 3px; 216 | -moz-border-radius: 3px; 217 | } 218 | .context-menu-theme-gloss .context-menu-item .context-menu-item-inner { 219 | padding:4px 16px 4px 35px; 220 | margin-left:0px; 221 | background-color:none; 222 | background-repeat:no-repeat; 223 | background-position:3px center; 224 | background-image:none; 225 | } 226 | .context-menu-theme-gloss .context-menu-item-hover .context-menu-item-inner { 227 | } 228 | .context-menu-theme-gloss .context-menu-item-disabled { 229 | color:#A7A7A7; 230 | } 231 | 232 | .context-menu-theme-gloss-cyan .context-menu-item-hover { 233 | border-color:#00c; 234 | } 235 | 236 | .context-menu-theme-gloss-semitransparent .context-menu-item-hover { 237 | border-color:#00c; 238 | background-color:#30f; 239 | } 240 | 241 | -------------------------------------------------------------------------------- /wwwroot/js/portinfo.js: -------------------------------------------------------------------------------- 1 | if (enabled_elements == null) 2 | enabled_elements = []; 3 | enabled_elements_count = enabled_elements.length; 4 | port_cmenu_items = []; 5 | wait_count = 0; 6 | bk_event = null; 7 | port_clicked = null; 8 | 9 | (function () { 10 | var menu_item_candidates = { 11 | link: {'Show links status': {onclick: menuItemClicked, className: 'itemname-link'}}, 12 | conf: {'Show ports configuration': {onclick: menuItemClicked, className: 'itemname-conf'}}, 13 | mac: {'Show device learned MACs': {onclick: menuItemClicked, className: 'itemname-mac'}}, 14 | portmac: {'Show port learned MACs': {onclick: menuItemClicked, className: 'itemname-portmac'}} 15 | }; 16 | var portinfo_enabled = false; 17 | for (var i in enabled_elements) { 18 | var name = enabled_elements[i]; 19 | port_cmenu_items.push(menu_item_candidates[name]); 20 | if (menu_item_candidates[name] != null && name.match (/^(link|conf|mac)$/)) 21 | portinfo_enabled = true; 22 | } 23 | if (portinfo_enabled) { 24 | port_cmenu_items.unshift($.contextMenu.separator); 25 | port_cmenu_items.unshift({'Show all info': {onclick: showAllClicked, className: 'itemname-all'}}); 26 | } 27 | })(); 28 | 29 | function showAllClicked(menuItem, menu) { 30 | for (var i in enabled_elements) { 31 | var name = enabled_elements[i]; 32 | if (name.match (/^(link|conf|mac)$/)) { 33 | port_clicked = this; 34 | menuItemClicked($('.context-menu-item.itemname-' + name)[0], menu); 35 | } 36 | } 37 | } 38 | 39 | $(document).ready(function () { 40 | // create global object port_cmenu 41 | if (port_cmenu_items.length) { 42 | port_cmenu = $.contextMenu.create(port_cmenu_items, {theme:'vista'}); 43 | // add popup button after every portname 44 | $('.interactive-portname.port-menu').after(''); 45 | $('
').hide().addClass('cursor-shadow').css('position', 'absolute').css('width', 16).css('height', 16).css("background-image", "url(index.php?module=chrome&uri=pix/ajax-loader.gif").appendTo('body'); 46 | 47 | // bind popup menu to every link with class port-popup 48 | $('a.port-popup').bind('click', function(e){port_cmenu.show(this,e);return false;}); 49 | $('body').bind('mouseup', rememberCursorPosition); 50 | } 51 | }); 52 | 53 | function disableMenuItem(menuItem) { 54 | setTimeout (function() { 55 | if (! $(menuItem).hasClass($.contextMenu.disabledItemClassName)) { 56 | $(menuItem).addClass($.contextMenu.disabledItemClassName); 57 | if (--enabled_elements_count <= 0) { 58 | $('.context-menu-item.itemname-all').addClass($.contextMenu.disabledItemClassName); 59 | } 60 | } 61 | }, 50); 62 | } 63 | 64 | function setItemIcon(menuItem, iconName) { 65 | var iconURL; 66 | if (iconName == 'wait') 67 | iconURL = 'index.php?module=chrome&uri=pix/ajax-loader.gif'; 68 | else if (iconName == 'ok') 69 | iconURL = 'index.php?module=chrome&uri=pix/checkbox_yes.png'; 70 | else 71 | iconURL = ''; 72 | $(menuItem).children('.' + $.contextMenu.innerDivClassName).css("background-image", "url(" + iconURL + ")"); 73 | } 74 | 75 | function menuItemClicked(menuItem, menu) { 76 | if (!port_clicked) 77 | port_clicked = this; 78 | // if the item is already disabled, do not react on click 79 | if ($(menuItem).hasClass($.contextMenu.disabledItemClassName)) 80 | return; 81 | 82 | // determine the typename of menuItem ('link', 'mac' or 'conf') 83 | var matches = menuItem.className.match(/itemname-([^ ]+)/); 84 | if (! matches) 85 | return; 86 | var type = matches[1]; 87 | var per_port_cmd = type == 'portmac'; 88 | var portnameElem = $(port_clicked).siblings('.interactive-portname')[0]; 89 | port_clicked = null; 90 | 91 | var bSuccessIcon = false; 92 | $.ajax({ 93 | async: true, 94 | beforeSend: function(XMLHttpRequest) { 95 | if (++wait_count > 0) { 96 | cursor_shadow = $('.cursor-shadow'); 97 | $('body').bind('mousemove', waitCursorMove); 98 | if (bk_event) 99 | waitCursorMove(bk_event); 100 | } 101 | setItemIcon(menuItem, 'wait'); 102 | }, 103 | complete: function(XMLHttpRequest, textStatus) { 104 | if (--wait_count <= 0) { 105 | $('.cursor-shadow').hide(); 106 | $('body').unbind('mousemove', waitCursorMove); 107 | $('body').unbind('click', rememberCursorPosition); 108 | } 109 | if (! bSuccessIcon) 110 | setItemIcon(menuItem, ''); 111 | }, 112 | type: 'GET', 113 | url: 'index.php', 114 | data: { 115 | 'module': 'ajax', 116 | 'ac': 'get-port-' + type, 117 | 'object_id': getQueryString('object_id'), 118 | 'port_name': getPortName(portnameElem) 119 | }, 120 | dataType: 'json', 121 | success: function(data, textStatus, XMLHttpRequest) { 122 | if (! data) 123 | return; 124 | bSuccessIcon = true; 125 | 126 | if (per_port_cmd) 127 | setItemIcon(menuItem, ''); 128 | else 129 | setItemIcon(menuItem, 'ok'); 130 | 131 | if (type == 'link') 132 | applyLinkData(data); 133 | else if (type == 'mac' || type == 'portmac') 134 | applyMacData(data); 135 | else if (type == 'conf') 136 | applyConfData(data); 137 | } 138 | }); 139 | if (!per_port_cmd) 140 | disableMenuItem(menuItem); 141 | } 142 | 143 | function rememberCursorPosition(event) { 144 | bk_event = event; 145 | } 146 | 147 | function waitCursorMove(event) { 148 | cursor_shadow.css("left", event.pageX + 15).css("top", event.pageY + 15).show(); 149 | } 150 | 151 | function applyLinkData(data) { 152 | var seen_portnames = {}; 153 | $('.interactive-portname').each(function() { 154 | var portname = getPortName (this); 155 | var item = data[portname]; 156 | if (item != null) { 157 | var prepended; 158 | if (item['inline']) 159 | prepended = $('').addClass('port-link').html(item['inline']).insertBefore(this); 160 | if (item['popup'] && prepended) { 161 | if (! seen_portnames[portname]) 162 | seen_portnames[portname] = $('
').addClass('popup-box').html(item['popup']).appendTo('body'); 163 | prepended.thumbPopup(seen_portnames[portname]); 164 | } 165 | } 166 | }); 167 | } 168 | 169 | function applyMacData(data) { 170 | var seen_portnames = {}; 171 | $('.interactive-portname').each(function() { 172 | var portname = getPortName (this); 173 | var item = data[portname]; 174 | if (item != null) { 175 | var prepended; 176 | if (item['inline']) 177 | { 178 | var obj = $(this).parent().find('.mac-count'); 179 | if (!obj.length) 180 | appended = $('
').addClass('mac-count').html(item['inline']).appendTo($(this).parent()); 181 | else 182 | appended = obj.html(item['inline']); 183 | } 184 | if (item['popup'] && appended) { 185 | var obj = $("[id='maclist-popup-"+portname+"']"); 186 | if (! obj.size()) 187 | obj = $('
').addClass('popup-box mac-list').attr('id', 'maclist-popup-'+portname).html(item['popup']).appendTo('body'); 188 | else 189 | obj.html(item['popup']); 190 | appended.thumbPopup(obj); 191 | } 192 | } 193 | }); 194 | } 195 | 196 | function applyConfData(data) { 197 | var seen_portnames = {}; 198 | $('.interactive-portname').each(function() { 199 | var portname = getPortName (this); 200 | var item = data[portname]; 201 | if (item != null) { 202 | if (! seen_portnames[portname]) 203 | seen_portnames[portname] = $('
').addClass('popup-box port-config').html(item['popup']).appendTo('body'); 204 | $(this).thumbPopup(seen_portnames[portname]); 205 | } 206 | }); 207 | } 208 | 209 | function getPortName (element) { 210 | if (element.type == 'text') 211 | return $(element).val(); 212 | else 213 | return $(element).html(); 214 | } 215 | -------------------------------------------------------------------------------- /wwwroot/js/jquery.optionTree.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery optionTree Plugin 3 | * version: 1.3 4 | * @requires jQuery v1.3 or later 5 | * 6 | * Dual licensed under the MIT and GPL licenses: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | * http://www.gnu.org/licenses/gpl.html 9 | * 10 | * @version $Id: jquery.optionTree.js 13 2011-03-31 08:51:59Z kkotowicz $ 11 | * @author Krzysztof Kotowicz 12 | * @see http://code.google.com/p/jquery-option-tree/ 13 | * @see http://blog.kotowicz.net/search/label/option 14 | */ 15 | 16 | /** 17 | * Converts passed JSON option tree into dynamically created ").attr('name',name) 109 | .change(function() { 110 | if (this.options[this.selectedIndex].value !== '') { 111 | if ($.isFunction(options.on_each_change)) { 112 | removeNested(name + '_'); 113 | options.on_each_change.apply(this, [this.options[this.selectedIndex].value, tree]); 114 | } else { 115 | // call with value as a first parameter 116 | $(this).optionTree(tree[this.options[this.selectedIndex].value], options); 117 | } 118 | if (options.set_value_on === 'each') { 119 | setValue(name, this.options[this.selectedIndex].value); 120 | } 121 | } else { 122 | removeNested(name + '_'); 123 | setValue(name, options.empty_value); 124 | } 125 | }); 126 | 127 | var text_to_choose = ''; 128 | 129 | if (jQuery.isFunction(options.choose)) { 130 | var level = $(this).siblings().andSelf().filter('select').length; 131 | text_to_choose = options.choose.apply(this, [level]); 132 | } else if ( options.choose !== '' ) { 133 | text_to_choose = options.choose; 134 | } 135 | 136 | // if show multiple -> show open select 137 | var count_tree_objects = 0; 138 | if ( text_to_choose !== '' ) { 139 | // we have a default value 140 | count_tree_objects++; 141 | } 142 | if (options.show_multiple > 1) { 143 | count_tree_objects = options.show_multiple; 144 | } else if (options.show_multiple === true) { 145 | $.each(tree, function() { 146 | count_tree_objects++; 147 | }); 148 | } 149 | if ( count_tree_objects > 1 ){ 150 | $select.attr('size', count_tree_objects); 151 | } 152 | 153 | if ($(this).is('input')) { 154 | $select.insertBefore(this); 155 | } else { 156 | $select.insertAfter(this); 157 | } 158 | 159 | if (options.select_class) { 160 | $select.addClass(options.select_class); 161 | } 162 | 163 | if (options.tabindex) { 164 | $select.attr('tabindex', options.tabindex); 165 | } 166 | 167 | if ( text_to_choose !== '' ) { 168 | $("