From 972a3434bcd6068ff1f84d7287005d004c55262c Mon Sep 17 00:00:00 2001 From: Matt Pass Date: Fri, 20 Jan 2012 09:55:29 +0000 Subject: [PATCH] v0.5.0 update Global variables removed from JS file Plugins system evolved, now including setInterval Seperate CodeMirror instances per tab backupOpenFiles plugin created Minor fixes & improvements --- CodeMirror-2.2/LICENSE | 19 + CodeMirror-2.2/README.md | 6 + CodeMirror-2.2/keymap/emacs.js | 29 + CodeMirror-2.2/keymap/vim.js | 76 + CodeMirror-2.2/lib/codemirror.css | 104 + CodeMirror-2.2/lib/codemirror.js | 2761 +++++++++++++++++ CodeMirror-2.2/lib/util/dialog.css | 23 + CodeMirror-2.2/lib/util/dialog.js | 63 + CodeMirror-2.2/lib/util/foldcode.js | 66 + CodeMirror-2.2/lib/util/formatting.js | 291 ++ CodeMirror-2.2/lib/util/javascript-hint.js | 83 + CodeMirror-2.2/lib/util/overlay.js | 51 + CodeMirror-2.2/lib/util/runmode.js | 27 + CodeMirror-2.2/lib/util/search.js | 114 + CodeMirror-2.2/lib/util/searchcursor.js | 117 + CodeMirror-2.2/lib/util/simple-hint.css | 16 + CodeMirror-2.2/lib/util/simple-hint.js | 66 + CodeMirror-2.2/mode/clike/clike.js | 249 ++ CodeMirror-2.2/mode/clike/index.html | 101 + CodeMirror-2.2/mode/css/css.js | 124 + CodeMirror-2.2/mode/css/index.html | 55 + CodeMirror-2.2/mode/javascript/index.html | 77 + CodeMirror-2.2/mode/javascript/javascript.js | 360 +++ CodeMirror-2.2/mode/php/index.html | 48 + CodeMirror-2.2/mode/php/php.js | 120 + CodeMirror-2.2/mode/xml/index.html | 44 + CodeMirror-2.2/mode/xml/xml.js | 252 ++ README.md | 29 + editor.php | 105 + files.php | 163 + images/Thumbs.db | Bin 0 -> 12800 bytes images/backup-open-files.png | Bin 0 -> 551 bytes images/clipboard.png | Bin 0 -> 1519 bytes images/database.png | Bin 0 -> 2622 bytes images/file-manager-icons/Thumbs.db | Bin 0 -> 32768 bytes images/file-manager-icons/application.png | Bin 0 -> 464 bytes images/file-manager-icons/code.png | Bin 0 -> 603 bytes images/file-manager-icons/css.png | Bin 0 -> 618 bytes images/file-manager-icons/db.png | Bin 0 -> 579 bytes images/file-manager-icons/directory.png | Bin 0 -> 537 bytes images/file-manager-icons/doc.png | Bin 0 -> 651 bytes images/file-manager-icons/file.png | Bin 0 -> 294 bytes images/file-manager-icons/film.png | Bin 0 -> 653 bytes images/file-manager-icons/flash.png | Bin 0 -> 582 bytes images/file-manager-icons/html.png | Bin 0 -> 734 bytes images/file-manager-icons/java.png | Bin 0 -> 633 bytes images/file-manager-icons/linux.png | Bin 0 -> 668 bytes images/file-manager-icons/music.png | Bin 0 -> 385 bytes .../file-manager-icons/padlock-disabled.png | Bin 0 -> 447 bytes images/file-manager-icons/padlock.png | Bin 0 -> 752 bytes images/file-manager-icons/pdf.png | Bin 0 -> 591 bytes images/file-manager-icons/php.png | Bin 0 -> 538 bytes images/file-manager-icons/picture.png | Bin 0 -> 606 bytes images/file-manager-icons/ppt.png | Bin 0 -> 588 bytes images/file-manager-icons/psd.png | Bin 0 -> 856 bytes images/file-manager-icons/ruby.png | Bin 0 -> 626 bytes images/file-manager-icons/script.png | Bin 0 -> 859 bytes images/file-manager-icons/txt.png | Bin 0 -> 342 bytes images/file-manager-icons/xls.png | Bin 0 -> 663 bytes images/file-manager-icons/zip.png | Bin 0 -> 386 bytes images/files-arrow.gif | Bin 0 -> 842 bytes images/ice-coder.gif | Bin 0 -> 2236 bytes images/images.png | Bin 0 -> 1533 bytes images/nav-bg.gif | Bin 0 -> 1326 bytes images/nav-close.gif | Bin 0 -> 56 bytes images/nav-new.png | Bin 0 -> 480 bytes images/upload.png | Bin 0 -> 538 bytes index.php | 128 + lib/coder.css | 95 + lib/coder.js | 844 +++++ lib/editor.css | 32 + lib/file-control.php | 167 + lib/files.css | 98 + lib/settings.php | 37 + plugins/adminer/adminer-3.3.3-mysql-en.php | 877 ++++++ plugins/adminer/adminer.css | 58 + plugins/backupOpenFiles/index.php | 78 + 77 files changed, 8053 insertions(+) create mode 100644 CodeMirror-2.2/LICENSE create mode 100644 CodeMirror-2.2/README.md create mode 100644 CodeMirror-2.2/keymap/emacs.js create mode 100644 CodeMirror-2.2/keymap/vim.js create mode 100644 CodeMirror-2.2/lib/codemirror.css create mode 100644 CodeMirror-2.2/lib/codemirror.js create mode 100644 CodeMirror-2.2/lib/util/dialog.css create mode 100644 CodeMirror-2.2/lib/util/dialog.js create mode 100644 CodeMirror-2.2/lib/util/foldcode.js create mode 100644 CodeMirror-2.2/lib/util/formatting.js create mode 100644 CodeMirror-2.2/lib/util/javascript-hint.js create mode 100644 CodeMirror-2.2/lib/util/overlay.js create mode 100644 CodeMirror-2.2/lib/util/runmode.js create mode 100644 CodeMirror-2.2/lib/util/search.js create mode 100644 CodeMirror-2.2/lib/util/searchcursor.js create mode 100644 CodeMirror-2.2/lib/util/simple-hint.css create mode 100644 CodeMirror-2.2/lib/util/simple-hint.js create mode 100644 CodeMirror-2.2/mode/clike/clike.js create mode 100644 CodeMirror-2.2/mode/clike/index.html create mode 100644 CodeMirror-2.2/mode/css/css.js create mode 100644 CodeMirror-2.2/mode/css/index.html create mode 100644 CodeMirror-2.2/mode/javascript/index.html create mode 100644 CodeMirror-2.2/mode/javascript/javascript.js create mode 100644 CodeMirror-2.2/mode/php/index.html create mode 100644 CodeMirror-2.2/mode/php/php.js create mode 100644 CodeMirror-2.2/mode/xml/index.html create mode 100644 CodeMirror-2.2/mode/xml/xml.js create mode 100644 README.md create mode 100644 editor.php create mode 100644 files.php create mode 100644 images/Thumbs.db create mode 100644 images/backup-open-files.png create mode 100644 images/clipboard.png create mode 100644 images/database.png create mode 100644 images/file-manager-icons/Thumbs.db create mode 100644 images/file-manager-icons/application.png create mode 100644 images/file-manager-icons/code.png create mode 100644 images/file-manager-icons/css.png create mode 100644 images/file-manager-icons/db.png create mode 100644 images/file-manager-icons/directory.png create mode 100644 images/file-manager-icons/doc.png create mode 100644 images/file-manager-icons/file.png create mode 100644 images/file-manager-icons/film.png create mode 100644 images/file-manager-icons/flash.png create mode 100644 images/file-manager-icons/html.png create mode 100644 images/file-manager-icons/java.png create mode 100644 images/file-manager-icons/linux.png create mode 100644 images/file-manager-icons/music.png create mode 100644 images/file-manager-icons/padlock-disabled.png create mode 100644 images/file-manager-icons/padlock.png create mode 100644 images/file-manager-icons/pdf.png create mode 100644 images/file-manager-icons/php.png create mode 100644 images/file-manager-icons/picture.png create mode 100644 images/file-manager-icons/ppt.png create mode 100644 images/file-manager-icons/psd.png create mode 100644 images/file-manager-icons/ruby.png create mode 100644 images/file-manager-icons/script.png create mode 100644 images/file-manager-icons/txt.png create mode 100644 images/file-manager-icons/xls.png create mode 100644 images/file-manager-icons/zip.png create mode 100644 images/files-arrow.gif create mode 100644 images/ice-coder.gif create mode 100644 images/images.png create mode 100644 images/nav-bg.gif create mode 100644 images/nav-close.gif create mode 100644 images/nav-new.png create mode 100644 images/upload.png create mode 100644 index.php create mode 100644 lib/coder.css create mode 100644 lib/coder.js create mode 100644 lib/editor.css create mode 100644 lib/file-control.php create mode 100644 lib/files.css create mode 100644 lib/settings.php create mode 100644 plugins/adminer/adminer-3.3.3-mysql-en.php create mode 100644 plugins/adminer/adminer.css create mode 100644 plugins/backupOpenFiles/index.php diff --git a/CodeMirror-2.2/LICENSE b/CodeMirror-2.2/LICENSE new file mode 100644 index 0000000..3f7c0bb --- /dev/null +++ b/CodeMirror-2.2/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Marijn Haverbeke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/CodeMirror-2.2/README.md b/CodeMirror-2.2/README.md new file mode 100644 index 0000000..09e6760 --- /dev/null +++ b/CodeMirror-2.2/README.md @@ -0,0 +1,6 @@ +# CodeMirror 2 + +CodeMirror 2 is a rewrite of [CodeMirror +1](http://github.com/marijnh/CodeMirror). The docs live +[here](http://codemirror.net/doc/manual.html), and the project page is +[http://codemirror.net/](http://codemirror.net/). diff --git a/CodeMirror-2.2/keymap/emacs.js b/CodeMirror-2.2/keymap/emacs.js new file mode 100644 index 0000000..8fd3564 --- /dev/null +++ b/CodeMirror-2.2/keymap/emacs.js @@ -0,0 +1,29 @@ +// TODO number prefixes +(function() { + // Really primitive kill-ring implementation. + var killRing = []; + function addToRing(str) { + killRing.push(str); + if (killRing.length > 50) killRing.shift(); + } + function getFromRing() { return killRing[killRing.length - 1] || ""; } + function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); } + + CodeMirror.keyMap.emacs = { + "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");}, + "Ctrl-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");}, + "Ctrl-Alt-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");}, + "Alt-W": function(cm) {addToRing(cm.getSelection());}, + "Ctrl-Y": function(cm) {cm.replaceSelection(getFromRing());}, + "Alt-Y": function(cm) {cm.replaceSelection(popFromRing());}, + "Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", + "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace", + "Ctrl-Z": "undo", "Cmd-Z": "undo", + fallthrough: ["basic", "emacsy"] + }; + + CodeMirror.keyMap["emacs-Ctrl-X"] = { + "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close", + auto: "emacs", catchall: function(cm) {/*ignore*/} + }; +})(); diff --git a/CodeMirror-2.2/keymap/vim.js b/CodeMirror-2.2/keymap/vim.js new file mode 100644 index 0000000..e03e012 --- /dev/null +++ b/CodeMirror-2.2/keymap/vim.js @@ -0,0 +1,76 @@ +(function() { + var count = ""; + function pushCountDigit(digit) { return function(cm) {count += digit;} } + function popCount() { var i = parseInt(count); count = ""; return i || 1; } + function countTimes(func) { + if (typeof func == "string") func = CodeMirror.commands[func]; + return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); } + } + + function iterObj(o, f) { + for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]); + } + + var word = [/\w/, /[^\w\s]/], bigWord = [/\S/]; + function findWord(line, pos, dir, regexps) { + var stop = 0, next = -1; + if (dir > 0) { stop = line.length; next = 0; } + var start = stop, end = stop; + // Find bounds of next one. + outer: for (; pos != stop; pos += dir) { + for (var i = 0; i < regexps.length; ++i) { + if (regexps[i].test(line.charAt(pos + next))) { + start = pos; + for (; pos != stop; pos += dir) { + if (!regexps[i].test(line.charAt(pos + next))) break; + } + end = pos; + break outer; + } + } + } + return {from: Math.min(start, end), to: Math.max(start, end)}; + } + function moveToWord(cm, regexps, dir, where) { + var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word; + while (true) { + word = findWord(line, ch, dir, regexps); + ch = word[where == "end" ? "to" : "from"]; + if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"]; + else break; + } + cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true); + } + + var map = CodeMirror.keyMap.vim = { + "0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);}, + "I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert");}, + "G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");}, + catchall: function(cm) {/*ignore*/} + }; + // Add bindings for number keys + for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i); + // Add bindings that are influenced by number keys + iterObj({"H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown", "K": "goLineUp", + "Left": "goColumnLeft", "Right": "goColumnRight", "Down": "goLineDown", "Up": "goLineUp", + "Backspace": "goCharLeft", "Space": "goCharRight", + "B": function(cm) {moveToWord(cm, word, -1, "end");}, + "E": function(cm) {moveToWord(cm, word, 1, "end");}, + "W": function(cm) {moveToWord(cm, word, 1, "start");}, + "Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");}, + "Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");}, + "Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");}, + "U": "undo", "Ctrl-R": "redo", "Shift-4": "goLineEnd"}, + function(key, cmd) { map[key] = countTimes(cmd); }); + + CodeMirror.keyMap["vim-prefix-g"] = { + "E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}), + "Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}), + auto: "vim", catchall: function(cm) {/*ignore*/} + }; + + CodeMirror.keyMap["vim-insert"] = { + "Esc": function(cm) {cm.setOption("keyMap", "vim");}, + fallthrough: ["default"] + }; +})(); diff --git a/CodeMirror-2.2/lib/codemirror.css b/CodeMirror-2.2/lib/codemirror.css new file mode 100644 index 0000000..1161425 --- /dev/null +++ b/CodeMirror-2.2/lib/codemirror.css @@ -0,0 +1,104 @@ +.CodeMirror { + line-height: 1em; + font-family: monospace; +} + +.CodeMirror-scroll { + overflow: auto; + height: 300px; + /* This is needed to prevent an IE[67] bug where the scrolled content + is visible outside of the scrolling box. */ + position: relative; +} + +.CodeMirror-gutter { + position: absolute; left: 0; top: 0; + z-index: 10; + background-color: #f7f7f7; + border-right: 1px solid #eee; + min-width: 2em; + height: 100%; +} +.CodeMirror-gutter-text { + color: #aaa; + text-align: right; + padding: .4em .2em .4em .4em; + white-space: pre !important; +} +.CodeMirror-lines { + padding: .4em; +} + +.CodeMirror pre { + -moz-border-radius: 0; + -webkit-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + border-width: 0; margin: 0; padding: 0; background: transparent; + font-family: inherit; + font-size: inherit; + padding: 0; margin: 0; + white-space: pre; + word-wrap: normal; +} + +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; +} +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror textarea { + outline: none !important; +} + +.CodeMirror pre.CodeMirror-cursor { + z-index: 10; + position: absolute; + visibility: hidden; + border-left: 1px solid black; +} +.CodeMirror-focused pre.CodeMirror-cursor { + visibility: visible; +} + +span.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused span.CodeMirror-selected { background: #d2dcf8; } + +.CodeMirror-searching {background: #ffa;} + +/* Default theme */ + +.cm-s-default span.cm-keyword {color: #708;} +.cm-s-default span.cm-atom {color: #219;} +.cm-s-default span.cm-number {color: #164;} +.cm-s-default span.cm-def {color: #00f;} +.cm-s-default span.cm-variable {color: black;} +.cm-s-default span.cm-variable-2 {color: #05a;} +.cm-s-default span.cm-variable-3 {color: #085;} +.cm-s-default span.cm-property {color: black;} +.cm-s-default span.cm-operator {color: black;} +.cm-s-default span.cm-comment {color: #a50;} +.cm-s-default span.cm-string {color: #a11;} +.cm-s-default span.cm-string-2 {color: #f50;} +.cm-s-default span.cm-meta {color: #555;} +.cm-s-default span.cm-error {color: #f00;} +.cm-s-default span.cm-qualifier {color: #555;} +.cm-s-default span.cm-builtin {color: #30a;} +.cm-s-default span.cm-bracket {color: #cc7;} +.cm-s-default span.cm-tag {color: #170;} +.cm-s-default span.cm-attribute {color: #00c;} +.cm-s-default span.cm-header {color: #a0a;} +.cm-s-default span.cm-quote {color: #090;} +.cm-s-default span.cm-hr {color: #999;} +.cm-s-default span.cm-link {color: #00c;} + +span.cm-header, span.cm-strong {font-weight: bold;} +span.cm-em {font-style: italic;} +span.cm-emstrong {font-style: italic; font-weight: bold;} +span.cm-link {text-decoration: underline;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} diff --git a/CodeMirror-2.2/lib/codemirror.js b/CodeMirror-2.2/lib/codemirror.js new file mode 100644 index 0000000..79eb457 --- /dev/null +++ b/CodeMirror-2.2/lib/codemirror.js @@ -0,0 +1,2761 @@ +// CodeMirror version 2.2 +// +// All functions that need access to the editor's state live inside +// the CodeMirror function. Below that, at the bottom of the file, +// some utilities are defined. + +// CodeMirror is the only global var we claim +var CodeMirror = (function() { + // This is the function that produces an editor instance. It's + // closure is used to store the editor state. + function CodeMirror(place, givenOptions) { + // Determine effective options based on given values and defaults. + var options = {}, defaults = CodeMirror.defaults; + for (var opt in defaults) + if (defaults.hasOwnProperty(opt)) + options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; + + var targetDocument = options["document"]; + // The element in which the editor lives. + var wrapper = targetDocument.createElement("div"); + wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : ""); + // This mess creates the base DOM structure for the editor. + wrapper.innerHTML = + '
' + // Wraps and hides input textarea + '
' + + '
' + + '
' + // Set to the height of the text, causes scrolling + '
' + // Moved around its parent to cover visible view + '
' + + // Provides positioning relative to (visible) text origin + '
' + + '
' + + '
 
' + // Absolutely positioned blinky cursor + '
' + // This DIV contains the actual code + '
'; + if (place.appendChild) place.appendChild(wrapper); else place(wrapper); + // I've never seen more elegant code in my life. + var inputDiv = wrapper.firstChild, input = inputDiv.firstChild, + scroller = wrapper.lastChild, code = scroller.firstChild, + mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild, + lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild, + cursor = measure.nextSibling, lineDiv = cursor.nextSibling; + themeChanged(); + // Needed to hide big blue blinking cursor on Mobile Safari + if (/AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent)) input.style.width = "0px"; + if (!webkit) lineSpace.draggable = true; + if (options.tabindex != null) input.tabIndex = options.tabindex; + if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; + + // Check for problem with IE innerHTML not working when we have a + // P (or similar) parent node. + try { stringWidth("x"); } + catch (e) { + if (e.message.match(/runtime/i)) + e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)"); + throw e; + } + + // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval. + var poll = new Delayed(), highlight = new Delayed(), blinker; + + // mode holds a mode API object. doc is the tree of Line objects, + // work an array of lines that should be parsed, and history the + // undo history (instance of History constructor). + var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused; + loadMode(); + // The selection. These are always maintained to point at valid + // positions. Inverted is used to remember that the user is + // selecting bottom-to-top. + var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; + // Selection-related flags. shiftSelecting obviously tracks + // whether the user is holding shift. + var shiftSelecting, lastClick, lastDoubleClick, draggingText, overwrite = false; + // Variables used by startOperation/endOperation to track what + // happened during the operation. + var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone, + gutterDirty, callbacks; + // Current visible range (may be bigger than the view window). + var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0; + // bracketHighlighted is used to remember that a backet has been + // marked. + var bracketHighlighted; + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + var maxLine = "", maxWidth, tabText = computeTabText(); + + // Initialize the content. + operation(function(){setValue(options.value || ""); updateInput = false;})(); + var history = new History(); + + // Register our event handlers. + connect(scroller, "mousedown", operation(onMouseDown)); + connect(scroller, "dblclick", operation(onDoubleClick)); + connect(lineSpace, "dragstart", onDragStart); + connect(lineSpace, "selectstart", e_preventDefault); + // Gecko browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for Gecko. + if (!gecko) connect(scroller, "contextmenu", onContextMenu); + connect(scroller, "scroll", function() { + updateDisplay([]); + if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px"; + if (options.onScroll) options.onScroll(instance); + }); + connect(window, "resize", function() {updateDisplay(true);}); + connect(input, "keyup", operation(onKeyUp)); + connect(input, "input", fastPoll); + connect(input, "keydown", operation(onKeyDown)); + connect(input, "keypress", operation(onKeyPress)); + connect(input, "focus", onFocus); + connect(input, "blur", onBlur); + + connect(scroller, "dragenter", e_stop); + connect(scroller, "dragover", e_stop); + connect(scroller, "drop", operation(onDrop)); + connect(scroller, "paste", function(){focusInput(); fastPoll();}); + connect(input, "paste", fastPoll); + connect(input, "cut", operation(function(){replaceSelection("");})); + + // IE throws unspecified error in certain cases, when + // trying to access activeElement before onload + var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { } + if (hasFocus) setTimeout(onFocus, 20); + else onBlur(); + + function isLine(l) {return l >= 0 && l < doc.size;} + // The instance object that we'll return. Mostly calls out to + // local functions in the CodeMirror function. Some do some extra + // range checking and/or clipping. operation is used to wrap the + // call so that changes it makes are tracked, and the display is + // updated afterwards. + var instance = wrapper.CodeMirror = { + getValue: getValue, + setValue: operation(setValue), + getSelection: getSelection, + replaceSelection: operation(replaceSelection), + focus: function(){focusInput(); onFocus(); fastPoll();}, + setOption: function(option, value) { + var oldVal = options[option]; + options[option] = value; + if (option == "mode" || option == "indentUnit") loadMode(); + else if (option == "readOnly" && value) {onBlur(); input.blur();} + else if (option == "theme") themeChanged(); + else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); + else if (option == "tabSize") operation(tabsChanged)(); + if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") + operation(gutterChanged)(); + }, + getOption: function(option) {return options[option];}, + undo: operation(undo), + redo: operation(redo), + indentLine: operation(function(n, dir) { + if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract"); + }), + indentSelection: operation(indentSelected), + historySize: function() {return {undo: history.done.length, redo: history.undone.length};}, + clearHistory: function() {history = new History();}, + matchBrackets: operation(function(){matchBrackets(true);}), + getTokenAt: operation(function(pos) { + pos = clipPos(pos); + return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch); + }), + getStateAfter: function(line) { + line = clipLine(line == null ? doc.size - 1: line); + return getStateBefore(line + 1); + }, + cursorCoords: function(start){ + if (start == null) start = sel.inverted; + return pageCoords(start ? sel.from : sel.to); + }, + charCoords: function(pos){return pageCoords(clipPos(pos));}, + coordsChar: function(coords) { + var off = eltOffset(lineSpace); + return coordsChar(coords.x - off.left, coords.y - off.top); + }, + markText: operation(markText), + setBookmark: setBookmark, + setMarker: operation(addGutterMarker), + clearMarker: operation(removeGutterMarker), + setLineClass: operation(setLineClass), + hideLine: operation(function(h) {return setLineHidden(h, true);}), + showLine: operation(function(h) {return setLineHidden(h, false);}), + onDeleteLine: function(line, f) { + if (typeof line == "number") { + if (!isLine(line)) return null; + line = getLine(line); + } + (line.handlers || (line.handlers = [])).push(f); + return line; + }, + lineInfo: lineInfo, + addWidget: function(pos, node, scroll, vert, horiz) { + pos = localCoords(clipPos(pos)); + var top = pos.yBot, left = pos.x; + node.style.position = "absolute"; + code.appendChild(node); + if (vert == "over") top = pos.y; + else if (vert == "near") { + var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()), + hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft(); + if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight) + top = pos.y - node.offsetHeight; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = (top + paddingTop()) + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = code.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2; + node.style.left = (left + paddingLeft()) + "px"; + } + if (scroll) + scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + lineCount: function() {return doc.size;}, + clipPos: clipPos, + getCursor: function(start) { + if (start == null) start = sel.inverted; + return copyPos(start ? sel.from : sel.to); + }, + somethingSelected: function() {return !posEq(sel.from, sel.to);}, + setCursor: operation(function(line, ch, user) { + if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user); + else setCursor(line, ch, user); + }), + setSelection: operation(function(from, to, user) { + (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from)); + }), + getLine: function(line) {if (isLine(line)) return getLine(line).text;}, + getLineHandle: function(line) {if (isLine(line)) return getLine(line);}, + setLine: operation(function(line, text) { + if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length}); + }), + removeLine: operation(function(line) { + if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0})); + }), + replaceRange: operation(replaceRange), + getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));}, + + execCommand: function(cmd) {return commands[cmd](instance);}, + // Stuff used by commands, probably not much use to outside code. + moveH: operation(moveH), + deleteH: operation(deleteH), + moveV: operation(moveV), + toggleOverwrite: function() {overwrite = !overwrite;}, + + posFromIndex: function(off) { + var lineNo = 0, ch; + doc.iter(0, doc.size, function(line) { + var sz = line.text.length + 1; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos({line: lineNo, ch: ch}); + }, + indexFromPos: function (coords) { + if (coords.line < 0 || coords.ch < 0) return 0; + var index = coords.ch; + doc.iter(0, coords.line, function (line) { + index += line.text.length + 1; + }); + return index; + }, + + operation: function(f){return operation(f)();}, + refresh: function(){updateDisplay(true);}, + getInputField: function(){return input;}, + getWrapperElement: function(){return wrapper;}, + getScrollerElement: function(){return scroller;}, + getGutterElement: function(){return gutter;} + }; + + function getLine(n) { return getLineAt(doc, n); } + function updateLineHeight(line, height) { + gutterDirty = true; + var diff = height - line.height; + for (var n = line; n; n = n.parent) n.height += diff; + } + + function setValue(code) { + var top = {line: 0, ch: 0}; + updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length}, + splitLines(code), top, top); + updateInput = true; + } + function getValue(code) { + var text = []; + doc.iter(0, doc.size, function(line) { text.push(line.text); }); + return text.join("\n"); + } + + function onMouseDown(e) { + setShift(e.shiftKey); + // Check whether this is a click in a widget + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == code && n != mover) return; + + // See if this is a click in the gutter + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) { + if (options.onGutterClick) + options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e); + return e_preventDefault(e); + } + + var start = posFromMouse(e); + + switch (e_button(e)) { + case 3: + if (gecko && !mac) onContextMenu(e); + return; + case 2: + if (start) setCursor(start.line, start.ch, true); + return; + } + // For button 1, if it was clicked inside the editor + // (posFromMouse returning non-null), we have to adjust the + // selection. + if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;} + + if (!focused) onFocus(); + + var now = +new Date; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { + e_preventDefault(e); + setTimeout(focusInput, 20); + return selectLine(start.line); + } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { + lastDoubleClick = {time: now, pos: start}; + e_preventDefault(e); + return selectWordAt(start); + } else { lastClick = {time: now, pos: start}; } + + var last = start, going; + if (dragAndDrop && !posEq(sel.from, sel.to) && + !posLess(start, sel.from) && !posLess(sel.to, start)) { + // Let the drag handler handle this. + if (webkit) lineSpace.draggable = true; + var up = connect(targetDocument, "mouseup", operation(function(e2) { + if (webkit) lineSpace.draggable = false; + draggingText = false; + up(); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + setCursor(start.line, start.ch, true); + focusInput(); + } + }), true); + draggingText = true; + return; + } + e_preventDefault(e); + setCursor(start.line, start.ch, true); + + function extend(e) { + var cur = posFromMouse(e, true); + if (cur && !posEq(cur, last)) { + if (!focused) onFocus(); + last = cur; + setSelectionUser(start, cur); + updateInput = false; + var visible = visibleLines(); + if (cur.line >= visible.to || cur.line < visible.from) + going = setTimeout(operation(function(){extend(e);}), 150); + } + } + + var move = connect(targetDocument, "mousemove", operation(function(e) { + clearTimeout(going); + e_preventDefault(e); + extend(e); + }), true); + var up = connect(targetDocument, "mouseup", operation(function(e) { + clearTimeout(going); + var cur = posFromMouse(e); + if (cur) setSelectionUser(start, cur); + e_preventDefault(e); + focusInput(); + updateInput = true; + move(); up(); + }), true); + } + function onDoubleClick(e) { + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) return e_preventDefault(e); + var start = posFromMouse(e); + if (!start) return; + lastDoubleClick = {time: +new Date, pos: start}; + e_preventDefault(e); + selectWordAt(start); + } + function onDrop(e) { + e.preventDefault(); + var pos = posFromMouse(e, true), files = e.dataTransfer.files; + if (!pos || options.readOnly) return; + if (files && files.length && window.FileReader && window.File) { + function loadFile(file, i) { + var reader = new FileReader; + reader.onload = function() { + text[i] = reader.result; + if (++read == n) { + pos = clipPos(pos); + operation(function() { + var end = replaceRange(text.join(""), pos, pos); + setSelectionUser(pos, end); + })(); + } + }; + reader.readAsText(file); + } + var n = files.length, text = Array(n), read = 0; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } + else { + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + var end = replaceRange(text, pos, pos); + var curFrom = sel.from, curTo = sel.to; + setSelectionUser(pos, end); + if (draggingText) replaceRange("", curFrom, curTo); + focusInput(); + } + } + catch(e){} + } + } + function onDragStart(e) { + var txt = getSelection(); + // This will reset escapeElement + htmlEscape(txt); + e.dataTransfer.setDragImage(escapeElement, 0, 0); + e.dataTransfer.setData("Text", txt); + } + function handleKeyBinding(e) { + var name = keyNames[e.keyCode], next = keyMap[options.keyMap].auto, bound, dropShift; + if (name == null || e.altGraphKey) { + if (next) options.keyMap = next; + return null; + } + if (e.altKey) name = "Alt-" + name; + if (e.ctrlKey) name = "Ctrl-" + name; + if (e.metaKey) name = "Cmd-" + name; + if (e.shiftKey && (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) { + dropShift = true; + } else { + bound = lookupKey(name, options.extraKeys, options.keyMap); + } + if (typeof bound == "string") { + if (commands.propertyIsEnumerable(bound)) bound = commands[bound]; + else bound = null; + } + if (next && (bound || !isModifierKey(e))) options.keyMap = next; + if (!bound) return false; + if (dropShift) { + var prevShift = shiftSelecting; + shiftSelecting = null; + bound(instance); + shiftSelecting = prevShift; + } else bound(instance); + e_preventDefault(e); + return true; + } + var lastStoppedKey = null; + function onKeyDown(e) { + if (!focused) onFocus(); + var code = e.keyCode; + // IE does strange things with escape. + if (ie && code == 27) { e.returnValue = false; } + setShift(code == 16 || e.shiftKey); + // First give onKeyEvent option a chance to handle this. + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + var handled = handleKeyBinding(e); + if (window.opera) { + lastStoppedKey = handled ? e.keyCode : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && (mac ? e.metaKey : e.ctrlKey) && e.keyCode == 88) + replaceSelection(""); + } + } + function onKeyPress(e) { + if (window.opera && e.keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + if (window.opera && !e.which && handleKeyBinding(e)) return; + if (options.electricChars && mode.electricChars) { + var ch = String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode); + if (mode.electricChars.indexOf(ch) > -1) + setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75); + } + fastPoll(); + } + function onKeyUp(e) { + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + if (e.keyCode == 16) shiftSelecting = null; + } + + function onFocus() { + if (options.readOnly) return; + if (!focused) { + if (options.onFocus) options.onFocus(instance); + focused = true; + if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1) + wrapper.className += " CodeMirror-focused"; + if (!leaveInputAlone) resetInput(true); + } + slowPoll(); + restartBlink(); + } + function onBlur() { + if (focused) { + if (options.onBlur) options.onBlur(instance); + focused = false; + wrapper.className = wrapper.className.replace(" CodeMirror-focused", ""); + } + clearInterval(blinker); + setTimeout(function() {if (!focused) shiftSelecting = null;}, 150); + } + + // Replace the range from from to to by the strings in newText. + // Afterwards, set the selection to selFrom, selTo. + function updateLines(from, to, newText, selFrom, selTo) { + if (history) { + var old = []; + doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); }); + history.addChange(from.line, newText.length, old); + while (history.done.length > options.undoDepth) history.done.shift(); + } + updateLinesNoUndo(from, to, newText, selFrom, selTo); + } + function unredoHelper(from, to) { + var change = from.pop(); + if (change) { + var replaced = [], end = change.start + change.added; + doc.iter(change.start, end, function(line) { replaced.push(line.text); }); + to.push({start: change.start, added: change.old.length, old: replaced}); + var pos = clipPos({line: change.start + change.old.length - 1, + ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])}); + updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos); + updateInput = true; + } + } + function undo() {unredoHelper(history.done, history.undone);} + function redo() {unredoHelper(history.undone, history.done);} + + function updateLinesNoUndo(from, to, newText, selFrom, selTo) { + var recomputeMaxLength = false, maxLineLength = maxLine.length; + if (!options.lineWrapping) + doc.iter(from.line, to.line, function(line) { + if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;} + }); + if (from.line != to.line || newText.length > 1) gutterDirty = true; + + var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line); + // First adjust the line structure, taking some care to leave highlighting intact. + if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == "") { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = [], prevLine = null; + if (from.line) { + prevLine = getLine(from.line - 1); + prevLine.fixMarkEnds(lastLine); + } else lastLine.fixMarkStarts(); + for (var i = 0, e = newText.length - 1; i < e; ++i) + added.push(Line.inheritMarks(newText[i], prevLine)); + if (nlines) doc.remove(from.line, nlines, callbacks); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (newText.length == 1) + firstLine.replace(from.ch, to.ch, newText[0]); + else { + lastLine = firstLine.split(to.ch, newText[newText.length-1]); + firstLine.replace(from.ch, null, newText[0]); + firstLine.fixMarkEnds(lastLine); + var added = []; + for (var i = 1, e = newText.length - 1; i < e; ++i) + added.push(Line.inheritMarks(newText[i], firstLine)); + added.push(lastLine); + doc.insert(from.line + 1, added); + } + } else if (newText.length == 1) { + firstLine.replace(from.ch, null, newText[0]); + lastLine.replace(null, to.ch, ""); + firstLine.append(lastLine); + doc.remove(from.line + 1, nlines, callbacks); + } else { + var added = []; + firstLine.replace(from.ch, null, newText[0]); + lastLine.replace(null, to.ch, newText[newText.length-1]); + firstLine.fixMarkEnds(lastLine); + for (var i = 1, e = newText.length - 1; i < e; ++i) + added.push(Line.inheritMarks(newText[i], firstLine)); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks); + doc.insert(from.line + 1, added); + } + if (options.lineWrapping) { + var perLine = scroller.clientWidth / charWidth() - 3; + doc.iter(from.line, from.line + newText.length, function(line) { + if (line.hidden) return; + var guess = Math.ceil(line.text.length / perLine) || 1; + if (guess != line.height) updateLineHeight(line, guess); + }); + } else { + doc.iter(from.line, i + newText.length, function(line) { + var l = line.text; + if (l.length > maxLineLength) { + maxLine = l; maxLineLength = l.length; maxWidth = null; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) { + maxLineLength = 0; maxLine = ""; maxWidth = null; + doc.iter(0, doc.size, function(line) { + var l = line.text; + if (l.length > maxLineLength) { + maxLineLength = l.length; maxLine = l; + } + }); + } + } + + // Add these lines to the work array, so that they will be + // highlighted. Adjust work lines if lines were added/removed. + var newWork = [], lendiff = newText.length - nlines - 1; + for (var i = 0, l = work.length; i < l; ++i) { + var task = work[i]; + if (task < from.line) newWork.push(task); + else if (task > to.line) newWork.push(task + lendiff); + } + var hlEnd = from.line + Math.min(newText.length, 500); + highlightLines(from.line, hlEnd); + newWork.push(hlEnd); + work = newWork; + startWorker(100); + // Remember that these lines changed, for updating the display + changes.push({from: from.line, to: to.line + 1, diff: lendiff}); + var changeObj = {from: from, to: to, text: newText}; + if (textChanged) { + for (var cur = textChanged; cur.next; cur = cur.next) {} + cur.next = changeObj; + } else textChanged = changeObj; + + // Update the selection + function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;} + setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line)); + + // Make sure the scroll-size div has the correct height. + code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px"; + } + + function replaceRange(code, from, to) { + from = clipPos(from); + if (!to) to = from; else to = clipPos(to); + code = splitLines(code); + function adjustPos(pos) { + if (posLess(pos, from)) return pos; + if (!posLess(to, pos)) return end; + var line = pos.line + code.length - (to.line - from.line) - 1; + var ch = pos.ch; + if (pos.line == to.line) + ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0)); + return {line: line, ch: ch}; + } + var end; + replaceRange1(code, from, to, function(end1) { + end = end1; + return {from: adjustPos(sel.from), to: adjustPos(sel.to)}; + }); + return end; + } + function replaceSelection(code, collapse) { + replaceRange1(splitLines(code), sel.from, sel.to, function(end) { + if (collapse == "end") return {from: end, to: end}; + else if (collapse == "start") return {from: sel.from, to: sel.from}; + else return {from: sel.from, to: end}; + }); + } + function replaceRange1(code, from, to, computeSel) { + var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length; + var newSel = computeSel({line: from.line + code.length - 1, ch: endch}); + updateLines(from, to, code, newSel.from, newSel.to); + } + + function getRange(from, to) { + var l1 = from.line, l2 = to.line; + if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch); + var code = [getLine(l1).text.slice(from.ch)]; + doc.iter(l1 + 1, l2, function(line) { code.push(line.text); }); + code.push(getLine(l2).text.slice(0, to.ch)); + return code.join("\n"); + } + function getSelection() { + return getRange(sel.from, sel.to); + } + + var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll + function slowPoll() { + if (pollingFast) return; + poll.set(options.pollInterval, function() { + startOperation(); + readInput(); + if (focused) slowPoll(); + endOperation(); + }); + } + function fastPoll() { + var missed = false; + pollingFast = true; + function p() { + startOperation(); + var changed = readInput(); + if (!changed && !missed) {missed = true; poll.set(60, p);} + else {pollingFast = false; slowPoll();} + endOperation(); + } + poll.set(20, p); + } + + // Previnput is a hack to work with IME. If we reset the textarea + // on every change, that breaks IME. So we look for changes + // compared to the previous content instead. (Modern browsers have + // events that indicate IME taking place, but these are not widely + // supported or compatible enough yet to rely on.) + var prevInput = ""; + function readInput() { + if (leaveInputAlone || !focused || hasSelection(input)) return false; + var text = input.value; + if (text == prevInput) return false; + shiftSelecting = null; + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput[same] == text[same]) ++same; + if (same < prevInput.length) + sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)}; + else if (overwrite && posEq(sel.from, sel.to)) + sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))}; + replaceSelection(text.slice(same), "end"); + prevInput = text; + return true; + } + function resetInput(user) { + if (!posEq(sel.from, sel.to)) { + prevInput = ""; + input.value = getSelection(); + input.select(); + } else if (user) prevInput = input.value = ""; + } + + function focusInput() { + if (!options.readOnly) input.focus(); + } + + function scrollEditorIntoView() { + if (!cursor.getBoundingClientRect) return; + var rect = cursor.getBoundingClientRect(); + // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden + if (ie && rect.top == rect.bottom) return; + var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); + if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView(); + } + function scrollCursorIntoView() { + var cursor = localCoords(sel.inverted ? sel.from : sel.to); + var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x; + return scrollIntoView(x, cursor.y, x, cursor.yBot); + } + function scrollIntoView(x1, y1, x2, y2) { + var pl = paddingLeft(), pt = paddingTop(), lh = textHeight(); + y1 += pt; y2 += pt; x1 += pl; x2 += pl; + var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true; + if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;} + else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;} + + var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft; + var gutterw = options.fixedGutter ? gutter.clientWidth : 0; + if (x1 < screenleft + gutterw) { + if (x1 < 50) x1 = 0; + scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw); + scrolled = true; + } + else if (x2 > screenw + screenleft - 3) { + scroller.scrollLeft = x2 + 10 - screenw; + scrolled = true; + if (x2 > code.clientWidth) result = false; + } + if (scrolled && options.onScroll) options.onScroll(instance); + return result; + } + + function visibleLines() { + var lh = textHeight(), top = scroller.scrollTop - paddingTop(); + var from_height = Math.max(0, Math.floor(top / lh)); + var to_height = Math.ceil((top + scroller.clientHeight) / lh); + return {from: lineAtHeight(doc, from_height), + to: lineAtHeight(doc, to_height)}; + } + // Uses a set of changes plus the current scroll position to + // determine which DOM updates have to be made, and makes the + // updates. + function updateDisplay(changes, suppressCallback) { + if (!scroller.clientWidth) { + showingFrom = showingTo = displayOffset = 0; + return; + } + // Compute the new visible window + var visible = visibleLines(); + // Bail out if the visible area is already rendered and nothing changed. + if (changes !== true && changes.length == 0 && visible.from >= showingFrom && visible.to <= showingTo) return; + var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100); + if (showingFrom < from && from - showingFrom < 20) from = showingFrom; + if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo); + + // Create a range of theoretically intact lines, and punch holes + // in that using the change info. + var intact = changes === true ? [] : + computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes); + // Clip off the parts that won't be visible + var intactLines = 0; + for (var i = 0; i < intact.length; ++i) { + var range = intact[i]; + if (range.from < from) {range.domStart += (from - range.from); range.from = from;} + if (range.to > to) range.to = to; + if (range.from >= range.to) intact.splice(i--, 1); + else intactLines += range.to - range.from; + } + if (intactLines == to - from) return; + intact.sort(function(a, b) {return a.domStart - b.domStart;}); + + var th = textHeight(), gutterDisplay = gutter.style.display; + lineDiv.style.display = gutter.style.display = "none"; + patchDisplay(from, to, intact); + lineDiv.style.display = ""; + + // Position the mover div to align with the lines it's supposed + // to be showing (which will cover the visible display) + var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th; + // This is just a bogus formula that detects when the editor is + // resized or the font size changes. + if (different) lastSizeC = scroller.clientHeight + th; + showingFrom = from; showingTo = to; + displayOffset = heightAtLine(doc, from); + mover.style.top = (displayOffset * th) + "px"; + code.style.height = (doc.height * th + 2 * paddingTop()) + "px"; + + // Since this is all rather error prone, it is honoured with the + // only assertion in the whole file. + if (lineDiv.childNodes.length != showingTo - showingFrom) + throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) + + " nodes=" + lineDiv.childNodes.length); + + if (options.lineWrapping) { + maxWidth = scroller.clientWidth; + var curNode = lineDiv.firstChild; + doc.iter(showingFrom, showingTo, function(line) { + if (!line.hidden) { + var height = Math.round(curNode.offsetHeight / th) || 1; + if (line.height != height) {updateLineHeight(line, height); gutterDirty = true;} + } + curNode = curNode.nextSibling; + }); + } else { + if (maxWidth == null) maxWidth = stringWidth(maxLine); + if (maxWidth > scroller.clientWidth) { + lineSpace.style.width = maxWidth + "px"; + // Needed to prevent odd wrapping/hiding of widgets placed in here. + code.style.width = ""; + code.style.width = scroller.scrollWidth + "px"; + } else { + lineSpace.style.width = code.style.width = ""; + } + } + gutter.style.display = gutterDisplay; + if (different || gutterDirty) updateGutter(); + updateCursor(); + if (!suppressCallback && options.onUpdate) options.onUpdate(instance); + return true; + } + + function computeIntact(intact, changes) { + for (var i = 0, l = changes.length || 0; i < l; ++i) { + var change = changes[i], intact2 = [], diff = change.diff || 0; + for (var j = 0, l2 = intact.length; j < l2; ++j) { + var range = intact[j]; + if (change.to <= range.from && change.diff) + intact2.push({from: range.from + diff, to: range.to + diff, + domStart: range.domStart}); + else if (change.to <= range.from || change.from >= range.to) + intact2.push(range); + else { + if (change.from > range.from) + intact2.push({from: range.from, to: change.from, domStart: range.domStart}); + if (change.to < range.to) + intact2.push({from: change.to + diff, to: range.to + diff, + domStart: range.domStart + (change.to - range.from)}); + } + } + intact = intact2; + } + return intact; + } + + function patchDisplay(from, to, intact) { + // The first pass removes the DOM nodes that aren't intact. + if (!intact.length) lineDiv.innerHTML = ""; + else { + function killNode(node) { + var tmp = node.nextSibling; + node.parentNode.removeChild(node); + return tmp; + } + var domPos = 0, curNode = lineDiv.firstChild, n; + for (var i = 0; i < intact.length; ++i) { + var cur = intact[i]; + while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;} + for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;} + } + while (curNode) curNode = killNode(curNode); + } + // This pass fills in the lines that actually changed. + var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from; + var sfrom = sel.from.line, sto = sel.to.line, inSel = sfrom < from && sto >= from; + var scratch = targetDocument.createElement("div"), newElt; + doc.iter(from, to, function(line) { + var ch1 = null, ch2 = null; + if (inSel) { + ch1 = 0; + if (sto == j) {inSel = false; ch2 = sel.to.ch;} + } else if (sfrom == j) { + if (sto == j) {ch1 = sel.from.ch; ch2 = sel.to.ch;} + else {inSel = true; ch1 = sel.from.ch;} + } + if (nextIntact && nextIntact.to == j) nextIntact = intact.shift(); + if (!nextIntact || nextIntact.from > j) { + if (line.hidden) scratch.innerHTML = "
";
+          else scratch.innerHTML = line.getHTML(ch1, ch2, true, tabText);
+          lineDiv.insertBefore(scratch.firstChild, curNode);
+        } else {
+          curNode = curNode.nextSibling;
+        }
+        ++j;
+      });
+    }
+
+    function updateGutter() {
+      if (!options.gutter && !options.lineNumbers) return;
+      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
+      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
+      var html = [], i = showingFrom;
+      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
+        if (line.hidden) {
+          html.push("
");
+        } else {
+          var marker = line.gutterMarker;
+          var text = options.lineNumbers ? i + options.firstLineNumber : null;
+          if (marker && marker.text)
+            text = marker.text.replace("%N%", text != null ? text : "");
+          else if (text == null)
+            text = "\u00a0";
+          html.push((marker && marker.style ? '
' : "
"), text);
+          for (var j = 1; j < line.height; ++j) html.push("
 "); + html.push("
"); + } + ++i; + }); + gutter.style.display = "none"; + gutterText.innerHTML = html.join(""); + var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = ""; + while (val.length + pad.length < minwidth) pad += "\u00a0"; + if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild); + gutter.style.display = ""; + lineSpace.style.marginLeft = gutter.offsetWidth + "px"; + gutterDirty = false; + } + function updateCursor() { + var head = sel.inverted ? sel.from : sel.to, lh = textHeight(); + var pos = localCoords(head, true); + var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv); + inputDiv.style.top = (pos.y + lineOff.top - wrapOff.top) + "px"; + inputDiv.style.left = (pos.x + lineOff.left - wrapOff.left) + "px"; + if (posEq(sel.from, sel.to)) { + cursor.style.top = pos.y + "px"; + cursor.style.left = (options.lineWrapping ? Math.min(pos.x, lineSpace.offsetWidth) : pos.x) + "px"; + cursor.style.display = ""; + } + else cursor.style.display = "none"; + } + + function setShift(val) { + if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from); + else shiftSelecting = null; + } + function setSelectionUser(from, to) { + var sh = shiftSelecting && clipPos(shiftSelecting); + if (sh) { + if (posLess(sh, from)) from = sh; + else if (posLess(to, sh)) to = sh; + } + setSelection(from, to); + userSelChange = true; + } + // Update the selection. Last two args are only used by + // updateLines, since they have to be expressed in the line + // numbers before the update. + function setSelection(from, to, oldFrom, oldTo) { + goalColumn = null; + if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;} + if (posEq(sel.from, from) && posEq(sel.to, to)) return; + if (posLess(to, from)) {var tmp = to; to = from; from = tmp;} + + // Skip over hidden lines. + if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch); + if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch); + + if (posEq(from, to)) sel.inverted = false; + else if (posEq(from, sel.to)) sel.inverted = false; + else if (posEq(to, sel.from)) sel.inverted = true; + + // Some ugly logic used to only mark the lines that actually did + // see a change in selection as changed, rather than the whole + // selected range. + if (posEq(from, to)) { + if (!posEq(sel.from, sel.to)) + changes.push({from: oldFrom, to: oldTo + 1}); + } + else if (posEq(sel.from, sel.to)) { + changes.push({from: from.line, to: to.line + 1}); + } + else { + if (!posEq(from, sel.from)) { + if (from.line < oldFrom) + changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1}); + else + changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1}); + } + if (!posEq(to, sel.to)) { + if (to.line < oldTo) + changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1}); + else + changes.push({from: Math.max(from.line, oldTo), to: to.line + 1}); + } + } + sel.from = from; sel.to = to; + selectionChanged = true; + } + function skipHidden(pos, oldLine, oldCh) { + function getNonHidden(dir) { + var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1; + while (lNo != end) { + var line = getLine(lNo); + if (!line.hidden) { + var ch = pos.ch; + if (ch > oldCh || ch > line.text.length) ch = line.text.length; + return {line: lNo, ch: ch}; + } + lNo += dir; + } + } + var line = getLine(pos.line); + if (!line.hidden) return pos; + if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1); + else return getNonHidden(-1) || getNonHidden(1); + } + function setCursor(line, ch, user) { + var pos = clipPos({line: line, ch: ch || 0}); + (user ? setSelectionUser : setSelection)(pos, pos); + } + + function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));} + function clipPos(pos) { + if (pos.line < 0) return {line: 0, ch: 0}; + if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length}; + var ch = pos.ch, linelen = getLine(pos.line).text.length; + if (ch == null || ch > linelen) return {line: pos.line, ch: linelen}; + else if (ch < 0) return {line: pos.line, ch: 0}; + else return pos; + } + + function findPosH(dir, unit) { + var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch; + var lineObj = getLine(line); + function findNextLine() { + for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) { + var lo = getLine(l); + if (!lo.hidden) { line = l; lineObj = lo; return true; } + } + } + function moveOnce(boundToLine) { + if (ch == (dir < 0 ? 0 : lineObj.text.length)) { + if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0; + else return false; + } else ch += dir; + return true; + } + if (unit == "char") moveOnce(); + else if (unit == "column") moveOnce(true); + else if (unit == "word") { + var sawWord = false; + for (;;) { + if (dir < 0) if (!moveOnce()) break; + if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; + else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;} + if (dir > 0) if (!moveOnce()) break; + } + } + return {line: line, ch: ch}; + } + function moveH(dir, unit) { + var pos = dir < 0 ? sel.from : sel.to; + if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit); + setCursor(pos.line, pos.ch, true); + } + function deleteH(dir, unit) { + if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to); + else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to); + else replaceRange("", sel.from, findPosH(dir, unit)); + userSelChange = true; + } + var goalColumn = null; + function moveV(dir, unit) { + var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true); + if (goalColumn != null) pos.x = goalColumn; + if (unit == "page") dist = scroller.clientHeight; + else if (unit == "line") dist = textHeight(); + var target = coordsChar(pos.x, pos.y + dist * dir + 2); + setCursor(target.line, target.ch, true); + goalColumn = pos.x; + } + + function selectWordAt(pos) { + var line = getLine(pos.line).text; + var start = pos.ch, end = pos.ch; + while (start > 0 && isWordChar(line.charAt(start - 1))) --start; + while (end < line.length && isWordChar(line.charAt(end))) ++end; + setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end}); + } + function selectLine(line) { + setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length}); + } + function indentSelected(mode) { + if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode); + var e = sel.to.line - (sel.to.ch ? 0 : 1); + for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode); + } + + function indentLine(n, how) { + if (!how) how = "add"; + if (how == "smart") { + if (!mode.indent) how = "prev"; + else var state = getStateBefore(n); + } + + var line = getLine(n), curSpace = line.indentation(options.tabSize), + curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (how == "prev") { + if (n) indentation = getLine(n-1).indentation(options.tabSize); + else indentation = 0; + } + else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text); + else if (how == "add") indentation = curSpace + options.indentUnit; + else if (how == "subtract") indentation = curSpace - options.indentUnit; + indentation = Math.max(0, indentation); + var diff = indentation - curSpace; + + if (!diff) { + if (sel.from.line != n && sel.to.line != n) return; + var indentString = curSpaceString; + } + else { + var indentString = "", pos = 0; + if (options.indentWithTabs) + for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";} + while (pos < indentation) {++pos; indentString += " ";} + } + + replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}); + } + + function loadMode() { + mode = CodeMirror.getMode(options, options.mode); + doc.iter(0, doc.size, function(line) { line.stateAfter = null; }); + work = [0]; + startWorker(); + } + function gutterChanged() { + var visible = options.gutter || options.lineNumbers; + gutter.style.display = visible ? "" : "none"; + if (visible) gutterDirty = true; + else lineDiv.parentNode.style.marginLeft = 0; + } + function wrappingChanged(from, to) { + if (options.lineWrapping) { + wrapper.className += " CodeMirror-wrap"; + var perLine = scroller.clientWidth / charWidth() - 3; + doc.iter(0, doc.size, function(line) { + if (line.hidden) return; + var guess = Math.ceil(line.text.length / perLine) || 1; + if (guess != 1) updateLineHeight(line, guess); + }); + lineSpace.style.width = code.style.width = ""; + } else { + wrapper.className = wrapper.className.replace(" CodeMirror-wrap", ""); + maxWidth = null; maxLine = ""; + doc.iter(0, doc.size, function(line) { + if (line.height != 1 && !line.hidden) updateLineHeight(line, 1); + if (line.text.length > maxLine.length) maxLine = line.text; + }); + } + changes.push({from: 0, to: doc.size}); + } + function computeTabText() { + for (var str = '', i = 0; i < options.tabSize; ++i) str += " "; + return str + ""; + } + function tabsChanged() { + tabText = computeTabText(); + updateDisplay(true); + } + function themeChanged() { + scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") + + options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + } + + function TextMarker() { this.set = []; } + TextMarker.prototype.clear = operation(function() { + var min = Infinity, max = -Infinity; + for (var i = 0, e = this.set.length; i < e; ++i) { + var line = this.set[i], mk = line.marked; + if (!mk || !line.parent) continue; + var lineN = lineNo(line); + min = Math.min(min, lineN); max = Math.max(max, lineN); + for (var j = 0; j < mk.length; ++j) + if (mk[j].set == this.set) mk.splice(j--, 1); + } + if (min != Infinity) + changes.push({from: min, to: max + 1}); + }); + TextMarker.prototype.find = function() { + var from, to; + for (var i = 0, e = this.set.length; i < e; ++i) { + var line = this.set[i], mk = line.marked; + for (var j = 0; j < mk.length; ++j) { + var mark = mk[j]; + if (mark.set == this.set) { + if (mark.from != null || mark.to != null) { + var found = lineNo(line); + if (found != null) { + if (mark.from != null) from = {line: found, ch: mark.from}; + if (mark.to != null) to = {line: found, ch: mark.to}; + } + } + } + } + } + return {from: from, to: to}; + }; + + function markText(from, to, className) { + from = clipPos(from); to = clipPos(to); + var tm = new TextMarker(); + function add(line, from, to, className) { + getLine(line).addMark(new MarkedText(from, to, className, tm.set)); + } + if (from.line == to.line) add(from.line, from.ch, to.ch, className); + else { + add(from.line, from.ch, null, className); + for (var i = from.line + 1, e = to.line; i < e; ++i) + add(i, null, null, className); + add(to.line, null, to.ch, className); + } + changes.push({from: from.line, to: to.line + 1}); + return tm; + } + + function setBookmark(pos) { + pos = clipPos(pos); + var bm = new Bookmark(pos.ch); + getLine(pos.line).addMark(bm); + return bm; + } + + function addGutterMarker(line, text, className) { + if (typeof line == "number") line = getLine(clipLine(line)); + line.gutterMarker = {text: text, style: className}; + gutterDirty = true; + return line; + } + function removeGutterMarker(line) { + if (typeof line == "number") line = getLine(clipLine(line)); + line.gutterMarker = null; + gutterDirty = true; + } + + function changeLine(handle, op) { + var no = handle, line = handle; + if (typeof handle == "number") line = getLine(clipLine(handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no)) changes.push({from: no, to: no + 1}); + else return null; + return line; + } + function setLineClass(handle, className) { + return changeLine(handle, function(line) { + if (line.className != className) { + line.className = className; + return true; + } + }); + } + function setLineHidden(handle, hidden) { + return changeLine(handle, function(line, no) { + if (line.hidden != hidden) { + line.hidden = hidden; + updateLineHeight(line, hidden ? 0 : 1); + if (hidden && (sel.from.line == no || sel.to.line == no)) + setSelection(skipHidden(sel.from, sel.from.line, sel.from.ch), + skipHidden(sel.to, sel.to.line, sel.to.ch)); + return (gutterDirty = true); + } + }); + } + + function lineInfo(line) { + if (typeof line == "number") { + if (!isLine(line)) return null; + var n = line; + line = getLine(line); + if (!line) return null; + } + else { + var n = lineNo(line); + if (n == null) return null; + } + var marker = line.gutterMarker; + return {line: n, handle: line, text: line.text, markerText: marker && marker.text, + markerClass: marker && marker.style, lineClass: line.className}; + } + + function stringWidth(str) { + measure.innerHTML = "
x
"; + measure.firstChild.firstChild.firstChild.nodeValue = str; + return measure.firstChild.firstChild.offsetWidth || 10; + } + // These are used to go from pixel positions to character + // positions, taking varying character widths into account. + function charFromX(line, x) { + if (x <= 0) return 0; + var lineObj = getLine(line), text = lineObj.text; + function getX(len) { + measure.innerHTML = "
" + lineObj.getHTML(null, null, false, tabText, len) + "
"; + return measure.firstChild.firstChild.offsetWidth; + } + var from = 0, fromX = 0, to = text.length, toX; + // Guess a suitable upper bound for our search. + var estimated = Math.min(to, Math.ceil(x / charWidth())); + for (;;) { + var estX = getX(estimated); + if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); + else {toX = estX; to = estimated; break;} + } + if (x > toX) return to; + // Try to guess a suitable lower bound as well. + estimated = Math.floor(to * 0.8); estX = getX(estimated); + if (estX < x) {from = estimated; fromX = estX;} + // Do a binary search between these bounds. + for (;;) { + if (to - from <= 1) return (toX - x > x - fromX) ? from : to; + var middle = Math.ceil((from + to) / 2), middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX;} + else {from = middle; fromX = middleX;} + } + } + + var tempId = Math.floor(Math.random() * 0xffffff).toString(16); + function measureLine(line, ch) { + var extra = ""; + // Include extra text at the end to make sure the measured line is wrapped in the right way. + if (options.lineWrapping) { + var end = line.text.indexOf(" ", ch + 2); + extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0))); + } + measure.innerHTML = "
" + line.getHTML(null, null, false, tabText, ch) +
+        '' + htmlEscape(line.text.charAt(ch) || " ") + "" +
+        extra + "
"; + var elt = document.getElementById("CodeMirror-temp-" + tempId); + var top = elt.offsetTop, left = elt.offsetLeft; + // Older IEs report zero offsets for spans directly after a wrap + if (ie && ch && top == 0 && left == 0) { + var backup = document.createElement("span"); + backup.innerHTML = "x"; + elt.parentNode.insertBefore(backup, elt.nextSibling); + top = backup.offsetTop; + } + return {top: top, left: left}; + } + function localCoords(pos, inLineWrap) { + var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0)); + if (pos.ch == 0) x = 0; + else { + var sp = measureLine(getLine(pos.line), pos.ch); + x = sp.left; + if (options.lineWrapping) y += Math.max(0, sp.top); + } + return {x: x, y: y, yBot: y + lh}; + } + // Coords must be lineSpace-local + function coordsChar(x, y) { + if (y < 0) y = 0; + var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th); + var lineNo = lineAtHeight(doc, heightPos); + if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length}; + var lineObj = getLine(lineNo), text = lineObj.text; + var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0; + if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0}; + function getX(len) { + var sp = measureLine(lineObj, len); + if (tw) { + var off = Math.round(sp.top / th); + return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth); + } + return sp.left; + } + var from = 0, fromX = 0, to = text.length, toX; + // Guess a suitable upper bound for our search. + var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw)); + for (;;) { + var estX = getX(estimated); + if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); + else {toX = estX; to = estimated; break;} + } + if (x > toX) return {line: lineNo, ch: to}; + // Try to guess a suitable lower bound as well. + estimated = Math.floor(to * 0.8); estX = getX(estimated); + if (estX < x) {from = estimated; fromX = estX;} + // Do a binary search between these bounds. + for (;;) { + if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to}; + var middle = Math.ceil((from + to) / 2), middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX;} + else {from = middle; fromX = middleX;} + } + } + function pageCoords(pos) { + var local = localCoords(pos, true), off = eltOffset(lineSpace); + return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot}; + } + + var cachedHeight, cachedHeightFor, measureText; + function textHeight() { + if (measureText == null) { + measureText = "
";
+        for (var i = 0; i < 49; ++i) measureText += "x
"; + measureText += "x
"; + } + var offsetHeight = lineDiv.clientHeight; + if (offsetHeight == cachedHeightFor) return cachedHeight; + cachedHeightFor = offsetHeight; + measure.innerHTML = measureText; + cachedHeight = measure.firstChild.offsetHeight / 50 || 1; + measure.innerHTML = ""; + return cachedHeight; + } + var cachedWidth, cachedWidthFor = 0; + function charWidth() { + if (scroller.clientWidth == cachedWidthFor) return cachedWidth; + cachedWidthFor = scroller.clientWidth; + return (cachedWidth = stringWidth("x")); + } + function paddingTop() {return lineSpace.offsetTop;} + function paddingLeft() {return lineSpace.offsetLeft;} + + function posFromMouse(e, liberal) { + var offW = eltOffset(scroller, true), x, y; + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX; y = e.clientY; } catch (e) { return null; } + // This is a mess of a heuristic to try and determine whether a + // scroll-bar was clicked or not, and to return null if one was + // (and !liberal). + if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight)) + return null; + var offL = eltOffset(lineSpace, true); + return coordsChar(x - offL.left, y - offL.top); + } + function onContextMenu(e) { + var pos = posFromMouse(e); + if (!pos || window.opera) return; // Opera is difficult. + if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) + operation(setCursor)(pos.line, pos.ch); + + var oldCSS = input.style.cssText; + inputDiv.style.position = "absolute"; + input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " + + "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + leaveInputAlone = true; + var val = input.value = getSelection(); + focusInput(); + input.select(); + function rehide() { + var newVal = splitLines(input.value).join("\n"); + if (newVal != val) operation(replaceSelection)(newVal, "end"); + inputDiv.style.position = "relative"; + input.style.cssText = oldCSS; + leaveInputAlone = false; + resetInput(true); + slowPoll(); + } + + if (gecko) { + e_stop(e); + var mouseup = connect(window, "mouseup", function() { + mouseup(); + setTimeout(rehide, 20); + }, true); + } + else { + setTimeout(rehide, 50); + } + } + + // Cursor-blinking + function restartBlink() { + clearInterval(blinker); + var on = true; + cursor.style.visibility = ""; + blinker = setInterval(function() { + cursor.style.visibility = (on = !on) ? "" : "hidden"; + }, 650); + } + + var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; + function matchBrackets(autoclear) { + var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1; + var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; + if (!match) return; + var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles; + for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2) + if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;} + + var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; + function scan(line, from, to) { + if (!line.text) return; + var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur; + for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) { + var text = st[i]; + if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;} + for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) { + if (pos >= from && pos < to && re.test(cur = text.charAt(j))) { + var match = matching[cur]; + if (match.charAt(1) == ">" == forward) stack.push(cur); + else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; + else if (!stack.length) return {pos: pos, match: true}; + } + } + } + } + for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) { + var line = getLine(i), first = i == head.line; + var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length); + if (found) break; + } + if (!found) found = {pos: null, match: false}; + var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; + var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style), + two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style); + var clear = operation(function(){one.clear(); two && two.clear();}); + if (autoclear) setTimeout(clear, 800); + else bracketHighlighted = clear; + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(n) { + var minindent, minline; + for (var search = n, lim = n - 40; search > lim; --search) { + if (search == 0) return 0; + var line = getLine(search-1); + if (line.stateAfter) return search; + var indented = line.indentation(options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + function getStateBefore(n) { + var start = findStartLine(n), state = start && getLine(start-1).stateAfter; + if (!state) state = startState(mode); + else state = copyState(mode, state); + doc.iter(start, n, function(line) { + line.highlight(mode, state, options.tabSize); + line.stateAfter = copyState(mode, state); + }); + if (start < n) changes.push({from: start, to: n}); + if (n < doc.size && !getLine(n).stateAfter) work.push(n); + return state; + } + function highlightLines(start, end) { + var state = getStateBefore(start); + doc.iter(start, end, function(line) { + line.highlight(mode, state, options.tabSize); + line.stateAfter = copyState(mode, state); + }); + } + function highlightWorker() { + var end = +new Date + options.workTime; + var foundWork = work.length; + while (work.length) { + if (!getLine(showingFrom).stateAfter) var task = showingFrom; + else var task = work.pop(); + if (task >= doc.size) continue; + var start = findStartLine(task), state = start && getLine(start-1).stateAfter; + if (state) state = copyState(mode, state); + else state = startState(mode); + + var unchanged = 0, compare = mode.compareStates, realChange = false, + i = start, bail = false; + doc.iter(i, doc.size, function(line) { + var hadState = line.stateAfter; + if (+new Date > end) { + work.push(i); + startWorker(options.workDelay); + if (realChange) changes.push({from: task, to: i + 1}); + return (bail = true); + } + var changed = line.highlight(mode, state, options.tabSize); + if (changed) realChange = true; + line.stateAfter = copyState(mode, state); + if (compare) { + if (hadState && compare(hadState, state)) return true; + } else { + if (changed !== false || !hadState) unchanged = 0; + else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, ""))) + return true; + } + ++i; + }); + if (bail) return; + if (realChange) changes.push({from: task, to: i + 1}); + } + if (foundWork && options.onHighlightComplete) + options.onHighlightComplete(instance); + } + function startWorker(time) { + if (!work.length) return; + highlight.set(time, operation(highlightWorker)); + } + + // Operations are used to wrap changes in such a way that each + // change won't have to update the cursor and display (which would + // be awkward, slow, and error-prone), but instead updates are + // batched and then all combined and executed at once. + function startOperation() { + updateInput = userSelChange = textChanged = null; + changes = []; selectionChanged = false; callbacks = []; + } + function endOperation() { + var reScroll = false, updated; + if (selectionChanged) reScroll = !scrollCursorIntoView(); + if (changes.length) updated = updateDisplay(changes, true); + else { + if (selectionChanged) updateCursor(); + if (gutterDirty) updateGutter(); + } + if (reScroll) scrollCursorIntoView(); + if (selectionChanged) {scrollEditorIntoView(); restartBlink();} + + if (focused && !leaveInputAlone && + (updateInput === true || (updateInput !== false && selectionChanged))) + resetInput(userSelChange); + + if (selectionChanged && options.matchBrackets) + setTimeout(operation(function() { + if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;} + if (posEq(sel.from, sel.to)) matchBrackets(false); + }), 20); + var tc = textChanged, cbs = callbacks; // these can be reset by callbacks + if (selectionChanged && options.onCursorActivity) + options.onCursorActivity(instance); + if (tc && options.onChange && instance) + options.onChange(instance, tc); + for (var i = 0; i < cbs.length; ++i) cbs[i](instance); + if (updated && options.onUpdate) options.onUpdate(instance); + } + var nestedOperation = 0; + function operation(f) { + return function() { + if (!nestedOperation++) startOperation(); + try {var result = f.apply(this, arguments);} + finally {if (!--nestedOperation) endOperation();} + return result; + }; + } + + for (var ext in extensions) + if (extensions.propertyIsEnumerable(ext) && + !instance.propertyIsEnumerable(ext)) + instance[ext] = extensions[ext]; + return instance; + } // (end of function CodeMirror) + + // The default configuration options. + CodeMirror.defaults = { + value: "", + mode: null, + theme: "default", + indentUnit: 2, + indentWithTabs: false, + tabSize: 4, + keyMap: "default", + extraKeys: null, + electricChars: true, + onKeyEvent: null, + lineWrapping: false, + lineNumbers: false, + gutter: false, + fixedGutter: false, + firstLineNumber: 1, + readOnly: false, + onChange: null, + onCursorActivity: null, + onGutterClick: null, + onHighlightComplete: null, + onUpdate: null, + onFocus: null, onBlur: null, onScroll: null, + matchBrackets: false, + workTime: 100, + workDelay: 200, + pollInterval: 100, + undoDepth: 40, + tabindex: null, + document: window.document + }; + + var mac = /Mac/.test(navigator.platform); + var win = /Win/.test(navigator.platform); + + // Known modes, by name and by MIME + var modes = {}, mimeModes = {}; + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + modes[name] = mode; + }; + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + CodeMirror.getMode = function(options, spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) + spec = mimeModes[spec]; + if (typeof spec == "string") + var mname = spec, config = {}; + else if (spec != null) + var mname = spec.name, config = spec; + var mfactory = modes[mname]; + if (!mfactory) { + if (window.console) console.warn("No mode " + mname + " found, falling back to plain text."); + return CodeMirror.getMode(options, "text/plain"); + } + return mfactory(options, config || {}); + }; + CodeMirror.listModes = function() { + var list = []; + for (var m in modes) + if (modes.propertyIsEnumerable(m)) list.push(m); + return list; + }; + CodeMirror.listMIMEs = function() { + var list = []; + for (var m in mimeModes) + if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]}); + return list; + }; + + var extensions = CodeMirror.extensions = {}; + CodeMirror.defineExtension = function(name, func) { + extensions[name] = func; + }; + + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});}, + killLine: function(cm) { + var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); + if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0}); + else cm.replaceRange("", from, sel ? to : {line: from.line}); + }, + deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});}, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + goDocStart: function(cm) {cm.setCursor(0, 0, true);}, + goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);}, + goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);}, + goLineStartSmart: function(cm) { + var cur = cm.getCursor(); + var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/)); + cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true); + }, + goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);}, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharLeft: function(cm) {cm.deleteH(-1, "char");}, + delCharRight: function(cm) {cm.deleteH(1, "char");}, + delWordLeft: function(cm) {cm.deleteH(-1, "word");}, + delWordRight: function(cm) {cm.deleteH(1, "word");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t", "end");}, + transposeChars: function(cm) { + var cur = cm.getCursor(), line = cm.getLine(cur.line); + if (cur.ch > 0 && cur.ch < line.length - 1) + cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), + {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1}); + }, + newlineAndIndent: function(cm) { + cm.replaceSelection("\n", "end"); + cm.indentLine(cm.getCursor().line); + }, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + var keyMap = CodeMirror.keyMap = {}; + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "indentMore", "Shift-Tab": "indentLess", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" + }; + // Note that the save and find-related commands aren't defined by + // default. Unknown commands are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + fallthrough: "basic" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft", + "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft", + "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageUp", "Shift-Ctrl-V": "goPageDown", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft", + "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" + }; + + function lookupKey(name, extraMap, map) { + function lookup(name, map, ft) { + var found = map[name]; + if (found != null) return found; + if (ft == null) ft = map.fallthrough; + if (ft == null) return map.catchall; + if (typeof ft == "string") return lookup(name, keyMap[ft]); + for (var i = 0, e = ft.length; i < e; ++i) { + found = lookup(name, keyMap[ft[i]]); + if (found != null) return found; + } + return null; + } + return extraMap ? lookup(name, extraMap, map) : lookup(name, keyMap[map]); + } + function isModifierKey(event) { + var name = keyNames[event.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + } + + CodeMirror.fromTextArea = function(textarea, options) { + if (!options) options = {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabindex) + options.tabindex = textarea.tabindex; + + function save() {textarea.value = instance.getValue();} + if (textarea.form) { + // Deplorable hack to make the submit method do the right thing. + var rmSubmit = connect(textarea.form, "submit", save, true); + if (typeof textarea.form.submit == "function") { + var realSubmit = textarea.form.submit; + function wrappedSubmit() { + save(); + textarea.form.submit = realSubmit; + textarea.form.submit(); + textarea.form.submit = wrappedSubmit; + } + textarea.form.submit = wrappedSubmit; + } + } + + textarea.style.display = "none"; + var instance = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + instance.save = save; + instance.getTextArea = function() { return textarea; }; + instance.toTextArea = function() { + save(); + textarea.parentNode.removeChild(instance.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + rmSubmit(); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + return instance; + }; + + // Utility functions for working with state. Exported because modes + // sometimes need to do this. + function copyState(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + } + CodeMirror.copyState = copyState; + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + } + CodeMirror.startState = startState; + + // The character stream used by a mode's parser. + function StringStream(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + } + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == 0;}, + peek: function() {return this.string.charAt(this.pos);}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() {return countColumn(this.string, this.start, this.tabSize);}, + indentation: function() {return countColumn(this.string, null, this.tabSize);}, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + function cased(str) {return caseInsensitive ? str.toLowerCase() : str;} + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } + else { + var match = this.string.slice(this.pos).match(pattern); + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);} + }; + CodeMirror.StringStream = StringStream; + + function MarkedText(from, to, className, set) { + this.from = from; this.to = to; this.style = className; this.set = set; + } + MarkedText.prototype = { + attach: function(line) { this.set.push(line); }, + detach: function(line) { + var ix = indexOf(this.set, line); + if (ix > -1) this.set.splice(ix, 1); + }, + split: function(pos, lenBefore) { + if (this.to <= pos && this.to != null) return null; + var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore; + var to = this.to == null ? null : this.to - pos + lenBefore; + return new MarkedText(from, to, this.style, this.set); + }, + dup: function() { return new MarkedText(null, null, this.style, this.set); }, + clipTo: function(fromOpen, from, toOpen, to, diff) { + if (this.from != null && this.from >= from) + this.from = Math.max(to, this.from) + diff; + if (this.to != null && this.to > from) + this.to = to < this.to ? this.to + diff : from; + if (fromOpen && to > this.from && (to < this.to || this.to == null)) + this.from = null; + if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null)) + this.to = null; + }, + isDead: function() { return this.from != null && this.to != null && this.from >= this.to; }, + sameSet: function(x) { return this.set == x.set; } + }; + + function Bookmark(pos) { + this.from = pos; this.to = pos; this.line = null; + } + Bookmark.prototype = { + attach: function(line) { this.line = line; }, + detach: function(line) { if (this.line == line) this.line = null; }, + split: function(pos, lenBefore) { + if (pos < this.from) { + this.from = this.to = (this.from - pos) + lenBefore; + return this; + } + }, + isDead: function() { return this.from > this.to; }, + clipTo: function(fromOpen, from, toOpen, to, diff) { + if ((fromOpen || from < this.from) && (toOpen || to > this.to)) { + this.from = 0; this.to = -1; + } else if (this.from > from) { + this.from = this.to = Math.max(to, this.from) + diff; + } + }, + sameSet: function(x) { return false; }, + find: function() { + if (!this.line || !this.line.parent) return null; + return {line: lineNo(this.line), ch: this.from}; + }, + clear: function() { + if (this.line) { + var found = indexOf(this.line.marked, this); + if (found != -1) this.line.marked.splice(found, 1); + this.line = null; + } + } + }; + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + function Line(text, styles) { + this.styles = styles || [text, null]; + this.text = text; + this.height = 1; + this.marked = this.gutterMarker = this.className = this.handlers = null; + this.stateAfter = this.parent = this.hidden = null; + } + Line.inheritMarks = function(text, orig) { + var ln = new Line(text), mk = orig && orig.marked; + if (mk) { + for (var i = 0; i < mk.length; ++i) { + if (mk[i].to == null && mk[i].style) { + var newmk = ln.marked || (ln.marked = []), mark = mk[i]; + var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln); + } + } + } + return ln; + } + Line.prototype = { + // Replace a piece of a line, keeping the styles around it intact. + replace: function(from, to_, text) { + var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_; + copyStyles(0, from, this.styles, st); + if (text) st.push(text, null); + copyStyles(to, this.text.length, this.styles, st); + this.styles = st; + this.text = this.text.slice(0, from) + text + this.text.slice(to); + this.stateAfter = null; + if (mk) { + var diff = text.length - (to - from); + for (var i = 0, mark = mk[i]; i < mk.length; ++i) { + mark.clipTo(from == null, from || 0, to_ == null, to, diff); + if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);} + } + } + }, + // Split a part off a line, keeping styles and markers intact. + split: function(pos, textBefore) { + var st = [textBefore, null], mk = this.marked; + copyStyles(pos, this.text.length, this.styles, st); + var taken = new Line(textBefore + this.text.slice(pos), st); + if (mk) { + for (var i = 0; i < mk.length; ++i) { + var mark = mk[i]; + var newmark = mark.split(pos, textBefore.length); + if (newmark) { + if (!taken.marked) taken.marked = []; + taken.marked.push(newmark); newmark.attach(taken); + } + } + } + return taken; + }, + append: function(line) { + var mylen = this.text.length, mk = line.marked, mymk = this.marked; + this.text += line.text; + copyStyles(0, line.text.length, line.styles, this.styles); + if (mymk) { + for (var i = 0; i < mymk.length; ++i) + if (mymk[i].to == null) mymk[i].to = mylen; + } + if (mk && mk.length) { + if (!mymk) this.marked = mymk = []; + outer: for (var i = 0; i < mk.length; ++i) { + var mark = mk[i]; + if (!mark.from) { + for (var j = 0; j < mymk.length; ++j) { + var mymark = mymk[j]; + if (mymark.to == mylen && mymark.sameSet(mark)) { + mymark.to = mark.to == null ? null : mark.to + mylen; + if (mymark.isDead()) { + mymark.detach(this); + mk.splice(i--, 1); + } + continue outer; + } + } + } + mymk.push(mark); + mark.attach(this); + mark.from += mylen; + if (mark.to != null) mark.to += mylen; + } + } + }, + fixMarkEnds: function(other) { + var mk = this.marked, omk = other.marked; + if (!mk) return; + for (var i = 0; i < mk.length; ++i) { + var mark = mk[i], close = mark.to == null; + if (close && omk) { + for (var j = 0; j < omk.length; ++j) + if (omk[j].sameSet(mark)) {close = false; break;} + } + if (close) mark.to = this.text.length; + } + }, + fixMarkStarts: function() { + var mk = this.marked; + if (!mk) return; + for (var i = 0; i < mk.length; ++i) + if (mk[i].from == null) mk[i].from = 0; + }, + addMark: function(mark) { + mark.attach(this); + if (this.marked == null) this.marked = []; + this.marked.push(mark); + this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);}); + }, + // Run the given mode's parser over a line, update the styles + // array, which contains alternating fragments of text and CSS + // classes. + highlight: function(mode, state, tabSize) { + var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0; + var changed = false, curWord = st[0], prevWord; + if (this.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state); + var substr = this.text.slice(stream.start, stream.pos); + stream.start = stream.pos; + if (pos && st[pos-1] == style) + st[pos-2] += substr; + else if (substr) { + if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true; + st[pos++] = substr; st[pos++] = style; + prevWord = curWord; curWord = st[pos]; + } + // Give up when line is ridiculously long + if (stream.pos > 5000) { + st[pos++] = this.text.slice(stream.pos); st[pos++] = null; + break; + } + } + if (st.length != pos) {st.length = pos; changed = true;} + if (pos && st[pos-2] != prevWord) changed = true; + // Short lines with simple highlights return null, and are + // counted as changed by the driver because they are likely to + // highlight the same way in various contexts. + return changed || (st.length < 5 && this.text.length < 10 ? null : false); + }, + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(mode, state, ch) { + var txt = this.text, stream = new StringStream(txt); + while (stream.pos < ch && !stream.eol()) { + stream.start = stream.pos; + var style = mode.token(stream, state); + } + return {start: stream.start, + end: stream.pos, + string: stream.current(), + className: style || null, + state: state}; + }, + indentation: function(tabSize) {return countColumn(this.text, null, tabSize);}, + // Produces an HTML fragment for the line, taking selection, + // marking, and highlighting into account. + getHTML: function(sfrom, sto, includePre, tabText, endAt) { + var html = [], first = true; + if (includePre) + html.push(this.className ? '
': "
");
+      function span(text, style) {
+        if (!text) return;
+        // Work around a bug where, in some compat modes, IE ignores leading spaces
+        if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
+        first = false;
+        if (style) html.push('', htmlEscape(text).replace(/\t/g, tabText), "");
+        else html.push(htmlEscape(text).replace(/\t/g, tabText));
+      }
+      var st = this.styles, allText = this.text, marked = this.marked;
+      if (sfrom == sto) sfrom = null;
+      var len = allText.length;
+      if (endAt != null) len = Math.min(endAt, len);
+
+      if (!allText && endAt == null)
+        span(" ", sfrom != null && sto == null ? "CodeMirror-selected" : null);
+      else if (!marked && sfrom == null)
+        for (var i = 0, ch = 0; ch < len; i+=2) {
+          var str = st[i], style = st[i+1], l = str.length;
+          if (ch + l > len) str = str.slice(0, len - ch);
+          ch += l;
+          span(str, style && "cm-" + style);
+        }
+      else {
+        var pos = 0, i = 0, text = "", style, sg = 0;
+        var markpos = -1, mark = null;
+        function nextMark() {
+          if (marked) {
+            markpos += 1;
+            mark = (markpos < marked.length) ? marked[markpos] : null;
+          }
+        }
+        nextMark();
+        while (pos < len) {
+          var upto = len;
+          var extraStyle = "";
+          if (sfrom != null) {
+            if (sfrom > pos) upto = sfrom;
+            else if (sto == null || sto > pos) {
+              extraStyle = " CodeMirror-selected";
+              if (sto != null) upto = Math.min(upto, sto);
+            }
+          }
+          while (mark && mark.to != null && mark.to <= pos) nextMark();
+          if (mark) {
+            if (mark.from > pos) upto = Math.min(upto, mark.from);
+            else {
+              extraStyle += " " + mark.style;
+              if (mark.to != null) upto = Math.min(upto, mark.to);
+            }
+          }
+          for (;;) {
+            var end = pos + text.length;
+            var appliedStyle = style;
+            if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
+            span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
+            if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+            pos = end;
+            text = st[i++]; style = "cm-" + st[i++];
+          }
+        }
+        if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
+      }
+      if (includePre) html.push("
"); + return html.join(""); + }, + cleanUp: function() { + this.parent = null; + if (this.marked) + for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this); + } + }; + // Utility used by replace and split above + function copyStyles(from, to, source, dest) { + for (var i = 0, pos = 0, state = 0; pos < to; i+=2) { + var part = source[i], end = pos + part.length; + if (state == 0) { + if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]); + if (end >= from) state = 1; + } + else if (state == 1) { + if (end > to) dest.push(part.slice(0, to - pos), source[i+1]); + else dest.push(part, source[i+1]); + } + pos = end; + } + } + + // Data structure that holds the sequence of lines. + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, e = lines.length, height = 0; i < e; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + remove: function(at, n, callbacks) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + line.cleanUp(); + if (line.handlers) + for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]); + } + this.lines.splice(at, n); + }, + collapse: function(lines) { + lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); + }, + insertHeight: function(at, lines, height) { + this.height += height; + this.lines.splice.apply(this.lines, [at, 0].concat(lines)); + for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; + }, + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0, e = children.length; i < e; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + remove: function(at, n, callbacks) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.remove(at, rm, callbacks); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + if (this.size - n < 25) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + } + }, + collapse: function(lines) { + for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); + }, + insert: function(at, lines) { + var height = 0; + for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; + this.insertHeight(at, lines, height); + }, + insertHeight: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertHeight(at, lines, height); + if (child.lines && child.lines.length > 50) { + while (child.lines.length > 50) { + var spilled = child.lines.splice(child.lines.length - 25, 25); + var newleaf = new LeafChunk(spilled); + child.height -= newleaf.height; + this.children.splice(i + 1, 0, newleaf); + newleaf.parent = this; + } + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iter: function(from, to, op) { this.iterN(from, to - from, op); }, + iterN: function(at, n, op) { + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + function getLineAt(chunk, n) { + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0, e = chunk.children.length; ; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no; + } + function lineAtHeight(chunk, h) { + var n = 0; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0, e = chunk.lines.length; i < e; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + function heightAtLine(chunk, n) { + var h = 0; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; continue outer; } + n -= sz; + h += child.height; + } + return h; + } while (!chunk.lines); + for (var i = 0; i < n; ++i) h += chunk.lines[i].height; + return h; + } + + // The history object 'chunks' changes that are made close together + // and at almost the same time into bigger undoable units. + function History() { + this.time = 0; + this.done = []; this.undone = []; + } + History.prototype = { + addChange: function(start, added, old) { + this.undone.length = 0; + var time = +new Date, last = this.done[this.done.length - 1]; + if (time - this.time > 400 || !last || + last.start > start + added || last.start + last.added < start - last.added + last.old.length) + this.done.push({start: start, added: added, old: old}); + else { + var oldoff = 0; + if (start < last.start) { + for (var i = last.start - start - 1; i >= 0; --i) + last.old.unshift(old[i]); + last.added += last.start - start; + last.start = start; + } + else if (last.start < start) { + oldoff = start - last.start; + added += oldoff; + } + for (var i = last.added - oldoff, e = old.length; i < e; ++i) + last.old.push(old[i]); + if (last.added < added) last.added = added; + } + this.time = time; + } + }; + + function stopMethod() {e_stop(this);} + // Ensure an event has a stop method. + function addStop(event) { + if (!event.stop) event.stop = stopMethod; + return event; + } + + function e_preventDefault(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + function e_stopPropagation(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + CodeMirror.e_stop = e_stop; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + if (e.which) return e.which; + else if (e.button & 1) return 1; + else if (e.button & 2) return 3; + else if (e.button & 4) return 2; + } + + // Event handler registration. If disconnect is true, it'll return a + // function that unregisters the handler. + function connect(node, type, handler, disconnect) { + if (typeof node.addEventListener == "function") { + node.addEventListener(type, handler, false); + if (disconnect) return function() {node.removeEventListener(type, handler, false);}; + } + else { + var wrapHandler = function(event) {handler(event || window.event);}; + node.attachEvent("on" + type, wrapHandler); + if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);}; + } + } + CodeMirror.connect = connect; + + function Delayed() {this.id = null;} + Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; + + // Detect drag-and-drop + var dragAndDrop = function() { + // IE8 has ondragstart and ondrop properties, but doesn't seem to + // actually support ondragstart the way it's supposed to work. + if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false; + var div = document.createElement('div'); + return "draggable" in div; + }(); + + var gecko = /gecko\/\d{7}/i.test(navigator.userAgent); + var ie = /MSIE \d/.test(navigator.userAgent); + var webkit = /WebKit\//.test(navigator.userAgent); + + var lineSep = "\n"; + // Feature-detect whether newlines in textareas are converted to \r\n + (function () { + var te = document.createElement("textarea"); + te.value = "foo\nbar"; + if (te.value.indexOf("\r") > -1) lineSep = "\r\n"; + }()); + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = 0, n = 0; i < end; ++i) { + if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); + else ++n; + } + return n; + } + + function computedStyle(elt) { + if (elt.currentStyle) return elt.currentStyle; + return window.getComputedStyle(elt, null); + } + + // Find the position of an element by following the offsetParent chain. + // If screen==true, it returns screen (rather than page) coordinates. + function eltOffset(node, screen) { + var bod = node.ownerDocument.body; + var x = 0, y = 0, skipBody = false; + for (var n = node; n; n = n.offsetParent) { + var ol = n.offsetLeft, ot = n.offsetTop; + // Firefox reports weird inverted offsets when the body has a border. + if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); } + else { x += ol, y += ot; } + if (screen && computedStyle(n).position == "fixed") + skipBody = true; + } + var e = screen && !skipBody ? null : bod; + for (var n = node.parentNode; n != e; n = n.parentNode) + if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;} + return {left: x, top: y}; + } + // Use the faster and saner getBoundingClientRect method when possible. + if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) { + // Take the parts of bounding client rect that we are interested in so we are able to edit if need be, + // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page) + try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; } + catch(e) { box = {top: 0, left: 0}; } + if (!screen) { + // Get the toplevel scroll, working around browser differences. + if (window.pageYOffset == null) { + var t = document.documentElement || document.body.parentNode; + if (t.scrollTop == null) t = document.body; + box.top += t.scrollTop; box.left += t.scrollLeft; + } else { + box.top += window.pageYOffset; box.left += window.pageXOffset; + } + } + return box; + }; + + // Get a node's text content. + function eltText(node) { + return node.textContent || node.innerText || node.nodeValue || ""; + } + + // Operations on {line, ch} objects. + function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} + function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function copyPos(x) {return {line: x.line, ch: x.ch};} + + var escapeElement = document.createElement("pre"); + function htmlEscape(str) { + escapeElement.textContent = str; + return escapeElement.innerHTML; + } + // Recent (late 2011) Opera betas insert bogus newlines at the start + // of the textContent, so we strip those. + if (htmlEscape("a") == "\na") + htmlEscape = function(str) { + escapeElement.textContent = str; + return escapeElement.innerHTML.slice(1); + }; + // Some IEs don't preserve tabs through innerHTML + else if (htmlEscape("\t") != "\t") + htmlEscape = function(str) { + escapeElement.innerHTML = ""; + escapeElement.appendChild(document.createTextNode(str)); + return escapeElement.innerHTML; + }; + CodeMirror.htmlEscape = htmlEscape; + + // Used to position the cursor after an undo/redo by finding the + // last edited character. + function editEnd(from, to) { + if (!to) return from ? from.length : 0; + if (!from) return to.length; + for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j) + if (from.charAt(i) != to.charAt(j)) break; + return j + 1; + } + + function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt); + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i; + return -1; + } + function isWordChar(ch) { + return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase(); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, nl, result = []; + while ((nl = string.indexOf("\n", pos)) > -1) { + result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl)); + pos = nl + 1; + } + result.push(string.slice(pos)); + return result; + } : function(string){return string.split(/\r?\n/);}; + CodeMirror.splitLines = splitLines; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 186: ";", 187: "=", 188: ",", + 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp", + 63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right", + 63233: "Down", 63302: "Insert", 63272: "Delete"}; + CodeMirror.keyNames = keyNames; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + return CodeMirror; +})(); diff --git a/CodeMirror-2.2/lib/util/dialog.css b/CodeMirror-2.2/lib/util/dialog.css new file mode 100644 index 0000000..4cb467e --- /dev/null +++ b/CodeMirror-2.2/lib/util/dialog.css @@ -0,0 +1,23 @@ +.CodeMirror-dialog { + position: relative; +} + +.CodeMirror-dialog > div { + position: absolute; + top: 0; left: 0; right: 0; + background: white; + border-bottom: 1px solid #eee; + z-index: 15; + padding: .1em .8em; + overflow: hidden; + color: #333; +} + +.CodeMirror-dialog input { + border: none; + outline: none; + background: transparent; + width: 20em; + color: inherit; + font-family: monospace; +} diff --git a/CodeMirror-2.2/lib/util/dialog.js b/CodeMirror-2.2/lib/util/dialog.js new file mode 100644 index 0000000..8950bf0 --- /dev/null +++ b/CodeMirror-2.2/lib/util/dialog.js @@ -0,0 +1,63 @@ +// Open simple dialogs on top of an editor. Relies on dialog.css. + +(function() { + function dialogDiv(cm, template) { + var wrap = cm.getWrapperElement(); + var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild); + dialog.className = "CodeMirror-dialog"; + dialog.innerHTML = '
' + template + '
'; + return dialog; + } + + CodeMirror.defineExtension("openDialog", function(template, callback) { + var dialog = dialogDiv(this, template); + var closed = false, me = this; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + } + var inp = dialog.getElementsByTagName("input")[0]; + if (inp) { + CodeMirror.connect(inp, "keydown", function(e) { + if (e.keyCode == 13 || e.keyCode == 27) { + CodeMirror.e_stop(e); + close(); + me.focus(); + if (e.keyCode == 13) callback(inp.value); + } + }); + inp.focus(); + CodeMirror.connect(inp, "blur", close); + } + return close; + }); + + CodeMirror.defineExtension("openConfirm", function(template, callbacks) { + var dialog = dialogDiv(this, template); + var buttons = dialog.getElementsByTagName("button"); + var closed = false, me = this, blurring = 1; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + } + buttons[0].focus(); + for (var i = 0; i < buttons.length; ++i) { + var b = buttons[i]; + (function(callback) { + CodeMirror.connect(b, "click", function(e) { + CodeMirror.e_preventDefault(e); + close(); + if (callback) callback(me); + }); + })(callbacks[i]); + CodeMirror.connect(b, "blur", function() { + --blurring; + setTimeout(function() { if (blurring <= 0) close(); }, 200); + }); + CodeMirror.connect(b, "focus", function() { ++blurring; }); + } + }); +})(); \ No newline at end of file diff --git a/CodeMirror-2.2/lib/util/foldcode.js b/CodeMirror-2.2/lib/util/foldcode.js new file mode 100644 index 0000000..1895779 --- /dev/null +++ b/CodeMirror-2.2/lib/util/foldcode.js @@ -0,0 +1,66 @@ +CodeMirror.braceRangeFinder = function(cm, line) { + var lineText = cm.getLine(line); + var startChar = lineText.lastIndexOf("{"); + if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return; + var tokenType = cm.getTokenAt({line: line, ch: startChar}).className; + var count = 1, lastLine = cm.lineCount(), end; + outer: for (var i = line + 1; i < lastLine; ++i) { + var text = cm.getLine(i), pos = 0; + for (;;) { + var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos); + if (nextOpen < 0) nextOpen = text.length; + if (nextClose < 0) nextClose = text.length; + pos = Math.min(nextOpen, nextClose); + if (pos == text.length) break; + if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) { + if (pos == nextOpen) ++count; + else if (!--count) { end = i; break outer; } + } + ++pos; + } + } + if (end == null || end == line + 1) return; + return end; +}; + + +CodeMirror.newFoldFunction = function(rangeFinder, markText) { + var folded = []; + if (markText == null) markText = '
%N%'; + + function isFolded(cm, n) { + for (var i = 0; i < folded.length; ++i) { + var start = cm.lineInfo(folded[i].start); + if (!start) folded.splice(i--, 1); + else if (start.line == n) return {pos: i, region: folded[i]}; + } + } + + function expand(cm, region) { + cm.clearMarker(region.start); + for (var i = 0; i < region.hidden.length; ++i) + cm.showLine(region.hidden[i]); + } + + return function(cm, line) { + cm.operation(function() { + var known = isFolded(cm, line); + if (known) { + folded.splice(known.pos, 1); + expand(cm, known.region); + } else { + var end = rangeFinder(cm, line); + if (end == null) return; + var hidden = []; + for (var i = line + 1; i < end; ++i) { + var handle = cm.hideLine(i); + if (handle) hidden.push(handle); + } + var first = cm.setMarker(line, markText); + var region = {start: first, hidden: hidden}; + cm.onDeleteLine(first, function() { expand(cm, region); }); + folded.push(region); + } + }); + }; +}; diff --git a/CodeMirror-2.2/lib/util/formatting.js b/CodeMirror-2.2/lib/util/formatting.js new file mode 100644 index 0000000..986bcb8 --- /dev/null +++ b/CodeMirror-2.2/lib/util/formatting.js @@ -0,0 +1,291 @@ +// ============== Formatting extensions ============================ +// A common storage for all mode-specific formatting features +if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {}; + +// Returns the extension of the editor's current mode +CodeMirror.defineExtension("getModeExt", function () { + return CodeMirror.modeExtensions[this.getOption("mode")]; +}); + +// If the current mode is 'htmlmixed', returns the extension of a mode located at +// the specified position (can be htmlmixed, css or javascript). Otherwise, simply +// returns the extension of the editor's current mode. +CodeMirror.defineExtension("getModeExtAtPos", function (pos) { + var token = this.getTokenAt(pos); + if (token && token.state && token.state.mode) + return CodeMirror.modeExtensions[token.state.mode == "html" ? "htmlmixed" : token.state.mode]; + else + return this.getModeExt(); +}); + +// Comment/uncomment the specified range +CodeMirror.defineExtension("commentRange", function (isComment, from, to) { + var curMode = this.getModeExtAtPos(this.getCursor()); + if (isComment) { // Comment range + var commentedText = this.getRange(from, to); + this.replaceRange(curMode.commentStart + this.getRange(from, to) + curMode.commentEnd + , from, to); + if (from.line == to.line && from.ch == to.ch) { // An empty comment inserted - put cursor inside + this.setCursor(from.line, from.ch + curMode.commentStart.length); + } + } + else { // Uncomment range + var selText = this.getRange(from, to); + var startIndex = selText.indexOf(curMode.commentStart); + var endIndex = selText.lastIndexOf(curMode.commentEnd); + if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) { + // Take string till comment start + selText = selText.substr(0, startIndex) + // From comment start till comment end + + selText.substring(startIndex + curMode.commentStart.length, endIndex) + // From comment end till string end + + selText.substr(endIndex + curMode.commentEnd.length); + } + this.replaceRange(selText, from, to); + } +}); + +// Applies automatic mode-aware indentation to the specified range +CodeMirror.defineExtension("autoIndentRange", function (from, to) { + var cmInstance = this; + this.operation(function () { + for (var i = from.line; i <= to.line; i++) { + cmInstance.indentLine(i); + } + }); +}); + +// Applies automatic formatting to the specified range +CodeMirror.defineExtension("autoFormatRange", function (from, to) { + var absStart = this.indexFromPos(from); + var absEnd = this.indexFromPos(to); + // Insert additional line breaks where necessary according to the + // mode's syntax + var res = this.getModeExt().autoFormatLineBreaks(this.getValue(), absStart, absEnd); + var cmInstance = this; + + // Replace and auto-indent the range + this.operation(function () { + cmInstance.replaceRange(res, from, to); + var startLine = cmInstance.posFromIndex(absStart).line; + var endLine = cmInstance.posFromIndex(absStart + res.length).line; + for (var i = startLine; i <= endLine; i++) { + cmInstance.indentLine(i); + } + }); +}); + +// Define extensions for a few modes + +CodeMirror.modeExtensions["css"] = { + commentStart: "/*", + commentEnd: "*/", + wordWrapChars: [";", "\\{", "\\}"], + autoFormatLineBreaks: function (text) { + return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2"); + } +}; + +CodeMirror.modeExtensions["javascript"] = { + commentStart: "/*", + commentEnd: "*/", + wordWrapChars: [";", "\\{", "\\}"], + + getNonBreakableBlocks: function (text) { + var nonBreakableRegexes = [ + new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"), + new RegExp("'([\\s\\S]*?)('|$)"), + new RegExp("\"([\\s\\S]*?)(\"|$)"), + new RegExp("//.*([\r\n]|$)") + ]; + var nonBreakableBlocks = new Array(); + for (var i = 0; i < nonBreakableRegexes.length; i++) { + var curPos = 0; + while (curPos < text.length) { + var m = text.substr(curPos).match(nonBreakableRegexes[i]); + if (m != null) { + nonBreakableBlocks.push({ + start: curPos + m.index, + end: curPos + m.index + m[0].length + }); + curPos += m.index + Math.max(1, m[0].length); + } + else { // No more matches + break; + } + } + } + nonBreakableBlocks.sort(function (a, b) { + return a.start - b.start; + }); + + return nonBreakableBlocks; + }, + + autoFormatLineBreaks: function (text) { + var curPos = 0; + var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g"); + var nonBreakableBlocks = this.getNonBreakableBlocks(text); + if (nonBreakableBlocks != null) { + var res = ""; + for (var i = 0; i < nonBreakableBlocks.length; i++) { + if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block + res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, "$1\n$2"); + curPos = nonBreakableBlocks[i].start; + } + if (nonBreakableBlocks[i].start <= curPos + && nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block + res += text.substring(curPos, nonBreakableBlocks[i].end); + curPos = nonBreakableBlocks[i].end; + } + } + if (curPos < text.length - 1) { + res += text.substr(curPos).replace(reLinesSplitter, "$1\n$2"); + } + return res; + } + else { + return text.replace(reLinesSplitter, "$1\n$2"); + } + } +}; + +CodeMirror.modeExtensions["xml"] = { + commentStart: "", + wordWrapChars: [">"], + + autoFormatLineBreaks: function (text) { + var lines = text.split("\n"); + var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)"); + var reOpenBrackets = new RegExp("<", "g"); + var reCloseBrackets = new RegExp("(>)([^\r\n])", "g"); + for (var i = 0; i < lines.length; i++) { + var mToProcess = lines[i].match(reProcessedPortion); + if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces + lines[i] = mToProcess[1] + + mToProcess[2].replace(reOpenBrackets, "\n$&").replace(reCloseBrackets, "$1\n$2") + + mToProcess[3]; + continue; + } + } + + return lines.join("\n"); + } +}; + +CodeMirror.modeExtensions["htmlmixed"] = { + commentStart: "", + wordWrapChars: [">", ";", "\\{", "\\}"], + + getModeInfos: function (text, absPos) { + var modeInfos = new Array(); + modeInfos[0] = + { + pos: 0, + modeExt: CodeMirror.modeExtensions["xml"], + modeName: "xml" + }; + + var modeMatchers = new Array(); + modeMatchers[0] = + { + regex: new RegExp("]*>([\\s\\S]*?)(]*>|$)", "i"), + modeExt: CodeMirror.modeExtensions["css"], + modeName: "css" + }; + modeMatchers[1] = + { + regex: new RegExp("]*>([\\s\\S]*?)(]*>|$)", "i"), + modeExt: CodeMirror.modeExtensions["javascript"], + modeName: "javascript" + }; + + var lastCharPos = (typeof (absPos) !== "undefined" ? absPos : text.length - 1); + // Detect modes for the entire text + for (var i = 0; i < modeMatchers.length; i++) { + var curPos = 0; + while (curPos <= lastCharPos) { + var m = text.substr(curPos).match(modeMatchers[i].regex); + if (m != null) { + if (m.length > 1 && m[1].length > 0) { + // Push block begin pos + var blockBegin = curPos + m.index + m[0].indexOf(m[1]); + modeInfos.push( + { + pos: blockBegin, + modeExt: modeMatchers[i].modeExt, + modeName: modeMatchers[i].modeName + }); + // Push block end pos + modeInfos.push( + { + pos: blockBegin + m[1].length, + modeExt: modeInfos[0].modeExt, + modeName: modeInfos[0].modeName + }); + curPos += m.index + m[0].length; + continue; + } + else { + curPos += m.index + Math.max(m[0].length, 1); + } + } + else { // No more matches + break; + } + } + } + // Sort mode infos + modeInfos.sort(function sortModeInfo(a, b) { + return a.pos - b.pos; + }); + + return modeInfos; + }, + + autoFormatLineBreaks: function (text, startPos, endPos) { + var modeInfos = this.getModeInfos(text); + var reBlockStartsWithNewline = new RegExp("^\\s*?\n"); + var reBlockEndsWithNewline = new RegExp("\n\\s*?$"); + var res = ""; + // Use modes info to break lines correspondingly + if (modeInfos.length > 1) { // Deal with multi-mode text + for (var i = 1; i <= modeInfos.length; i++) { + var selStart = modeInfos[i - 1].pos; + var selEnd = (i < modeInfos.length ? modeInfos[i].pos : endPos); + + if (selStart >= endPos) { // The block starts later than the needed fragment + break; + } + if (selStart < startPos) { + if (selEnd <= startPos) { // The block starts earlier than the needed fragment + continue; + } + selStart = startPos; + } + if (selEnd > endPos) { + selEnd = endPos; + } + var textPortion = text.substring(selStart, selEnd); + if (modeInfos[i - 1].modeName != "xml") { // Starting a CSS or JavaScript block + if (!reBlockStartsWithNewline.test(textPortion) + && selStart > 0) { // The block does not start with a line break + textPortion = "\n" + textPortion; + } + if (!reBlockEndsWithNewline.test(textPortion) + && selEnd < text.length - 1) { // The block does not end with a line break + textPortion += "\n"; + } + } + res += modeInfos[i - 1].modeExt.autoFormatLineBreaks(textPortion); + } + } + else { // Single-mode text + res = modeInfos[0].modeExt.autoFormatLineBreaks(text.substring(startPos, endPos)); + } + + return res; + } +}; diff --git a/CodeMirror-2.2/lib/util/javascript-hint.js b/CodeMirror-2.2/lib/util/javascript-hint.js new file mode 100644 index 0000000..4e88a7e --- /dev/null +++ b/CodeMirror-2.2/lib/util/javascript-hint.js @@ -0,0 +1,83 @@ +(function () { + function forEach(arr, f) { + for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); + } + + function arrayContains(arr, item) { + if (!Array.prototype.indexOf) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + return true; + } + } + return false; + } + return arr.indexOf(item) != -1; + } + + CodeMirror.javascriptHint = function(editor) { + // Find the token at the cursor + var cur = editor.getCursor(), token = editor.getTokenAt(cur), tprop = token; + // If it's not a 'word-style' token, ignore the token. + if (!/^[\w$_]*$/.test(token.string)) { + token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state, + className: token.string == "." ? "property" : null}; + } + // If it is a property, find out what it is a property of. + while (tprop.className == "property") { + tprop = editor.getTokenAt({line: cur.line, ch: tprop.start}); + if (tprop.string != ".") return; + tprop = editor.getTokenAt({line: cur.line, ch: tprop.start}); + if (!context) var context = []; + context.push(tprop); + } + return {list: getCompletions(token, context), + from: {line: cur.line, ch: token.start}, + to: {line: cur.line, ch: token.end}}; + } + + var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + + "toUpperCase toLowerCase split concat match replace search").split(" "); + var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " + + "lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); + var funcProps = "prototype apply call bind".split(" "); + var keywords = ("break case catch continue debugger default delete do else false finally for function " + + "if in instanceof new null return switch throw true try typeof var void while with").split(" "); + + function getCompletions(token, context) { + var found = [], start = token.string; + function maybeAdd(str) { + if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str); + } + function gatherCompletions(obj) { + if (typeof obj == "string") forEach(stringProps, maybeAdd); + else if (obj instanceof Array) forEach(arrayProps, maybeAdd); + else if (obj instanceof Function) forEach(funcProps, maybeAdd); + for (var name in obj) maybeAdd(name); + } + + if (context) { + // If this is a property, see if it belongs to some object we can + // find in the current environment. + var obj = context.pop(), base; + if (obj.className == "variable") + base = window[obj.string]; + else if (obj.className == "string") + base = ""; + else if (obj.className == "atom") + base = 1; + while (base != null && context.length) + base = base[context.pop().string]; + if (base != null) gatherCompletions(base); + } + else { + // If not, just look in the window object and any local scope + // (reading into JS mode internals to get at the local variables) + for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); + gatherCompletions(window); + forEach(keywords, maybeAdd); + } + return found; + } +})(); diff --git a/CodeMirror-2.2/lib/util/overlay.js b/CodeMirror-2.2/lib/util/overlay.js new file mode 100644 index 0000000..c4cdf9f --- /dev/null +++ b/CodeMirror-2.2/lib/util/overlay.js @@ -0,0 +1,51 @@ +// Utility function that allows modes to be combined. The mode given +// as the base argument takes care of most of the normal mode +// functionality, but a second (typically simple) mode is used, which +// can override the style of text. Both modes get to parse all of the +// text, but when both assign a non-null style to a piece of code, the +// overlay wins, unless the combine argument was true, in which case +// the styles are combined. + +CodeMirror.overlayParser = function(base, overlay, combine) { + return { + startState: function() { + return { + base: CodeMirror.startState(base), + overlay: CodeMirror.startState(overlay), + basePos: 0, baseCur: null, + overlayPos: 0, overlayCur: null + }; + }, + copyState: function(state) { + return { + base: CodeMirror.copyState(base, state.base), + overlay: CodeMirror.copyState(overlay, state.overlay), + basePos: state.basePos, baseCur: null, + overlayPos: state.overlayPos, overlayCur: null + }; + }, + + token: function(stream, state) { + if (stream.start == state.basePos) { + state.baseCur = base.token(stream, state.base); + state.basePos = stream.pos; + } + if (stream.start == state.overlayPos) { + stream.pos = stream.start; + state.overlayCur = overlay.token(stream, state.overlay); + state.overlayPos = stream.pos; + } + stream.pos = Math.min(state.basePos, state.overlayPos); + if (stream.eol()) state.basePos = state.overlayPos = 0; + + if (state.overlayCur == null) return state.baseCur; + if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur; + else return state.overlayCur; + }, + + indent: function(state, textAfter) { + return base.indent(state.base, textAfter); + }, + electricChars: base.electricChars + }; +}; diff --git a/CodeMirror-2.2/lib/util/runmode.js b/CodeMirror-2.2/lib/util/runmode.js new file mode 100644 index 0000000..de4a760 --- /dev/null +++ b/CodeMirror-2.2/lib/util/runmode.js @@ -0,0 +1,27 @@ +CodeMirror.runMode = function(string, modespec, callback) { + var mode = CodeMirror.getMode({indentUnit: 2}, modespec); + var isNode = callback.nodeType == 1; + if (isNode) { + var node = callback, accum = []; + callback = function(string, style) { + if (string == "\n") + accum.push("
"); + else if (style) + accum.push("" + CodeMirror.htmlEscape(string) + ""); + else + accum.push(CodeMirror.htmlEscape(string)); + } + } + var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode); + for (var i = 0, e = lines.length; i < e; ++i) { + if (i) callback("\n"); + var stream = new CodeMirror.StringStream(lines[i]); + while (!stream.eol()) { + var style = mode.token(stream, state); + callback(stream.current(), style, i, stream.start); + stream.start = stream.pos; + } + } + if (isNode) + node.innerHTML = accum.join(""); +}; diff --git a/CodeMirror-2.2/lib/util/search.js b/CodeMirror-2.2/lib/util/search.js new file mode 100644 index 0000000..63ebca9 --- /dev/null +++ b/CodeMirror-2.2/lib/util/search.js @@ -0,0 +1,114 @@ +// Define search commands. Depends on dialog.js or another +// implementation of the openDialog method. + +// Replace works a little oddly -- it will do the replace on the next +// Ctrl-G (or whatever is bound to findNext) press. You prevent a +// replace by making sure the match is no longer selected when hitting +// Ctrl-G. + +(function() { + function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.marked = []; + } + function getSearchState(cm) { + return cm._searchState || (cm._searchState = new SearchState()); + } + function dialog(cm, text, shortText, f) { + if (cm.openDialog) cm.openDialog(text, f); + else f(prompt(shortText, "")); + } + function confirmDialog(cm, text, shortText, fs) { + if (cm.openConfirm) cm.openConfirm(text, fs); + else if (confirm(shortText)) fs[0](); + } + function parseQuery(query) { + var isRE = query.match(/^\/(.*)\/$/); + return isRE ? new RegExp(isRE[1]) : query; + } + var queryDialog = + 'Search: (Use /re/ syntax for regexp search)'; + function doSearch(cm, rev) { + var state = getSearchState(cm); + if (state.query) return findNext(cm, rev); + dialog(cm, queryDialog, "Search for:", function(query) { + cm.operation(function() { + if (!query || state.query) return; + state.query = parseQuery(query); + if (cm.lineCount() < 2000) { // This is too expensive on big documents. + for (var cursor = cm.getSearchCursor(query); cursor.findNext();) + state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching")); + } + state.posFrom = state.posTo = cm.getCursor(); + findNext(cm, rev); + }); + }); + } + function findNext(cm, rev) {cm.operation(function() { + var state = getSearchState(cm); + var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo); + if (!cursor.find(rev)) { + cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0}); + if (!cursor.find(rev)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + state.posFrom = cursor.from(); state.posTo = cursor.to(); + })} + function clearSearch(cm) {cm.operation(function() { + var state = getSearchState(cm); + if (!state.query) return; + state.query = null; + for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear(); + state.marked.length = 0; + })} + + var replaceQueryDialog = + 'Replace: (Use /re/ syntax for regexp search)'; + var replacementQueryDialog = 'With: '; + var doReplaceConfirm = "Replace? "; + function replace(cm, all) { + dialog(cm, replaceQueryDialog, "Replace:", function(query) { + if (!query) return; + query = parseQuery(query); + dialog(cm, replacementQueryDialog, "Replace with:", function(text) { + if (all) { + cm.operation(function() { + for (var cursor = cm.getSearchCursor(query); cursor.findNext();) { + if (typeof query != "string") { + var match = cm.getRange(cursor.from(), cursor.to()).match(query); + cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];})); + } else cursor.replace(text); + } + }); + } else { + clearSearch(cm); + var cursor = cm.getSearchCursor(query, cm.getCursor()); + function advance() { + var start = cursor.from(), match; + if (!(match = cursor.findNext())) { + cursor = cm.getSearchCursor(query); + if (!(match = cursor.findNext()) || + (cursor.from().line == start.line && cursor.from().ch == start.ch)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + confirmDialog(cm, doReplaceConfirm, "Replace?", + [function() {doReplace(match);}, advance]); + } + function doReplace(match) { + cursor.replace(typeof query == "string" ? text : + text.replace(/\$(\d)/, function(w, i) {return match[i];})); + advance(); + } + advance(); + } + }); + }); + } + + CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; + CodeMirror.commands.findNext = doSearch; + CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; + CodeMirror.commands.clearSearch = clearSearch; + CodeMirror.commands.replace = replace; + CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; +})(); diff --git a/CodeMirror-2.2/lib/util/searchcursor.js b/CodeMirror-2.2/lib/util/searchcursor.js new file mode 100644 index 0000000..3b77829 --- /dev/null +++ b/CodeMirror-2.2/lib/util/searchcursor.js @@ -0,0 +1,117 @@ +(function(){ + function SearchCursor(cm, query, pos, caseFold) { + this.atOccurrence = false; this.cm = cm; + if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase(); + + pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0}; + this.pos = {from: pos, to: pos}; + + // The matches method is filled in based on the type of query. + // It takes a position and a direction, and returns an object + // describing the next occurrence of the query, or null if no + // more matches were found. + if (typeof query != "string") // Regexp match + this.matches = function(reverse, pos) { + if (reverse) { + var line = cm.getLine(pos.line).slice(0, pos.ch), match = line.match(query), start = 0; + while (match) { + var ind = line.indexOf(match[0]); + start += ind; + line = line.slice(ind + 1); + var newmatch = line.match(query); + if (newmatch) match = newmatch; + else break; + start++; + } + } + else { + var line = cm.getLine(pos.line).slice(pos.ch), match = line.match(query), + start = match && pos.ch + line.indexOf(match[0]); + } + if (match) + return {from: {line: pos.line, ch: start}, + to: {line: pos.line, ch: start + match[0].length}, + match: match}; + }; + else { // String query + if (caseFold) query = query.toLowerCase(); + var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;}; + var target = query.split("\n"); + // Different methods for single-line and multi-line queries + if (target.length == 1) + this.matches = function(reverse, pos) { + var line = fold(cm.getLine(pos.line)), len = query.length, match; + if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1) + : (match = line.indexOf(query, pos.ch)) != -1) + return {from: {line: pos.line, ch: match}, + to: {line: pos.line, ch: match + len}}; + }; + else + this.matches = function(reverse, pos) { + var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln)); + var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match)); + if (reverse ? offsetA >= pos.ch || offsetA != match.length + : offsetA <= pos.ch || offsetA != line.length - match.length) + return; + for (;;) { + if (reverse ? !ln : ln == cm.lineCount() - 1) return; + line = fold(cm.getLine(ln += reverse ? -1 : 1)); + match = target[reverse ? --idx : ++idx]; + if (idx > 0 && idx < target.length - 1) { + if (line != match) return; + else continue; + } + var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length); + if (reverse ? offsetB != line.length - match.length : offsetB != match.length) + return; + var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB}; + return {from: reverse ? end : start, to: reverse ? start : end}; + } + }; + } + } + + SearchCursor.prototype = { + findNext: function() {return this.find(false);}, + findPrevious: function() {return this.find(true);}, + + find: function(reverse) { + var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to); + function savePosAndFail(line) { + var pos = {line: line, ch: 0}; + self.pos = {from: pos, to: pos}; + self.atOccurrence = false; + return false; + } + + for (;;) { + if (this.pos = this.matches(reverse, pos)) { + this.atOccurrence = true; + return this.pos.match || true; + } + if (reverse) { + if (!pos.line) return savePosAndFail(0); + pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length}; + } + else { + var maxLine = this.cm.lineCount(); + if (pos.line == maxLine - 1) return savePosAndFail(maxLine); + pos = {line: pos.line+1, ch: 0}; + } + } + }, + + from: function() {if (this.atOccurrence) return this.pos.from;}, + to: function() {if (this.atOccurrence) return this.pos.to;}, + + replace: function(newText) { + var self = this; + if (this.atOccurrence) + self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to); + } + }; + + CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this, query, pos, caseFold); + }); +})(); diff --git a/CodeMirror-2.2/lib/util/simple-hint.css b/CodeMirror-2.2/lib/util/simple-hint.css new file mode 100644 index 0000000..4387cb9 --- /dev/null +++ b/CodeMirror-2.2/lib/util/simple-hint.css @@ -0,0 +1,16 @@ +.CodeMirror-completions { + position: absolute; + z-index: 10; + overflow: hidden; + -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); + -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); + box-shadow: 2px 3px 5px rgba(0,0,0,.2); +} +.CodeMirror-completions select { + background: #fafafa; + outline: none; + border: none; + padding: 0; + margin: 0; + font-family: monospace; +} diff --git a/CodeMirror-2.2/lib/util/simple-hint.js b/CodeMirror-2.2/lib/util/simple-hint.js new file mode 100644 index 0000000..b38f389 --- /dev/null +++ b/CodeMirror-2.2/lib/util/simple-hint.js @@ -0,0 +1,66 @@ +(function() { + CodeMirror.simpleHint = function(editor, getHints) { + // We want a single cursor position. + if (editor.somethingSelected()) return; + var result = getHints(editor); + if (!result || !result.list.length) return; + var completions = result.list; + function insert(str) { + editor.replaceRange(str, result.from, result.to); + } + // When there is only one completion, use it directly. + if (completions.length == 1) {insert(completions[0]); return true;} + + // Build the select widget + var complete = document.createElement("div"); + complete.className = "CodeMirror-completions"; + var sel = complete.appendChild(document.createElement("select")); + // Opera doesn't move the selection when pressing up/down in a + // multi-select, but it does properly support the size property on + // single-selects, so no multi-select is necessary. + if (!window.opera) sel.multiple = true; + for (var i = 0; i < completions.length; ++i) { + var opt = sel.appendChild(document.createElement("option")); + opt.appendChild(document.createTextNode(completions[i])); + } + sel.firstChild.selected = true; + sel.size = Math.min(10, completions.length); + var pos = editor.cursorCoords(); + complete.style.left = pos.x + "px"; + complete.style.top = pos.yBot + "px"; + document.body.appendChild(complete); + // Hack to hide the scrollbar. + if (completions.length <= 10) + complete.style.width = (sel.clientWidth - 1) + "px"; + + var done = false; + function close() { + if (done) return; + done = true; + complete.parentNode.removeChild(complete); + } + function pick() { + insert(completions[sel.selectedIndex]); + close(); + setTimeout(function(){editor.focus();}, 50); + } + CodeMirror.connect(sel, "blur", close); + CodeMirror.connect(sel, "keydown", function(event) { + var code = event.keyCode; + // Enter + if (code == 13) {CodeMirror.e_stop(event); pick();} + // Escape + else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();} + else if (code != 38 && code != 40) { + close(); editor.focus(); + setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50); + } + }); + CodeMirror.connect(sel, "dblclick", pick); + + sel.focus(); + // Opera sometimes ignores focusing a freshly created node + if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100); + return true; + }; +})(); diff --git a/CodeMirror-2.2/mode/clike/clike.js b/CodeMirror-2.2/mode/clike/clike.js new file mode 100644 index 0000000..69877ef --- /dev/null +++ b/CodeMirror-2.2/mode/clike/clike.js @@ -0,0 +1,249 @@ +CodeMirror.defineMode("clike", function(config, parserConfig) { + var indentUnit = config.indentUnit, + keywords = parserConfig.keywords || {}, + blockKeywords = parserConfig.blockKeywords || {}, + atoms = parserConfig.atoms || {}, + hooks = parserConfig.hooks || {}, + multiLineStrings = parserConfig.multiLineStrings; + var isOperatorChar = /[+\-*&%=<>!?|\/]/; + + var curPunc; + + function tokenBase(stream, state) { + var ch = stream.next(); + if (hooks[ch]) { + var result = hooks[ch](stream, state); + if (result !== false) return result; + } + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + if (/[\[\]{}\(\),;\:\.]/.test(ch)) { + curPunc = ch; + return null + } + if (/\d/.test(ch)) { + stream.eatWhile(/[\w\.]/); + return "number"; + } + if (ch == "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } + if (stream.eat("/")) { + stream.skipToEnd(); + return "comment"; + } + } + if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar); + return "operator"; + } + stream.eatWhile(/[\w\$_]/); + var cur = stream.current(); + if (keywords.propertyIsEnumerable(cur)) { + if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + return "keyword"; + } + if (atoms.propertyIsEnumerable(cur)) return "atom"; + return "word"; + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next, end = false; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) {end = true; break;} + escaped = !escaped && next == "\\"; + } + if (end || !(escaped || multiLineStrings)) + state.tokenize = tokenBase; + return "string"; + }; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = tokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return "comment"; + } + + function Context(indented, column, type, align, prev) { + this.indented = indented; + this.column = column; + this.type = type; + this.align = align; + this.prev = prev; + } + function pushContext(state, col, type) { + return state.context = new Context(state.indented, col, type, null, state.context); + } + function popContext(state) { + var t = state.context.type; + if (t == ")" || t == "]" || t == "}") + state.indented = state.context.indented; + return state.context = state.context.prev; + } + + // Interface + + return { + startState: function(basecolumn) { + return { + tokenize: null, + context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), + indented: 0, + startOfLine: true + }; + }, + + token: function(stream, state) { + var ctx = state.context; + if (stream.sol()) { + if (ctx.align == null) ctx.align = false; + state.indented = stream.indentation(); + state.startOfLine = true; + } + if (stream.eatSpace()) return null; + curPunc = null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style == "comment" || style == "meta") return style; + if (ctx.align == null) ctx.align = true; + + if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); + else if (curPunc == "{") pushContext(state, stream.column(), "}"); + else if (curPunc == "[") pushContext(state, stream.column(), "]"); + else if (curPunc == "(") pushContext(state, stream.column(), ")"); + else if (curPunc == "}") { + while (ctx.type == "statement") ctx = popContext(state); + if (ctx.type == "}") ctx = popContext(state); + while (ctx.type == "statement") ctx = popContext(state); + } + else if (curPunc == ctx.type) popContext(state); + else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) + pushContext(state, stream.column(), "statement"); + state.startOfLine = false; + return style; + }, + + indent: function(state, textAfter) { + if (state.tokenize != tokenBase && state.tokenize != null) return 0; + var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); + if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; + var closing = firstChar == ctx.type; + if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit); + else if (ctx.align) return ctx.column + (closing ? 0 : 1); + else return ctx.indented + (closing ? 0 : indentUnit); + }, + + electricChars: "{}" + }; +}); + +(function() { + function words(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + var cKeywords = "auto if break int case long char register continue return default short do sizeof " + + "double static else struct entry switch extern typedef float union for unsigned " + + "goto while enum void const signed volatile"; + + function cppHook(stream, state) { + if (!state.startOfLine) return false; + stream.skipToEnd(); + return "meta"; + } + + // C#-style strings where "" escapes a quote. + function tokenAtString(stream, state) { + var next; + while ((next = stream.next()) != null) { + if (next == '"' && !stream.eat('"')) { + state.tokenize = null; + break; + } + } + return "string"; + } + + CodeMirror.defineMIME("text/x-csrc", { + name: "clike", + keywords: words(cKeywords), + blockKeywords: words("case do else for if switch while struct"), + atoms: words("null"), + hooks: {"#": cppHook} + }); + CodeMirror.defineMIME("text/x-c++src", { + name: "clike", + keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + + "static_cast typeid catch operator template typename class friend private " + + "this using const_cast inline public throw virtual delete mutable protected " + + "wchar_t"), + blockKeywords: words("catch class do else finally for if struct switch try while"), + atoms: words("true false null"), + hooks: {"#": cppHook} + }); + CodeMirror.defineMIME("text/x-java", { + name: "clike", + keywords: words("abstract assert boolean break byte case catch char class const continue default " + + "do double else enum extends final finally float for goto if implements import " + + "instanceof int interface long native new package private protected public " + + "return short static strictfp super switch synchronized this throw throws transient " + + "try void volatile while"), + blockKeywords: words("catch class do else finally for if switch try while"), + atoms: words("true false null"), + hooks: { + "@": function(stream, state) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); + CodeMirror.defineMIME("text/x-csharp", { + name: "clike", + keywords: words("abstract as base bool break byte case catch char checked class const continue decimal" + + " default delegate do double else enum event explicit extern finally fixed float for" + + " foreach goto if implicit in int interface internal is lock long namespace new object" + + " operator out override params private protected public readonly ref return sbyte sealed short" + + " sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked" + + " unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get" + + " global group into join let orderby partial remove select set value var yield"), + blockKeywords: words("catch class do else finally for foreach if struct switch try while"), + atoms: words("true false null"), + hooks: { + "@": function(stream, state) { + if (stream.eat('"')) { + state.tokenize = tokenAtString; + return tokenAtString(stream, state); + } + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); + CodeMirror.defineMIME("text/x-groovy", { + name: "clike", + keywords: words("abstract as assert boolean break byte case catch char class const continue def default " + + "do double else enum extends final finally float for goto if implements import " + + "in instanceof int interface long native new package property private protected public " + + "return short static strictfp super switch synchronized this throw throws transient " + + "try void volatile while"), + atoms: words("true false null"), + hooks: { + "@": function(stream, state) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); +}()); diff --git a/CodeMirror-2.2/mode/clike/index.html b/CodeMirror-2.2/mode/clike/index.html new file mode 100644 index 0000000..5e375ef --- /dev/null +++ b/CodeMirror-2.2/mode/clike/index.html @@ -0,0 +1,101 @@ + + + + CodeMirror: C-like mode + + + + + + + +

CodeMirror: C-like mode

+ +
+ + + +

Simple mode that tries to handle C-like languages as well as it + can. Takes two configuration parameters: keywords, an + object whose property names are the keywords in the language, + and useCPP, which determines whether C preprocessor + directives are recognized.

+ +

MIME types defined: text/x-csrc + (C code), text/x-c++src (C++ + code), text/x-java (Java + code), text/x-groovy (Groovy code).

+ + diff --git a/CodeMirror-2.2/mode/css/css.js b/CodeMirror-2.2/mode/css/css.js new file mode 100644 index 0000000..45170a3 --- /dev/null +++ b/CodeMirror-2.2/mode/css/css.js @@ -0,0 +1,124 @@ +CodeMirror.defineMode("css", function(config) { + var indentUnit = config.indentUnit, type; + function ret(style, tp) {type = tp; return style;} + + function tokenBase(stream, state) { + var ch = stream.next(); + if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());} + else if (ch == "/" && stream.eat("*")) { + state.tokenize = tokenCComment; + return tokenCComment(stream, state); + } + else if (ch == "<" && stream.eat("!")) { + state.tokenize = tokenSGMLComment; + return tokenSGMLComment(stream, state); + } + else if (ch == "=") ret(null, "compare"); + else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); + else if (ch == "\"" || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + else if (ch == "#") { + stream.eatWhile(/[\w\\\-]/); + return ret("atom", "hash"); + } + else if (ch == "!") { + stream.match(/^\s*\w*/); + return ret("keyword", "important"); + } + else if (/\d/.test(ch)) { + stream.eatWhile(/[\w.%]/); + return ret("number", "unit"); + } + else if (/[,.+>*\/]/.test(ch)) { + return ret(null, "select-op"); + } + else if (/[;{}:\[\]]/.test(ch)) { + return ret(null, ch); + } + else { + stream.eatWhile(/[\w\\\-]/); + return ret("variable", "variable"); + } + } + + function tokenCComment(stream, state) { + var maybeEnd = false, ch; + while ((ch = stream.next()) != null) { + if (maybeEnd && ch == "/") { + state.tokenize = tokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return ret("comment", "comment"); + } + + function tokenSGMLComment(stream, state) { + var dashes = 0, ch; + while ((ch = stream.next()) != null) { + if (dashes >= 2 && ch == ">") { + state.tokenize = tokenBase; + break; + } + dashes = (ch == "-") ? dashes + 1 : 0; + } + return ret("comment", "comment"); + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) + break; + escaped = !escaped && ch == "\\"; + } + if (!escaped) state.tokenize = tokenBase; + return ret("string", "string"); + }; + } + + return { + startState: function(base) { + return {tokenize: tokenBase, + baseIndent: base || 0, + stack: []}; + }, + + token: function(stream, state) { + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + + var context = state.stack[state.stack.length-1]; + if (type == "hash" && context == "rule") style = "atom"; + else if (style == "variable") { + if (context == "rule") style = "number"; + else if (!context || context == "@media{") style = "tag"; + } + + if (context == "rule" && /^[\{\};]$/.test(type)) + state.stack.pop(); + if (type == "{") { + if (context == "@media") state.stack[state.stack.length-1] = "@media{"; + else state.stack.push("{"); + } + else if (type == "}") state.stack.pop(); + else if (type == "@media") state.stack.push("@media"); + else if (context == "{" && type != "comment") state.stack.push("rule"); + return style; + }, + + indent: function(state, textAfter) { + var n = state.stack.length; + if (/^\}/.test(textAfter)) + n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; + return state.baseIndent + n * indentUnit; + }, + + electricChars: "}" + }; +}); + +CodeMirror.defineMIME("text/css", "css"); diff --git a/CodeMirror-2.2/mode/css/index.html b/CodeMirror-2.2/mode/css/index.html new file mode 100644 index 0000000..4993434 --- /dev/null +++ b/CodeMirror-2.2/mode/css/index.html @@ -0,0 +1,55 @@ + + + + CodeMirror: CSS mode + + + + + + + +

CodeMirror: CSS mode

+
+ + +

MIME types defined: text/css.

+ + + diff --git a/CodeMirror-2.2/mode/javascript/index.html b/CodeMirror-2.2/mode/javascript/index.html new file mode 100644 index 0000000..c3ab91d --- /dev/null +++ b/CodeMirror-2.2/mode/javascript/index.html @@ -0,0 +1,77 @@ + + + + CodeMirror: JavaScript mode + + + + + + + +

CodeMirror: JavaScript mode

+ +
+ + + +

JavaScript mode supports a single configuration + option, json, which will set the mode to expect JSON + data rather than a JavaScript program.

+ +

MIME types defined: text/javascript, application/json.

+ + diff --git a/CodeMirror-2.2/mode/javascript/javascript.js b/CodeMirror-2.2/mode/javascript/javascript.js new file mode 100644 index 0000000..be2a069 --- /dev/null +++ b/CodeMirror-2.2/mode/javascript/javascript.js @@ -0,0 +1,360 @@ +CodeMirror.defineMode("javascript", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var jsonMode = parserConfig.json; + + // Tokenizer + + var keywords = function(){ + function kw(type) {return {type: type, style: "keyword"};} + var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); + var operator = kw("operator"), atom = {type: "atom", style: "atom"}; + return { + "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "var": kw("var"), "const": kw("var"), "let": kw("var"), + "function": kw("function"), "catch": kw("catch"), + "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), + "in": operator, "typeof": operator, "instanceof": operator, + "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom + }; + }(); + + var isOperatorChar = /[+\-*&%=<>!?|]/; + + function chain(stream, state, f) { + state.tokenize = f; + return f(stream, state); + } + + function nextUntilUnescaped(stream, end) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == end && !escaped) + return false; + escaped = !escaped && next == "\\"; + } + return escaped; + } + + // Used as scratch variables to communicate multiple values without + // consing up tons of objects. + var type, content; + function ret(tp, style, cont) { + type = tp; content = cont; + return style; + } + + function jsTokenBase(stream, state) { + var ch = stream.next(); + if (ch == '"' || ch == "'") + return chain(stream, state, jsTokenString(ch)); + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) + return ret(ch); + else if (ch == "0" && stream.eat(/x/i)) { + stream.eatWhile(/[\da-f]/i); + return ret("number", "number"); + } + else if (/\d/.test(ch)) { + stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); + return ret("number", "number"); + } + else if (ch == "/") { + if (stream.eat("*")) { + return chain(stream, state, jsTokenComment); + } + else if (stream.eat("/")) { + stream.skipToEnd(); + return ret("comment", "comment"); + } + else if (state.reAllowed) { + nextUntilUnescaped(stream, "/"); + stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla + return ret("regexp", "string"); + } + else { + stream.eatWhile(isOperatorChar); + return ret("operator", null, stream.current()); + } + } + else if (ch == "#") { + stream.skipToEnd(); + return ret("error", "error"); + } + else if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar); + return ret("operator", null, stream.current()); + } + else { + stream.eatWhile(/[\w\$_]/); + var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; + return (known && state.kwAllowed) ? ret(known.type, known.style, word) : + ret("variable", "variable", word); + } + } + + function jsTokenString(quote) { + return function(stream, state) { + if (!nextUntilUnescaped(stream, quote)) + state.tokenize = jsTokenBase; + return ret("string", "string"); + }; + } + + function jsTokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = jsTokenBase; + break; + } + maybeEnd = (ch == "*"); + } + return ret("comment", "comment"); + } + + // Parser + + var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; + + function JSLexical(indented, column, type, align, prev, info) { + this.indented = indented; + this.column = column; + this.type = type; + this.prev = prev; + this.info = info; + if (align != null) this.align = align; + } + + function inScope(state, varname) { + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return true; + } + + function parseJS(state, style, type, content, stream) { + var cc = state.cc; + // Communicate our context to the combinators. + // (Less wasteful than consing up a hundred closures on every call.) + cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; + + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = true; + + while(true) { + var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; + if (combinator(type, content)) { + while(cc.length && cc[cc.length - 1].lex) + cc.pop()(); + if (cx.marked) return cx.marked; + if (type == "variable" && inScope(state, content)) return "variable-2"; + return style; + } + } + } + + // Combinator utils + + var cx = {state: null, column: null, marked: null, cc: null}; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + function register(varname) { + var state = cx.state; + if (state.context) { + cx.marked = "def"; + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return; + state.localVars = {name: varname, next: state.localVars}; + } + } + + // Combinators + + var defaultVars = {name: "this", next: {name: "arguments"}}; + function pushcontext() { + if (!cx.state.context) cx.state.localVars = defaultVars; + cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; + } + function popcontext() { + cx.state.localVars = cx.state.context.vars; + cx.state.context = cx.state.context.prev; + } + function pushlex(type, info) { + var result = function() { + var state = cx.state; + state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info) + }; + result.lex = true; + return result; + } + function poplex() { + var state = cx.state; + if (state.lexical.prev) { + if (state.lexical.type == ")") + state.indented = state.lexical.indented; + state.lexical = state.lexical.prev; + } + } + poplex.lex = true; + + function expect(wanted) { + return function expecting(type) { + if (type == wanted) return cont(); + else if (wanted == ";") return pass(); + else return cont(arguments.callee); + }; + } + + function statement(type) { + if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); + if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); + if (type == "keyword b") return cont(pushlex("form"), statement, poplex); + if (type == "{") return cont(pushlex("}"), block, poplex); + if (type == ";") return cont(); + if (type == "function") return cont(functiondef); + if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), + poplex, statement, poplex); + if (type == "variable") return cont(pushlex("stat"), maybelabel); + if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), + block, poplex, poplex); + if (type == "case") return cont(expression, expect(":")); + if (type == "default") return cont(expect(":")); + if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), + statement, poplex, popcontext); + return pass(pushlex("stat"), expression, expect(";"), poplex); + } + function expression(type) { + if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); + if (type == "function") return cont(functiondef); + if (type == "keyword c") return cont(maybeexpression); + if (type == "(") return cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); + if (type == "operator") return cont(expression); + if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); + if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); + return cont(); + } + function maybeexpression(type) { + if (type.match(/[;\}\)\],]/)) return pass(); + return pass(expression); + } + + function maybeoperator(type, value) { + if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); + if (type == "operator") return cont(expression); + if (type == ";") return; + if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); + if (type == ".") return cont(property, maybeoperator); + if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); + } + function maybelabel(type) { + if (type == ":") return cont(poplex, statement); + return pass(maybeoperator, expect(";"), poplex); + } + function property(type) { + if (type == "variable") {cx.marked = "property"; return cont();} + } + function objprop(type) { + if (type == "variable") cx.marked = "property"; + if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); + } + function commasep(what, end) { + function proceed(type) { + if (type == ",") return cont(what, proceed); + if (type == end) return cont(); + return cont(expect(end)); + } + return function commaSeparated(type) { + if (type == end) return cont(); + else return pass(what, proceed); + }; + } + function block(type) { + if (type == "}") return cont(); + return pass(statement, block); + } + function vardef1(type, value) { + if (type == "variable"){register(value); return cont(vardef2);} + return cont(); + } + function vardef2(type, value) { + if (value == "=") return cont(expression, vardef2); + if (type == ",") return cont(vardef1); + } + function forspec1(type) { + if (type == "var") return cont(vardef1, forspec2); + if (type == ";") return pass(forspec2); + if (type == "variable") return cont(formaybein); + return pass(forspec2); + } + function formaybein(type, value) { + if (value == "in") return cont(expression); + return cont(maybeoperator, forspec2); + } + function forspec2(type, value) { + if (type == ";") return cont(forspec3); + if (value == "in") return cont(expression); + return cont(expression, expect(";"), forspec3); + } + function forspec3(type) { + if (type != ")") cont(expression); + } + function functiondef(type, value) { + if (type == "variable") {register(value); return cont(functiondef);} + if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); + } + function funarg(type, value) { + if (type == "variable") {register(value); return cont();} + } + + // Interface + + return { + startState: function(basecolumn) { + return { + tokenize: jsTokenBase, + reAllowed: true, + kwAllowed: true, + cc: [], + lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), + localVars: null, + context: null, + indented: 0 + }; + }, + + token: function(stream, state) { + if (stream.sol()) { + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = false; + state.indented = stream.indentation(); + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + if (type == "comment") return style; + state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/); + state.kwAllowed = type != '.'; + return parseJS(state, style, type, content, stream); + }, + + indent: function(state, textAfter) { + if (state.tokenize != jsTokenBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, + type = lexical.type, closing = firstChar == type; + if (type == "vardef") return lexical.indented + 4; + else if (type == "form" && firstChar == "{") return lexical.indented; + else if (type == "stat" || type == "form") return lexical.indented + indentUnit; + else if (lexical.info == "switch" && !closing) + return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); + else if (lexical.align) return lexical.column + (closing ? 0 : 1); + else return lexical.indented + (closing ? 0 : indentUnit); + }, + + electricChars: ":{}" + }; +}); + +CodeMirror.defineMIME("text/javascript", "javascript"); +CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); diff --git a/CodeMirror-2.2/mode/php/index.html b/CodeMirror-2.2/mode/php/index.html new file mode 100644 index 0000000..7949044 --- /dev/null +++ b/CodeMirror-2.2/mode/php/index.html @@ -0,0 +1,48 @@ + + + + CodeMirror: PHP mode + + + + + + + + + + + +

CodeMirror: PHP mode

+ +
+ + + +

Simple HTML/PHP mode based on + the C-like mode. Depends on XML, + JavaScript, CSS, and C-like modes.

+ +

MIME types defined: application/x-httpd-php (HTML with PHP code), text/x-php (plain, non-wrapped PHP code).

+ + diff --git a/CodeMirror-2.2/mode/php/php.js b/CodeMirror-2.2/mode/php/php.js new file mode 100644 index 0000000..f88b3f8 --- /dev/null +++ b/CodeMirror-2.2/mode/php/php.js @@ -0,0 +1,120 @@ +(function() { + function keywords(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + function heredoc(delim) { + return function(stream, state) { + if (stream.match(delim)) state.tokenize = null; + else stream.skipToEnd(); + return "string"; + } + } + var phpConfig = { + name: "clike", + keywords: keywords("abstract and array as break case catch cfunction class clone const continue declare " + + "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " + + "final for foreach function global goto if implements interface instanceof namespace " + + "new or private protected public static switch throw try use var while xor return" + + "die echo empty exit eval include include_once isset list require require_once print unset"), + blockKeywords: keywords("catch do else elseif for foreach if switch try while"), + atoms: keywords("true false null TRUE FALSE NULL"), + multiLineStrings: true, + hooks: { + "$": function(stream, state) { + stream.eatWhile(/[\w\$_]/); + return "variable-2"; + }, + "<": function(stream, state) { + if (stream.match(/</; + state.mode = 'php'; + } + else if (style == "tag" && stream.current() == ">" && state.curState.context) { + if (/^script$/i.test(state.curState.context.tagName)) { + state.curMode = jsMode; + state.curState = jsMode.startState(htmlMode.indent(state.curState, "")); + state.curClose = /^<\/\s*script\s*>/i; + state.mode = 'javascript'; + } + else if (/^style$/i.test(state.curState.context.tagName)) { + state.curMode = cssMode; + state.curState = cssMode.startState(htmlMode.indent(state.curState, "")); + state.curClose = /^<\/\s*style\s*>/i; + state.mode = 'css'; + } + } + return style; + } + else if (stream.match(state.curClose, false)) { + state.curMode = htmlMode; + state.curState = state.html; + state.curClose = null; + state.mode = 'html'; + return dispatch(stream, state); + } + else return state.curMode.token(stream, state.curState); + } + + return { + startState: function() { + var html = htmlMode.startState(); + return {html: html, + php: phpMode.startState(), + curMode: parserConfig.startOpen ? phpMode : htmlMode, + curState: parserConfig.startOpen ? phpMode.startState() : html, + curClose: parserConfig.startOpen ? /^\?>/ : null, + mode: parserConfig.startOpen ? 'php' : 'html'} + }, + + copyState: function(state) { + var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html), + php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur; + if (state.curState == html) cur = htmlNew; + else if (state.curState == php) cur = phpNew; + else cur = CodeMirror.copyState(state.curMode, state.curState); + return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur, curClose: state.curClose}; + }, + + token: dispatch, + + indent: function(state, textAfter) { + if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) || + (state.curMode == phpMode && /^\?>/.test(textAfter))) + return htmlMode.indent(state.html, textAfter); + return state.curMode.indent(state.curState, textAfter); + }, + + electricChars: "/{}:" + } + }); + CodeMirror.defineMIME("application/x-httpd-php", "php"); + CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); + CodeMirror.defineMIME("text/x-php", phpConfig); +})(); diff --git a/CodeMirror-2.2/mode/xml/index.html b/CodeMirror-2.2/mode/xml/index.html new file mode 100644 index 0000000..3b6d6af --- /dev/null +++ b/CodeMirror-2.2/mode/xml/index.html @@ -0,0 +1,44 @@ + + + + CodeMirror: XML mode + + + + + + + +

CodeMirror: XML mode

+
+ +

The XML mode supports two configuration parameters:

+
+
htmlMode (boolean)
+
This switches the mode to parse HTML instead of XML. This + means attributes do not have to be quoted, and some elements + (such as br) do not require a closing tag.
+
alignCDATA (boolean)
+
Setting this to true will force the opening tag of CDATA + blocks to not be indented.
+
+ +

MIME types defined: application/xml, text/html.

+ + diff --git a/CodeMirror-2.2/mode/xml/xml.js b/CodeMirror-2.2/mode/xml/xml.js new file mode 100644 index 0000000..71e0e2b --- /dev/null +++ b/CodeMirror-2.2/mode/xml/xml.js @@ -0,0 +1,252 @@ +CodeMirror.defineMode("xml", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var Kludges = parserConfig.htmlMode ? { + autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true, + "meta": true, "col": true, "frame": true, "base": true, "area": true}, + doNotIndent: {"pre": true}, + allowUnquoted: true + } : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false}; + var alignCDATA = parserConfig.alignCDATA; + + // Return variables for tokenizers + var tagName, type; + + function inText(stream, state) { + function chain(parser) { + state.tokenize = parser; + return parser(stream, state); + } + + var ch = stream.next(); + if (ch == "<") { + if (stream.eat("!")) { + if (stream.eat("[")) { + if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); + else return null; + } + else if (stream.match("--")) return chain(inBlock("comment", "-->")); + else if (stream.match("DOCTYPE", true, true)) { + stream.eatWhile(/[\w\._\-]/); + return chain(doctype(1)); + } + else return null; + } + else if (stream.eat("?")) { + stream.eatWhile(/[\w\._\-]/); + state.tokenize = inBlock("meta", "?>"); + return "meta"; + } + else { + type = stream.eat("/") ? "closeTag" : "openTag"; + stream.eatSpace(); + tagName = ""; + var c; + while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; + state.tokenize = inTag; + return "tag"; + } + } + else if (ch == "&") { + stream.eatWhile(/[^;]/); + stream.eat(";"); + return "atom"; + } + else { + stream.eatWhile(/[^&<]/); + return null; + } + } + + function inTag(stream, state) { + var ch = stream.next(); + if (ch == ">" || (ch == "/" && stream.eat(">"))) { + state.tokenize = inText; + type = ch == ">" ? "endTag" : "selfcloseTag"; + return "tag"; + } + else if (ch == "=") { + type = "equals"; + return null; + } + else if (/[\'\"]/.test(ch)) { + state.tokenize = inAttribute(ch); + return state.tokenize(stream, state); + } + else { + stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/); + return "word"; + } + } + + function inAttribute(quote) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.next() == quote) { + state.tokenize = inTag; + break; + } + } + return "string"; + }; + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = inText; + break; + } + stream.next(); + } + return style; + }; + } + function doctype(depth) { + return function(stream, state) { + var ch; + while ((ch = stream.next()) != null) { + if (ch == "<") { + state.tokenize = doctype(depth + 1); + return state.tokenize(stream, state); + } else if (ch == ">") { + if (depth == 1) { + state.tokenize = inText; + break; + } else { + state.tokenize = doctype(depth - 1); + return state.tokenize(stream, state); + } + } + } + return "meta"; + }; + } + + var curState, setStyle; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + + function pushContext(tagName, startOfLine) { + var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); + curState.context = { + prev: curState.context, + tagName: tagName, + indent: curState.indented, + startOfLine: startOfLine, + noIndent: noIndent + }; + } + function popContext() { + if (curState.context) curState.context = curState.context.prev; + } + + function element(type) { + if (type == "openTag") { + curState.tagName = tagName; + return cont(attributes, endtag(curState.startOfLine)); + } else if (type == "closeTag") { + var err = false; + if (curState.context) { + err = curState.context.tagName != tagName; + } else { + err = true; + } + if (err) setStyle = "error"; + return cont(endclosetag(err)); + } + return cont(); + } + function endtag(startOfLine) { + return function(type) { + if (type == "selfcloseTag" || + (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) + return cont(); + if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();} + return cont(); + }; + } + function endclosetag(err) { + return function(type) { + if (err) setStyle = "error"; + if (type == "endTag") { popContext(); return cont(); } + setStyle = "error"; + return cont(arguments.callee); + } + } + + function attributes(type) { + if (type == "word") {setStyle = "attribute"; return cont(attributes);} + if (type == "equals") return cont(attvalue, attributes); + if (type == "string") {setStyle = "error"; return cont(attributes);} + return pass(); + } + function attvalue(type) { + if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} + if (type == "string") return cont(attvaluemaybe); + return pass(); + } + function attvaluemaybe(type) { + if (type == "string") return cont(attvaluemaybe); + else return pass(); + } + + return { + startState: function() { + return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; + }, + + token: function(stream, state) { + if (stream.sol()) { + state.startOfLine = true; + state.indented = stream.indentation(); + } + if (stream.eatSpace()) return null; + + setStyle = type = tagName = null; + var style = state.tokenize(stream, state); + state.type = type; + if ((style || type) && style != "comment") { + curState = state; + while (true) { + var comb = state.cc.pop() || element; + if (comb(type || style)) break; + } + } + state.startOfLine = false; + return setStyle || style; + }, + + indent: function(state, textAfter, fullLine) { + var context = state.context; + if ((state.tokenize != inTag && state.tokenize != inText) || + context && context.noIndent) + return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; + if (alignCDATA && / + + + +CodeMirror 2: ICE Coders Editor of Choice + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/files.php b/files.php new file mode 100644 index 0000000..2198245 --- /dev/null +++ b/files.php @@ -0,0 +1,163 @@ + 2) { // To ignore . and .. directories + if($first_call) { + // Root Directory + $dirRep = str_replace("\\","/",$directory); + $link = str_replace("[link]", "$dirRep/", $return_link); + $link = str_replace("//","/",$link); + $fileAtts = ""; + if ($serverType=="Linux") { + $ownerInfo = posix_getpwuid(fileowner($link)); + $chmodInfo = substr(sprintf('%o', fileperms($link)), -4); + if ($ownerInfo['name']!="nobody"&&(substr($chmodInfo, -1)!=2&&substr($chmodInfo, -1)!=3&&substr($chmodInfo, -1)!=6&&substr($chmodInfo, -1)!=7)) { + $fileAtts = ""; + } + } + $fileManager = "
    "; + $fileManager .= "
  •         / [ROOT] ".$fileAtts.""; + $fileManager .= $fileManager .= fileManager_dir("$directory/", $return_link ,false); + $fileManager .= "
  • "; + $first_call = false; + } else { + $fileManager = "
      "; + } + foreach( $file as $this_file ) { + $bannedFile=false; + for ($i=0;$i"; + } + } + $fileManager .= "
    •         " . htmlspecialchars($this_file) . " ".$fileAtts.""; + $fileManager .= fileManager_dir("$directory/$this_file", $return_link , false); + $fileManager .= "
    • "; + } else { + // File + // Get extension (prefix 'ext-' to prevent invalid classes from extensions that begin with numbers) + $ext = "ext-" . substr($this_file, strrpos($this_file, ".") + 1); + $dirRep = str_replace("\\","/",$directory); + $link = str_replace("[link]", "$dirRep/" . urlencode($this_file), $return_link); + $link = str_replace("//","/",$link); + + $restrictedFile=false; + for ($i=0;$i"; + } + } + $fileManager .= "
    •         " . htmlspecialchars($this_file) . " ".$fileAtts."
    • "; + } else { + if ($_SESSION['userLevel'] == 0) { + $fileAtts = ""; + $fileManager .= "
    •         [HIDDEN] ".$fileAtts."
    • "; + } else { + $fileAtts = ""; + $fileManager .= "
    •         " . htmlspecialchars($this_file) . " ".$fileAtts."
    • "; + } + } + } + } + } + $fileManager .= "
    "; + } + return $fileManager; +} + +// For PHP4 compatibility +function php4_scandir($dir) { + $dh = opendir($dir); + while( false !== ($filename = readdir($dh)) ) { + $files[] = $filename; + } + sort($files); + return($files); +} +?> + + + + +ICE Coder File Manager + + + + + + + + + + + + \ No newline at end of file diff --git a/images/Thumbs.db b/images/Thumbs.db new file mode 100644 index 0000000000000000000000000000000000000000..625bd9f1bce75c64b666cc0e3609f90744d3218a GIT binary patch literal 12800 zcmeI2c|29y+ram6jtqy)Lm@Jxh?1!|AvaU5gp{ac$dC{!5)m1ah*DjYOPX#XW8CEA znlfaLP|B2{$e5Fkv)^ZnZuh?L`@55IjOdnUF+yL+FIlkF+0X4<{%Ud-@T;X#V5ka&N7f9Wa zWANnWFT7wea}9^t&VQ2Oj|P>?tE+H$P<|IJwtUQ&;%5Wty00qjzbj+)$FjnFcfR$<{Fn*500g@h zYYOa{eChvKOu%Bmod08f?hF5a>Hk=Kz+%9c{*T2GECyiy&krmCmI4BRAb{nw3{qi0 z1XvD;0+>070}{XrKoVF9tOBF}X<#)V1IPkcK5HSx><4Q@c|ZYB1e5?}U_Gz_Pyti{ z60i|a1JnTxU=yGT`~++Uv;Zt`9Y}QnJzxu<5Bv-m09ye=U>jfr7z5Zf+aWatb^tp8 zGhi2B4p;!Yfjt1GYYFK-zzVPiYyeweKVS!7w&(yj0tW!>nuCx!11^9oa0qY%+yM{Z zFmMDo3U~ru0Orl!z;VC_!16f(sUP4EV77n*&d`DVJVRe0>|3<;v=JN_)jsS7(Kcur zJRKeO2SR{9dPaJB0)d{HfngCN3o{D~k(o$jUChbOx|m}zk;u-=&cVga!^6YE#>dag z&Ckir!;NKv!^1TMdM0{$CT>c+k9WK<%fm}Yt* zk8$0wxV*J{024DWAODi25-TKEu98wvR8n5QLFK2-TG~3gdRt7ko9@_Yw#(eccE6py zgW~~@!$*#KdL8o)JQWli5_&o;`uv5Mi&2 zWb1Sd<2%2{!e@P)-tZk#rG4tlfm>S7BJ4s3gV(=k>@n-Ow|>B>&MG%AyC8O2=;lS! z4M9UIwLlH^)H0xtN*Snjx#~m_w@Vqr+ zi_0qWvXBG9S(c}L~Eq&f!Alx{#KPziQrr@?zm29aBqwF}p1M07j zkOf@|>N*WWh|NnM)}cr_F-*FoU@66nXeu4N(gpMnVg zU*ZQgZu%bimhra`6sQaBg$Xuh`yRo{htLhZ0JJ~IeDYcYO25y(tYG8C?~!k*zcv&o zjNLQ{Hdg%}!OF+p*RgT>eCuxly0@^-59G)AX~B-4rW&*;Bgs_br#*FvBiexyf28X< z53ONYeKwxw*_NwnF*==op=^Z~xlO z@1KZt+vl1~zj_zczA|v@$kCwbxMcJGjOh#!iF23S#v-%_15rdsVMkP<&5bl>=9lfa zl4yN@BtfPH+B}&limOJCJE2H$T=d5t6;~9I_z*+#O@7hpv#F^gFUP&|_^Lun1^43a zeOuHw?JhfW*NtG=M?sMseiUh?BU@4(hb;>)7OcpM?$yY6YU~y%MI)ROsX^HBCv2Nf z)9Te3d{~`r(_B0DC_TIN!RK;C(3HpCwD%9Pud|iWaD}wHrHW$fP3sOjP5e%c3@G4m zRK8yzS8JV}b1rl5=0kk@ItqJL8TuU3YEh(x?^Scinzynp$-!D8HkD^>w&}QCiSwUg z_w7q*cQ$b-v3Li4n%{)`skj)u9BK+#``f#p&*Rrrh-V9-|KURR{iXl;5q}nJ{F&x% z5R3dn|Ly_xR<{BA6P6MJl5Q@_$9p5I?;TWdb}DnP^ptpH7HD%gTr;rmS8r1pE`v)u zXf5|o@m?x#|4lvg&h4_XyJP~TwOKR$xIlLlU7qdX-4g?hzY?ch{bjS_oZcsF*EKd{ zIezXOgGf(iTVzunnWD81MG^xIQG^`)ATE--?}S8ytFw7eSLkMQ&5G?okGs9c!a53y zI{c=X+EL`?Nev-}lT>w~h@8wD>CT5u1t!;SkjRj$xtIEWXsXRHvg-HTuvSu+Pc{1q zyIeLxOP}1E^oLg_ikmlCSnDsV_39me;*cGblQ+UUCA396FQUF)DJQ@xPt9gbsiAN~ zr@ty=s?}8v1^480QBk66rF5E-vYsAHdlB6_N(`~gPv4TF)4V8`jkC2sc59s5jsE+r zJXup0n0%Qx5b5r3Q~!N2{hkrKvo|RxeCgik=Y&;^Tb9s;a<7Wv@3_#FCiDb3>Zx+& z%7xQHCC}M)siKu4#xFGt6@Te)KDx)H;{EZUh&7@^W{av$W*ZW^CsKr2`vRX3}PGE@CgTy_S!6c zA*In#3#TJtItO_PS5>;so07CTuE-7Ou%54T??t!+xM)eh+QtV-2iBG4G^ah2YhBB`0765o(- zusSC>g>`i*&8&YkSd!aFgUhREQ~D+Itb_{Ni+!QJ4#~D-JL__yV(aUusyD7I`nXjo z^kDK;&D!{=t18}yg;pl{%aH^Ucd4a|M{AF5Ohgf#vFn~3zBqB_{&A=E&J(_NW(^0= zZ#lcXe8ciXpshal!ZG*$z_mc;A2bo>AMyL&G5;`)|L8C=?fB9;)pfA9DRL06!SCm| zEXz09&pR)2FnxMJJ*RB)&RZ0@*YD{U@ZgzD3Wq)4HZRT6t^Em9w+#r2>bB}^*%g`NWr^% zPe|x=T6<)6li}sYW5MKKXqjTu+*7SXGTcVHb^PZuESmG5_ysb5O+<)4{O8}{KkpM* zD0XeTGIsS^TtBy)zbkBohU;U4_RXq!oPpu->x<8nqKM3j*A8Dq`%mxOUw+ToFVFu` z{KwYGzDK@g{$no`xO{g016!l}9)a>_)+w<)3iF-+Z~|Sw+4-jp-%~hTJ6C^fI%U4) z2Y_zb?EK4j7C&=2R_>g9ZGQ7#hWoVsM#NTdeyqR2y5hoLf4J5uTE2$&-(hCj(7IFc^@<0T$%cUZEl$S zznb-2{Pb8L^Y2R$(I5Wv@96)hxVp$?XUGAu2?68I!jIYonyxiw@u$7cYjm!;EM8r& zW>oDKf7RV7p_c53A{=j2HK_{2ha~G?+*Wsd!9P$SPw{S3J~dn{<%J>#o9%}UI~tWe z*Zv}k2-=6$o7`l)t4Ioqk@~ok{~^<0fs|L$YvHv%%EJjicfEZ=;}H%ikbC1D5}B`> zI3T>3D($-e)=M2Hg^@O)kvoE%dHgj^1=q5MtK;ksidvXeoDA49ktQ)xe1fZZHaWpE;venGXoZm&VUhq_e zpIn?1%d4FFn^CpRQGM^pIn|d~j8e~bMn~nmVqv_g)^o_f_o;p76L+G%S69;!#;(oG zx9)GH^IwZB>63D${CosOrWPNtr0_{n8gomAQtkS04EbCpv!jT!>)Yn6ONHLg2i^o9 z4IfgcOnCS)oZzSWA1!HILVmQs z*h@6}a+-p2_>pPys9+;`Sk`dlc6XSk?#6ge8831IuaiA3;U;y9f%VK@1NXn}HdqbuYi7W+7=OdRstRWd z`w_5RXV!oR?D_fo&V-r4$!yM!us3Kw?0d3-oNeLA9klJCENqw1r~M8yOIf-)wO8Y- za4wMJQP8#qoiFvU{SMeV5i*)_}0iw6tj{hbA2{Lz2^JNoZwy#_^9XX{ec2YRGu;*SZpcNjCV zq$Ja&q%g;b@Q4K92u5ZqWU6lduEZMqkL1BSrI`=UP$b%%6mH9^>XL#CUetC3V%9DL oG1nbFt~0*zrx#(y{!ii@o~R*=wkS0|+s5#ZgWZ41>>GanFE?6>?f?J) literal 0 HcmV?d00001 diff --git a/images/backup-open-files.png b/images/backup-open-files.png new file mode 100644 index 0000000000000000000000000000000000000000..d3778054d32d58bfcf28800c4ca1d4352628c924 GIT binary patch literal 551 zcmV+?0@(eDP)(RCwCdRJm@#KoAY~5)N?)LBSzt zL5Pxu9`U*S10UeR6*M3^4v7YdOBkF7k4y~SB_XLY602oq-pupNvm@j2_|0Jbe!taf zxvtyocC*=RwOWnEVh=eMe(xcR$K$8dX}8-Ahr`3+U|H6By&jE5`~6;nj~EQFXf%30 zpOsRmxY=xGvl-4G;o%1bMs3>$9%m|*S}YdZ?e=>-nlt44KJK7^6Zm4WIG@j@#3jkn z87Tk^{`hNO4bP7|X1Q9eJkLXdVi{(OkpeSF1Ypc!Fc_dYxFiyZQmNGGbd+R-@o0{d z{b3kEE|){pyV`U*y^L0iCx8Fba7WK%GFhoq3WWkaD1im5FnM}V0_Ei|_(MEgC+C9m zhBx)6AAQIl6a-0o#7j*0(o>fA`1AREuh%P=%aoAlLh^6@ zwS_a83|>Bjn$0HG#-|7mTdzMPVbt|{-Eo{+tp>H2IO_LDgJ9b2Hm7LHG4dy#ukDi@ zV}Cf0$K!IjOsCTjk7(%yJik`J%NOAVJXg?YG{9Vj|LpmL!u$%~YgR-lb$C%s(R<0d+xdSm1xdR!!~BHRIfs50izXKCWLSr zYV{aYu86rt14oY@Esl?m4;KoBTXaP>m%~E6j>YN>N+ZJ%xgj`6v|39gYpjw|K;u7- zsMAIyG^VDeo{&-=7DB9@n3y=MwSI@dZ4er0Yv4L{h;R;4mypkvnw^m58q44ULP`ih zLneO{15Lk1Z3gq0gE8jq-Me>hEtkuvR4Q-f^0|Yi9bW7#wI~7wsU$N&(5hi%d<-`x zCedC5w4w*0i3-j}8DR(<#dbz$ zJ7Jh1dMYD|xeSCc!ZqhMv=~msd!y|5V z-Da#_Gd5hlznt%MI;3X{q&bvQsLs}_xBtE#P2ZTr`O0xIbNMVrbAf=OVEnuC62}4}I zat-@le-+}NI{@7)(v&@W-`uBXt5vyS+mra{(3c2Zgk~tvoNr=bz5yMO^5h<+G*}is zQg9wo6d?>F6th_z{OTL5Uq6O(Cr{vu58uVY^wlhx&)HJ3gteO=g|QuQlB^|Fp@=EN z#fO&OS1#%e7D?iv8h#{j6d)EC*^mU<_{Kdp07k3go#Slp?nz zwn}?Tn)Q|3!H?tNy1*$o^&tODdk1pP=%khRNf&Ts;8<1mb(d|rh)EZ*-Yskl9SF8i zclxq!=nb3bYX{_r8I!X)3de3CIW5@dGO^IgM=z3Il`fZuSR$9aBUv6|E)zNWjF(PI zL+wpA-Fy9g#xipgKa<|)-inqQoa++>0~N_H)7f9s@MAFJwKshUwX`)FT2v4)?F;Ne z*=s@=OlS-YA1X8Lh3~wdC3!ZDr^ zzKC?foXMqZ;z_2Pr0(@D&_S9?J|r*P82a?sAZ*$|aoq^%y3PeUEJ=!lPXJ%_3lPP_lTi3tYm?bQ78+k~e0_ z-zgePtv05vUB&q`6f4( z!;)!K>gVJf_p11lB5X6;Ni^=ZqB`-q)6fzq05utT){bQ9z z<;dgJ$}z!Bhj)^ABlVS#Tx3!h0%a9oWKFr78^hJeeLt=~}O*JdPmxB;rG~hQ|HR|n~h2~c;3~BVzE4WW&86lzxb~J0|1A2 V9ktd-Yy|)S002ovPDHLkV1n3w*jWGo literal 0 HcmV?d00001 diff --git a/images/database.png b/images/database.png new file mode 100644 index 0000000000000000000000000000000000000000..087860d182a4363f075e3a598ac45b5297659ed8 GIT binary patch literal 2622 zcmaJ@dpMK*A6^zMr$#FFlBbazVw>}prP(NAjX9TUwg*eIwLLQB#e^cIB$Y$G4wb{3 z#2ZDasi`F$N$Pbd=SU<`t^B4py}v(x{hsT3p6}th@B4FqKHtyvy`B^rb-kK0N*M-& zskv^Tc*#d?`Kyail7IL1$BoJd9mv@qqH{x_C{DnY#7YJQOIL3!$AlL21D5qMD)A58)$&dBBK3lJg^=- zG8o3*u!j%Q_fWl=d%~G`7TR$w;2K5dwmci2klikk4ngF=*gB1PUjj z|1st7K?BHKJ_y)YV9l9WTO43(ZGp4K;;r$k0ZS|ni@{l9uy*D+EWyT(fW-kn9<)3f zpA|yzqPYBsC0`NIVGzV4U@%cpQ5I2F7F>QP28YMvF<48CrKPzXVJ?V{fEYsa2!X+z z0tFN>`D`A<=0*Usii}`xBt%5Zo&J*ohxb!9Lhz$Z@`7Q63?2q&ft^ih4(Q?W|Dhbt zPqYB?0{`{g~K`HoNSzN z_7p2CGKoyFrr=3)Tnd*N$pIsvIWFs8uG25Mv#r44$s|cAa z|E1m!F6-A`@W13@btt(A>WW zTlnI>@0v72za>PU$v01ff;xhTUpv}Ay^XoHRqeTD!%~C@xzI2Xp@}whYQk$S%rMUd zGyuy)BpNPFMEWDQR~&6tUw$x8T(#!L=;@)MZ9aZ&XC`(mZ4$wcAdE{|f_&a}?0ra_ zIvsVqtjvt!3GKZzuGcj+HP9)ePh73(iS9&oUAFNM8&LK-n_fV_9)9y%WeCrg05QItbhNJvL_gYKOiIP{mEtbT_ABfAp_NiY##$_9I zh~T&is6wyu4} zU#3mxlnQqgGM%SuCv5Ad@I5XquQlomWr~}hcD>ps)cZYL#cmW8vU^#q)OmZRh6zF1 zd;~KH)yKOn2-LoLKdYi;KB!SpzO_Np^(Zg*RltPSwvxW$S1QP^vHJ9gZ}b>Wk6w&z z9pze#>ZTW`#+JiHMo6|&!4_m@>iy7+WhU0X$IenJCbceG(yCY;@CF>OFmk+SS~0D$ zE9r`|maKY4GuE~^c#~?yww#_*$?20X6t24^mM&>{5*%itaRf62jB6!|l7L;^w{EMg zmKm7!Jigl~Uc4aviF(E;JO)=a_(;?JOgwv}+qhHw zuGY?5Q&KEQ@+qps6xAA!Ktipx<nnKluL>iBYcmx59V*JMrPCyrcx$wt@3Nz zei~`Sz*CoGzf5*A)X6a|6s2(O#_+(S(8);ICn-}D&+e@zk{ZLjxbEWlaZJ%8o+4H9-m!k^buniMszecJ+e zMAc4*yKZl&e4he4QG*bwFGaMRM`Wh2n2ypfYBANO&X0&NR$0$tQ@x&b~`gX zx+Tkeu}xhXYOgd>$f|CusJA zf7ej7V9U5nPgP0#y?0J?pH3dX;F0v=p}-5ixp&IS$|M|I#j4POxVF<*<7V1&mxcsn z*+o~|;q{7t8y!OmgpCg}FOh88 z%)rRR%(Y`D_paTdV&W2#QhW9vP*7AlsC-E4sJ4#ovEzCsr%lh8oi(>`aCCBZadkWI zbJ^F=|H{>Xu<#oZkx@5qMccpL`1V!gZQK!ExYi=jdc4$9-2N9R%7 zvRUo0he{K|Hf>9_w31zpLxS4&-|zTI#(aRMewXT-W{xX|6c5E^=Wd)0)Iz}7zDi3pp ziICupdmBqB1OKh={0=v~;I^4qPG?!mq$Q3k^6z)8;E!c%OqjwOAay-zUuHK&ggjpSXR-F=u)aS-xMVsUo_=`fwTm#jn zr4RD)do*4M&lfkkxjHpZA18Fyl-u2XleUrDjW?R9SBh*N9lhK0q|m5?KLA}C-m8YY6oH_28F0!N=hOz_R_RHS+#A~ zj?uD)o+2~hC~>{A_~U2dg~Ui>MJ;8 z_=EQp{pzW?o9YYm*zAyH(VcJ(hC9@knayLDqYQWY%5jaz@kVm@ky~+AMpAQ59m>uQ z%1$lk417#^+kD$~#tZxMC3ss&-^#p5II}FYT%BjnymDvPKrd0(#%2TWv#PWQiC@3u zow!2WjISmu!Qv!#IqP^G{!_}dI^m#qjGYmD9r{U)@3{O^65>cjZ}(;w?zsMTT0RJe zeAvaXdcC7HJ^p;F7hB7_Bcyzff<&6OGiN!rc4A_gC>H}1a7co9ZZG|4Yvg(Qj|_bN zh4~R2Oawd4S>u}>Gj{UgkkAjM)mk{jW_Qs_qnE~VXtjsbROYl!fs?1p&d5;lsmy$m z9=2w-y++w3jJZn^VVt)uE)?>LRQDShPNi1vvGI@6&`*}RhuKzW%2b6zG-VZBN~dxh zWtIyL5og?D!y)v>sjSNHVs{MRJ*zyz}9ib9XXdh6kPSA}UFuTxL8k z@M1Xf!@y2#XaADeCMz*^l6vZD98%e4+J8HcZ7Y_h(Q>aH`P~=Sxo=y%5S;Lrd@&Z= zSZJ9VOGhJ9%JiN)=9;Km{mRm#G5YCq(TULp*y_Dc^35CcHkt+%UkHsbP^38cVyvf# zWY5xei3?6DhLUa$$47+|G=yFqEWXxRg!gLtf`ttg8#c{@MOF+N_Q!zHRM$ujt5ny0 zQbflL?@+(-n%Q&P=p1(JIl=1v0=7j32V=Ghwu)ysr0uQuh=z1#%7k~nclfsKbFLXx z#&fiRIOL#}WhC~&vvBpviqa)6M_ajG2Gl_s zh<9+tYL5$sW3?{!hBv3%B%`QZX2UXH<<6-Xo=@S==}r`=wS0)#a6*RXw0tiPdDBsB zQ+nuA?}n0Ivi6X9D6@FRHB81lxA!$KP3b9%Pi#pGTh$VA2nXBcR|kc%2QqBBHw9Ma z>*e|klBqTE`xF%dbZ7t&wzqMxBLgkaW%>MqJ++@luONC=M{Up=2>MB2O=GQqU zrksmy5ns?CdNw#)PHEg&l1je35zZJUs-h0xN=LJf>Hjv~)dtsfu?{5-({Ehb%c1W&~r{Feh-x*a!KK4`YJKjXS)3R}cHOd-Srn zX7hErj9yRo6fw2np04)e3v#~i)?>c$x)O`4j>*iF$er-&L$6!KeD1mWRG+^dSTC+? zY0utW;Ps01Oy?aIGsZgd6O{v$49olc_qT~o5@luk>4eH-tQaOU`>1CTC2l2-r*2G! zGV*OgVipR8RS6%OEZV|LUWd-L zIK+hohrBNu8JsStkbGr@wKzx|f{pDA89Bzvk1ZXrA$~8RSCuxk@W^q@D#og;?WE_E zJKX(8!^6sKrQ2HfWR`Z|kg~*8v!H4IB`>zAjsCuTX@fXKJ?ClDeU7Wv$JirRC%L6Y zy*GVKWg}5YG?%uTc%8W~=;a}wCt(L)NRCAp@`uUneL$*zH)l`n5P`6NAHVd9WlVvU z(sPZxh_38jy`q~Og<%HPX2TPwLxYw2C$)p0_1j6ByC3LIZ+XY}VYzNmJBev0vE>5$ zd?0yQQ*H)#4Oh9MN1XYM8@7ed24nX0Io8^_M0d|c#pbK0>Rk}I9ayC%a>315Z!#T+ zxTRr#BHk^NoD;G*m{;MU5Fml|IY}Kmo_$+A>R_mPlw|kL*T+~skeo};KhrvSzWDup-yi7JY$9uTEd45gdaK2Q||D1u0OP(Xm_d4-tAGX za?Z3!IoiL-FDg42Z;x%dw&$_5F*dWiU@pEpCWfSNcPaESQr=fG^5p}hPWezm|Lt9o zPod!2c8RN5)R^?_Y!^1(FtaI7F%&L_!z43@bW{Th+h-+gh1J|L^s&hT;pWrFamW)E zf3|t@OC?7_o_ld(llu*ccAaia`*@9|uES0-!kV#Whw1ENQ+Z+XCwA2a(bJjGDD^7s z;WniPhm0Ja$;s2$!xHQ(@M!&1E= zF_MO8zZDLNw0!$X>?5_-(0oX=QQPev`F;E+BiM-=y2RafcdE&&TU1V$DEcP)W9&S9 zL+k}t)ZZCed%K6u=g*HAlvXfyF0np8z+v}PwX?{Cys4)o@_xYcx|P^LPjS|^YfJYn zGq)U@vNL`-xg9oF}S|$-L}lVX?K-^;_K_udqO`H4v3N z;!Tit6T9aF|JZ{i_gSf~pJoO=rPm!xxO$Vfv3es5oribKr(y4$f`CVP85BmH&sg5; zj1TTm&{(FXs90=ErKgqZ49yuH?kGB3CsC28n9(mUtQ79luyKYZYh}=LOn9Lb^WN3e z;f_U=F|;y$BOxLiD%YcT$P1udR1ZAj$%ze!*~0dTz6ggjszhT;I9B;dS4-eF{Ls}8 zrlZqos|*VwG1C+N4w!3781cZ<)737?@^Aayu5QfO5o;ZA?1GxGqAlf{wy=>>a{041 zetYDu_1Dr?v$8dPoS9Lwq4GU_?3Enmc+8u8iG%7|Mk{IWz1SN)oRUX%_Krwv2;Js_v(7qta=$e5>A7D%pKZC%R0$$4SLI)TFATWjDCB zduBeqquY8?QzCgsnp#4*YJqzdACUy*r-uy@Qfchr^Y@GR$5|x=$|pMtmva~@dN*BH z)Zg522Zsz^b0`tV5-+KNt=7)_=ha^^qAO|4*yPqaw4HT4IK5Q(I1!_%*0XV=nIiuR z*D{iOqnn5c=A+%JR}~Uho3J;Mc;YMw+J>7Jrf}q))_;#Oe)tvESd}pOne6QYclwBw)~J!A3)6#Y_=bkS-41x$BPS9<@u>^i9{AUwLiY7{|R&Y>PP#d6n|Cw9KiT zL{m68t9PM))y&xT&}a#%?Y>YOiJhyD(>w++HpJBu72`%r$Fsw=rk0Ei@+$8_U%N-s za4w>%C+Nsj`2{ckPMb*&Ll>*0jm5OyHclpNQDF1dIo9{^oo{8m*gD%<+Xff}v41 zE5GyI$aLRkojR{K-cLq)o;ajTshn_7X;Jl zY$tMx_=l4(#C9_p9sIMRO6`}rL)L)GHPk+n*i~5F9AMh{zzi1lN zFO2$;Q9tlDU_0Jh8q`0G`hb7S z|0@sseggIasQiA24*&{)BA^5u1eAe8fC_LJPzBTgG|dr+H2_UO3pfg(ZcQCP7dQqS z2lN1a08L{Eu@PVloB&P&rvMY+G++vx0Z?BgDsK+41z-uB1FQgRzy`1d>;QYf0dNGI z05qKo#IArFa2{|6JOEF?3-AUm094@VNB#3Bz5)-vpX>K{kNRre;RuPs5#A3+M*`Ug zzI8r0MpE!i3ciWLRzcXy2Y*X|B)V4^j=SXNzlC7SfzN;MgKwzjpU*Ywe?=G->nMYM z_64K*SPA|f{zoc=YTf_%*{}Nd_dgO&52e~9jOjT>;de4bFEhK}z7kq8`SF zpDMX{u_x}Qqj%T1n=!X{b#l}!U5PM>z#oji7_`#l(@gt`zM}G;@_;(^SV4~{PyY+G zC2861>2c;Vw>W}Scpi6&Y&)Ql`)*%>l!;!4i{HmsvUUp`Vlr(VpBfmb%p1jcKhr&=^G@#GyeosL4qgfFHXd%8QFZ4O2;1~Vq^TOW~ex&~B zGfnh-p#gnX`FjGYp9nHQpVfYE{ZXB`&z&$l+x?TD->mnaYtNFF-R`EE3Vzj(uJxasV2^)?=b!8L^MA*F;OWiuq<^RWwD=NH@prFk2#o;2uK3(^R2El-v_^J2KWOVzSBeQTy-_*Ceg^ z8vRctkqb8NY`?w>S+gJJb^BSLKk!=5A0}k+`^MaQRR}I7iP{k;Ow?d@yw}v zVahCFmeI|ho}`j1^6e}aNi2!;zS+20L5MeiXo1e2o{r#2uo~UTs~i$l>KIx5eT|~y z1lm(85xLG;fr-sdB-VGQHR6!h=S^)=L$~n(Bnb-qa!t^3v?NL8LK(* zMYj2yaqe2hZn?Oq>ySRS$Er2Nn?=tzp-Hy*N@%rkT1ZG8LBk7ni#v4( zKF~CoPm#~`dB_X4N{)4&)u6= z_(C0-L!yyy+dg_hS!@4_>(`I<_W$R$|3x!QY_Nw_!m{`DhDd*m>Y10d)KvOJi6vQ2|tLgfrsy)BIy&Dq-d9z87>L;#UM6mS!`1w;e4fja=2CI;eI;2sbM+y~-;1RxQ303-nqfn)$plM3-8APq90ZM@~;2H27CPn3Xieg85{ z+~@U|>(3wm?>v7T#^?t2O%2_f%U{$kDZua@`l$a_@9;w}4KjtRe9IgzhlBMwFOY1B zbe`8c6KMIc)_ikB+J4L7u4iWh2P0?7m1#{T$^7sNIecR7ElBvUvRcSf6`xEQi`{%G zzadeJrt|EZ-pfZ``{~Y^*oR(93%XXe7%*+a=E2a~*ZQF8k?FNZ z<1Yewj0-Alu4F!ni)dFvo`*@8ZI!G%k3(SP1^HVnZU57ru#UWlp?Eu%?1Pzy({3>f z1_air(Q7EB^F*_}Y9DiM8fr5086z=HnDg*KWkIM>*jDiy~eX%gNiE_8V0bSVPX?8&wgyVAx1~U*Xr%?23xykT`lj#(LJu&ewJ>m9j$m)bgg?62oa$h z+Fc13>yHRZ4c%{8mXb?LPG~H*zkZ-EH|k)+B|P#hjZC$JaQ9ketNf_Yw7#}B$%=fT z|HFct*rdzCIq!dFE-O^}+s~G{3)5^@J_=ANC7;zj@3BWM&}Hl7 zmB?8Yh68U;bqNX=P^H8@zCJJ{E!oGin8THKH+r-~Yd`A?y`f!?8e{@*Iun&!m7Vyh z-~aF>$-V`-lvR;NJ~{r8_RgzR(+$;wxSnGJ~b8I4xHyqe|VUyQ_QT0}{ z=bkj3W%7uJNZ-OIQuDm6Y(E96nCf5YPIT>`nZeImsyL0P2@_ikCTgo0TWWirYKd%Z zw`{HLHLA+?2^e{BJ7ad)S^l$qt=SLTy8Zkm_9ONO_#c>{KV$}A`1yHQ`BnG$Prs(X zRvtLtXb}JX`ai#qj280xUi}3i%k)LR#2=s^)w>qZI{mv)0Rrv#KTApee*Jh`AS*fm zEyK^b{_D>U*e&s;{{O|#FPD1fqNh!JedO56ll2VL2}8RM5AL<&BvOsk753%5EH0s# zaKT+SaJ4~CJ=lv3OEh5c80+iu(DR-_=e~Ra?=w>`@?B^j-Hu*7@>UQpH^XB%Xe(vF zoIH(}1UAN-_*H+c*5O9qSBj=#-5gnYzM&ZRkldIv4s;opgJO=EDmE&5R|s5;WdP~9 z;ltC%{OX^3TS!l89qm4we_2?#Q!nH7nX`A_6sIKEcnC2P68y&9$XfqN4(IdlG5&=& zK&`*O3*Jli_h0`(*?&W)mq|up;I4b6(Y7ZVCK-n2%to;rX7ws<2swAZh&#xuFV+15 zQ^{fnIMnRalq)BRl0S5S+ewPeN-*7h+Yn`w$w_gLD)jrF{>x#X2KWy8UF3pXCWw9|W|Thi7!Y%^9k z=jeJ~EcIpB!$w1^(igvBEx+y;*X*Yj`r~!`S@$3PiThA*xyr$i_;Mb}nI^7a^VMdn39f?UHB6z}nUCyx>1UHV((e()?6Y|Y!{_IlgD)$z zPr^Q1SbJ^`Yt+$qWtzj!?125G-^iSU>8)}yA+~k`hfhS8B8{UR8nOhL-0rE^`b5_ z7=_h}g0tW9{X0L>)4q&*WkPShQ*gm6b!zVaDI_{+uDQ=>cZ4{o~{X;i`uer*(EkU78{#*=yF)ZT0I(CTsTd=?Cv$r2c^MCpzu~ z_1``I90u9Xi}oQ#-yZUN0?dE^tQRc<8onp5k07)*|6k}Y(2u^Vc>m{1Ec))6KfnHz zpnnxTVG!2W|F6Hl`8VE7{qNr2yfj?dx=TDMt|rT+Hsw&ZIPs*AYXE^`mw1?<@__uV z(WmE}%N2_K+!dCDgq6sqI4!acrEwpz74q9sEji36n}z9R@=$&F-fLG=Oq*VQW{A2- zSD> zh$R3?KnmCcNCPr}EFcHS13v+Kfqej)?f}FJfFhs-90ZhsLx2i!7*GY&0CnI9fTq)g zSPM7`Xn)xToBtMJ{r&gf@nZk~o%Od%w=3Cb(;QPhEe)Q&;Y-RYDBk>GzR@?5Bkw53 zu4@5NeXlR2XsN(u6~#v*Zd=hUk)UT$wAGo%hm<)iQdZz7l)>Xm3IIq<|BT#l(lnw6vxi zrEgseYyBtsJYjwOw(dXs6a8mPT6)vt!8sUXTH_Av`QC~SM-u#JP7ci3?~d9WpzvS% z(7x4~Le7+{Hg!afz2Rfc^7i;=HYtXq_%9{$Dsv-eJfqDoa#B6kVvb}yp=*l_>PGkM zxb@JYhwEu+Tdn|!da^++S&?>6dMi6)tHP#DVueSBU!Cd|*)^;GKoyp?iK*@wtL&j| z$PK(k(|5ePtEY61^+8m_4Sn&TgRfI4lppU_AqyWfwmg0$X@7LYM3mR7^rEr13(R(D zds>q%CEA@lMT?rA{>zs`e8*kPn*GiE;P`L-{(t@c{|E2?S2j0u98Bx!cMP;rbhEbJ zFY`t^vr`1`<^Js>)siDs?h<=Tgk*FDJ8B+uk#P8pHtQ>IEe@FZpqV%j!b?DK{b{Dd zvt%2&XLi=D^Ah4hwe&4DLfy(#rsN{jIRlf?n&uzklb zy-t`4P1+k?=l*d554{qtwSSTI>(39(9})Qr{102;9$Eg2{{wxu?C%Lb;{V|W{pffP z4Pt+RelgI$?~8u%->?7k`!`V!J38R_T&aKau^;p+ebK-E|EqrUKXd&%|HmQ@F<7}r zt5ec4=^@mY>dkm;yY8jMSZdvSjXjW)~qN#GC=etrz{X{v29GUv7(VBL3Z3Zrt4=)1<1OO@0UeBC zO6GdpC->PEDRwFIzP1ZfJ>Q~3*)DHZsyaDa5^EPdRD$}E*ZNNuXb8GRJZAa`(gcXrOKSle=O`#W=mg-ywVz@OkKCRlgzn$r5)hYFy zw2_Yp+4?*~LPEl@Xne&j_S-S<*WK%y{fMvI&kx;ytY3eA`1-Ttu0P$^^l^;O=J?~L z%gjFdyafXHnJ{^g`c9!HoLzp~b}&Y0%9-?DY;iq5bn?D>^5ug3=5y9I_sp{Lsh-(h zSLZw}Y|Ux*vR-qqtX-v>PT|zi(W2n!j-K1`fh)ott&L7{++iI≤;Oydw`3Bt()d zDK47@#U7m+F%&5)x^{PE^=3!f>yC(qOV4NPf3oJ^aZBS^iU<{#c3nf*9^DY1xz&ax z!?XvhhBzdxKCSlT#o)~XO3=gJ>uk38<3)5HKz47&H#w+(D`N~LG4a?K*@yZ6tgvbjb^RN$AsoN&ybBsTP zzO9@q>=Fg#wpsYMnY42BIONp(nuo4#Vq30^zuV7$n?N); zlpw-Y9CM`Mu@avC{p&<_29%dp2`uDzT2!mz6XmWYs8C(P=qC!Pa&Ff?EVNJAlq`kr z$+#rJrt={_$(JiVotkeX)wM=?O{y1~my9*U8t-{)-aoQLsz~iM<6d*TH@9*XFs7c)YoPj*~5IKQ@@z8#SOdZzmjo)SxEMu zb8`G9FI3xRRPM`sB1f3}^lJ%*uX3`5xme$p2c7xE_>BZQyUh_wh0ZAZdX5yT4PD=` bR&sPM+^@Bvs~`SH!r>P)pwONFzlQ$@tf^Js literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/application.png b/images/file-manager-icons/application.png new file mode 100644 index 0000000000000000000000000000000000000000..1dee9e366094e87db68c606d0522d72d4b939818 GIT binary patch literal 464 zcmV;>0WbcEP)8e6`gpm!y1M!N^ZV(=IC*t) z{^;nqJv-tM$9J1L2QJ2DN!#51=1_l@G`2=6e0lehL%sic%`_4--LFM}IF!KzJCseW zq1I3__Z40|e?qyK1__gzP(qrBf-G7SQbQ`#Lw94WVe(o`qg+f4hy;Qju)q#I(9{`% zQmAGomzhQ!b|gq>KqL@IkO~$=Koi}a$u6d07kiS}NoYVMJjAeZpaB*;wwcDdEbK@K zNP;B7RzhQ|H9AlUO<`J>m1(5R)Pb-iLBb@7Jp)}LHdAb-VVgYxVoTzGoqu{~a>6uj zeqCRFI9pC#h09bGwy9;oHcp6(RB%jeY^F=Ll!S+9JkVe4nDG7tJMQiP0000^~*-1fljz_B$LUvK}k?BNXe#Y!m=zM!!V#}8bncK5m;8VP zw86G*RI63?Cd%b9bX|ueNlZ|wR6rj|r_)VIP@r2imh3?SN+^{|kY%~8B{maJ@F*OK z&VH9LwOeGt#DRjj0~v~8`>iO7!Ybi;zE$va`A^T#yW`y44;k^#O~K5*jD=qcUhPSc zvyy~q;5H_1WT1l~cqje9yfa+l!hu6xjdOJ8s;8E^+=QQ$tw p?%p!Hy#YapB=@+^9(46X{{RQg%9y;OKjr`c002ovPDHLkV1g7l326WT literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/css.png b/images/file-manager-icons/css.png new file mode 100644 index 0000000000000000000000000000000000000000..f907e44b3330e3ed1763e42746a2943234adb94d GIT binary patch literal 618 zcmV-w0+s!VP)Z@gK0z$EtPV#+`^OH`R@cE-cuE&_!D)SZGxmQxeobP_Zwq zMEgi6ePN45N`|V1so0uE8^}1xw8s;VM%Ai@7} z2-&Cyvez_-O4?6uv{zTaj|YeYEk34i~K@`8YW2g{x* zc;7z3lItpVy_et{Z-ZZ)<@*%{l7Ao8mu@V7*gz<_1##mwW*%LEwCdzNsVLYx2*T-J z#HeQ*_a=R~KDdVNk$EVgAIRl$oQi_(`_IrdJciDpH|Xe{K-YsMtc!cRnFi$qzsr4z z5*$;ecov%3->1{YNy6-Gf(Ecy&_I$CjI#laeuE+S120^|Vjsf)W&i*H07*qoM6N<$ Ef)^>s`J(VpX#y^kqzQ;#=2x({YMw9Q&ndHT&`BD$#%Ql?{+)-OuSA`r}MWJ zVg+2Gc(GW}a=BERPNy^;kEz$|38dTYlFQ{%5S!g@|8f8D_!Nu9_Ni2glF1}xG8xi! zorc39&F6EPOeWOt_XS`W2H_Bo$MXugy}SEctJQj=(TLXTHL(jRXfzs>NF=0SHk;94 zF!&HjdZNX(3U3;LY64IMX__Xv%_wjLC!J2`0Jw?X=zPK$C$`&dYPDKaC={e16bcE@ zgun^<0k;ak*=xLE)@(Lqu~MmsFoMCLY&0Qog`NO(h@kyxaA%EbwJLy8sU*Vi`~52K zX0wrqW;_LmMq@evX4iAM9Od(Q0eHP$1%L|xAh@vrqB`HPQLon}f3aAka=9!3hr=O- z5F9`#J_7Jhah=U(4RjaRhkS4Xkk98kDz-`i!r|~~AQ1TFcDw(@<8g{aBE)l)PNxNE zI(RPyc>9e{@WGSMU%i7*v{!&P$WLz25)0oc=Dl-yy%xYZAm4b-rttL7UjR#%`#j_F R;_mx(K@^6+>g^d@v4;gkbWsEoXE%32*i1tcpTNXd5CcIl)ECgqz|2rE6EW}s7R?kl za1q`0GCkMruC6-2LANtwVlsgzsp4?{@7$`KBv!G66>Vie3h?3OmEEkjwdLG0PgLVi z`!N((f$A@n17Ldj#`};0I3@iHJ5M{#IZz|UIYRm4(!uV7eYIYIwQf&}_2J~}>pQ^n z6o8--^T(=hkBNQ_k{-_GWE;FMW7!p}f{NG3nHZ{D5<3d8&tLh%a4AqqnjMkr3m&fkMdECD3N5}Unig5wy40;>lo4j~k+e}v)` zR6)J8Mk*u=SpB`p6o)7j?S0T@9?bz#m@l>gc*zk__|*!FMcHwP!gwLJvS~9c0px8E zWhkjP zNW|QGv-YFNLN^qH@tJycPNG5ti6B7;r4mEr#lr@*T8*M85D`{ZR^BWwF23T<%MYIh zdC)S*p=|xk^!~H=+HSZ183~y8v4|mYmZxt&)5{{~>J`>E223Q5>T$=~mtA71q-jdG z+eJhOAyBW^0k9Gk1+rX8)zFx((CG^&tDY>6XaS~Fy!WJON|Gdujg5^~Vzt@o%BcYLiNiTQSD`zL^ociBz_>bDlpw3kriQ@Z`bVsGz-_6N>$&gTDiKDTKR^ z-hB*tHa^>!oD~5TK^0UK5rZ}RBm50Bv}S-yA%s=Ha5RYb{)!z2N&$&64gfhybBu8p lh~_|?8^bu;BRYt{<}Yrwd83Y=s?Goa002ovPDHLkV1l%3CP4rI literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/file.png b/images/file-manager-icons/file.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8b1ca0000bc8fa8d0379926736029f8fabe364 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E zYiz5X^`c$+%8#zC{u)yfe-5 zmgid={Z3k(ERKCKrE7DF;=x4^O+ pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6 literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/film.png b/images/file-manager-icons/film.png new file mode 100644 index 0000000000000000000000000000000000000000..b0ce7bb198a3b268bd634d2b26e9b710f3797d37 GIT binary patch literal 653 zcmV;80&@L{P)WO3(`_cf+b25@DJ#zdQm}8GzWtq2-QnZ8W6mB^kfeK5f%S{ zUW%tGMCwrwic~ZrQcG=4f?5bkV+3dRk8hw6bk~y$KX#b!y*J4EJ~>;dRASqrSu;ZpM>?P}K~6AT zWv6Dmq?v&9LdXC(m%WCO6ma_di$R(v$@ad_>@R41N3N5lSJq9@6CGhX84-$%Xrd_6 z;){?{E|Ytt5$S-&Au>t4wDlIxdkfe-a22LMj``McG};r8@{GsRPm*+8fFey6C)@ifDBXVyTw(N@Xd41b45OFg6x_QA zpwLiigyy~cVoPxW^r~C7ZQpr%>1$*HKmv~AY-qJw4;gUecS--wnqslISSS=^KA&Ic n@BK|Onfz#3R%n{$a)0j^sqv5F(1NTL00000NkvXXu0mjf3S}fX literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/flash.png b/images/file-manager-icons/flash.png new file mode 100644 index 0000000000000000000000000000000000000000..5769120b1b6d38019b505c9167498ea199212cc1 GIT binary patch literal 582 zcmV-M0=fN(P)OL3{+!MJa`3kv~Q#QfQ%c z)1s}QE<_XaYBG;IuRF=td#+}fi4h(6HgoUyJLi0t(*dA^B)%@8kkG&bdM5P5^Z5WF z%d%>m^SbN0XeV)wbUOXn5Ag#A$gJx+7-OCkMM1S%MWIlTkbFLmOeW(&n&wUd&;`>p zVcRy$Z{K0=?SpNnP^;BYEEXleFbq(UY&LrXX$6qkJ~)8+b{=jj3HEXds;Z(?D%}}L zX3`39&dy=Zyar!ehA}e>w)(*vrCct{PI9^2Jpj&OZS8<3-@{0(gNv%1{)zAiLY+_^ zl}e>Ofd4&#Irj#7>=o=Uhv5IJ@?sN0^J|(WL2Uun$4}si6}TG-s3T#p&6GE<<2W)O zf{^Y2HlO#*QDvTp3v&d@;8*}aUC4lisG9(w7@d5Y8y)}U#FwCkqp*Mcgme4{&gGRf zlBfd`nF9cQBKB2_L{F8G2)7pAf$i)Ds`|}-c>pc^LRW{w4SQ)3N^BbZx)6BlCZts! zKph%`(m#xg-q3I7=(us;9<)*2%iuQ1J`oV3gU6V~T}^JU5714JN33&GwEEru0d}Uo U{MPL+lmGw#07*qoM6N<$f^vibe*gdg literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/html.png b/images/file-manager-icons/html.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2490ed1432d5d667a76235360824a1088e928 GIT binary patch literal 734 zcmV<40wMj0P)JT{hN;C#tgf#9krG=I>5!<*aE1_(spcgF}<`n4i zJi-}^6UUeU4jUFwdCiVPDm%`Zx^UBa8J(mnR6wEgz^}o8;)M*Y(@l_!Kfv)}4+NuM zaPXE50z)r)9=D=SR|RIqfQ^j}Hu!fzMeQBo+@PZk1G8hOw|vBTvkx`HM)Xe9q3xao z@`p0`NO!2904FHSLA6E@Y-O6zH$DQzvq@aHsz}}<(!v(Z_+EodX%R&NZW75g+nENo zV0020rxE^;7d!067AN>6*+&YLp$9uH6F-=In`XC{Cn%+o|5)b&boEPr02w@|P*oGm QmjD0&07*qoM6N<$g78X0Q~&?~ literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/java.png b/images/file-manager-icons/java.png new file mode 100644 index 0000000000000000000000000000000000000000..b7bfcd15fb2f7ce658185bd7ef4729815e2f18b9 GIT binary patch literal 633 zcmV-<0*3vGP)DAD_Iw@kR+3LLZX?3 zyhGkEvUzKYKpu0v_u>?yY~y}#nAbh$p6}dm6adQqK)FzXa=E-qP)ntfS|}9Md_I4Y z%jHh8*{qt$WYlyzt)^0`-M<7XmC7CwTlIP!6`0meW$j(o%*9*fiupyDJZx7&n@&K>z*>QCDhTzTp zTlnzwp?s_A3C!nn*-|JJ`k^?T&hB6^z;e07X0ws&YPAxuvwwlMjasdSU@%xy91e#I zzZYAh^udB=a16G~?^>-EC_Ew4q~Q1a4;7oucH0!-LK+*Y)he3JCK`a7P}Mc?vlj7AM;VkzMEhOwnj`hl1MBj6s4Nlz_+^kH@of;eX>V_G&2` Tt35or00000NkvXXu0mjf&s-qj literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/linux.png b/images/file-manager-icons/linux.png new file mode 100644 index 0000000000000000000000000000000000000000..52699bfee0ce434356c6a9576f32fb6633b01866 GIT binary patch literal 668 zcmV;N0%QG&P)Q{U6)pC|tRy7$(5JQ<@7eB8yk=XcNf-aBIe#;8c_B$^=N z{-Iq&o3%O}V4~G($=zcP(LI|+6dq{?rby~MXwJQ*=!bOvl%?k zYY;jP^@M_k03MHL+-9?_3W5MN=moFW3xmPHU=-4Bw;62MrIhg_lwHEsv)V9U4x>+9cG2kIz8fWo`WyMMfz zdg-)p!<(hFR{VYSDJHEJn09O@#)%q0l?GUg9eS2~vKPUtd+=ak5lWLd-jI=;cjEf# zt$1;~?G!t@s+VLwL=P+Ks;E z!Jkh#NeohG;&02OFD7^EYklCE>?a@fNhGaV ftv%qM$TQzJ6;XjO8erVL00000NkvXXu0mjfw}q7O literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/padlock-disabled.png b/images/file-manager-icons/padlock-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..88c5049320c7b0242f2390419171021e07d7eafc GIT binary patch literal 447 zcmV;w0YLtVP)QbB>9Q6mdh=Y@$gF^8ibo2+*(a9wl{R7T*YZk$floXnTe0c7&Da9{z@WA1| zk9+QU_r1sKx@HZ0-`~@9{ixMy?HGn3fsf$Gah!)Hhc^Nw4-rlwU|E(ei@2`KEX%r; zBMCEsDZ3vPoqK@j9&7#=H%awQx*&s#%$LWNGd-5&IMy=%4t6gxy1 zb-Udd1-Hn-0Xw#BznZ2wWS?;lKF?;e^{T2iNx*3p)u&+cF}vUIrwCzD6pZ>MK}8#y zrZH;x8`S85fwh9kKCR?=z9Gx<`FK3e=kvL^48%G~gsDpc>>rTef>z=^4)*&HcjN5(+PxVDWD1QE07DhHckHt|07uKN%^e+|B2xj p3qb&?^b|jda7*fBGI@CuU;wVMnMuRnJ_i5*002ovPDHLkV1iwB!W;kq literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/padlock.png b/images/file-manager-icons/padlock.png new file mode 100644 index 0000000000000000000000000000000000000000..817a93261ecc9a74e79ea4e96046cbff0edfc64e GIT binary patch literal 752 zcmVa1)h)ANM2wps>c!(&1xdsGJxo8AIP*C(B{(~IFvmSHOMD$TN#=eeQJHU<{8cyXBd+ z^>qZ2zt)Y!#bhRTR!{dl|G2p1et7?GI?DJ{-|B!%#uAowFx{xvQRpo`GjwB0(eyCF^;mh*!UC(p-IJxh4Yjy4$ z-@|$9J1#fpAkrMZ7r{{FC1Pd-pQ>E$R4u5XBgK@naJ@g5M=BxG*AjaV)NI~`ndIDz zK`|n7urrU-vBE&?jEV_1Kgl-k<*LS@nTd}T!A5crJ;%Y7QGgp1DM*JwxCaQz-%wdx zs0pd*=y)8=4iRYv2z{3bZSbf`j_dH7YiKoB;cWkedsu^DY6Orzn3jN&7=cKg0(=wF zEm67(8SDX}4aQY4p%H;DZe*dDqg3@60d2TDUm-mUoW>gZ0g)sX?FLOrG1JhB<4}7} zlHV-^&NjH3pdS-Q>W&YoaCFz9d$?kl&<4&SI9MgWpGj6Bc|pPcf&K&OLDoEQp%)Oe zwyCKl$_cU(kV=c9O;%_zX+uF|Mk+G!AzC}XOOgE*RqYin^$x@Y6g_(cl;l5XTkz|L iq~2D&cDVajfB^vH_9@Zn)Y`8A0000~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27 z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj= z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5 z0#sE+JRUD8iT9*fz{)_^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p-uiS@?KNj zk-Go8G$hH6g002ovPDHLkV1hVj1#|!a literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/php.png b/images/file-manager-icons/php.png new file mode 100644 index 0000000000000000000000000000000000000000..7868a25945cd5e5cb7daaca9591927511ca65c0f GIT binary patch literal 538 zcmV+#0_FXQP)vYep8SaFV10Q$h+;hIUPX_=v5b}%>Tm<(&j1&5;I!55C)oN0s(P%ZB zP3Q#ahfpXKWF@S?jm4U#fv)QovMhrriclyNs6-G12#3R##4PSZ0VY(dRWJ;Lwuq{# zAW0Gwi$yA^R4RZ!;W+L`f&%x{=D^VK#BBWL4Ys{;*!A7Q;!=dN<&D8*GzGaF4`hV4 zDbY0{NrMX>ZqF=0((gR5-zL$kC*b)!fwu{Euru|XrG<$^n#@)7i_>rCmRxnDq>$Y%gJaCkRd|tE*a2x05Pe!I^e13o69#&RQZ36s0 zB=O|K2Yi(jsMqThn}9t?f5E-)L^naZ+db$&%M$!bCdm=jv7?t_lB?3&%Ltq(>ESw? c;MI421LCcoDG!2@;{X5v07*qoM6N<$f`UZt7XSbN literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/picture.png b/images/file-manager-icons/picture.png new file mode 100644 index 0000000000000000000000000000000000000000..4a158fef7e0da8fd19525f574f2c4966443866cf GIT binary patch literal 606 zcmV-k0-^nhP)Q2rnAt>LM%-F zK|rtwgcU)}7x~z1Hrcs5bH*ZO$!>xO8K#?==bZPQ_ecnV>#P`H`QzGaRhd62G_&rC zTLU$c7_x*nFP_dW#Q+*);mMHE?j)HexK784D4x9l_tfpz2$@1y}9rkF+ zI+J5NMWeZyObc!d+rUc=>D+uOdAOg#%+Ej6h+wn5^xPmVVH*Eu446Y0A_@ zo$rlds-+sL10DbHU2HvUSp%6 z*n}iP63IK?dpo;h@sj9~pcxo;VVTc-XLiP@DgefqE#NE=@oyUd-&HjLpsLIuSFXV-EMck)oQ(A`s%*^&wf0(rNiNHsU%=0Rw;WC z(kbc37l6fo`-0uR!pYkYv8U^3?nsh^@pw!K0TH3uYyx1_2>|JbXPmfskJ|1YAw9w! z9`N)1^Aesr;y5Nr5-ODn)oOL|CGi}f9!&iVwpK$khlIX10X$H6^A_stBJqvLhU$?V`QXqKme*s~gVDJ4A;LTs_e15jhc1;By a82kqHEPVYFAD2!500006nP)PbXFR5;6x zQ`<|^Q5@e>|3Fq06ckj13SKAzrBX7=2LmNa=VjAGbC_kBmo!b(h0(lh&dtlb&FNfD zmuquN(K1t)x?D|-M01+g{cLIqvEiq)K|Q2K51*IA`CQKDe7`gRw4E?o66yPi8&Nn? z6l%~H1nUQ%T@&i^1O5KKw~aW)k2+%HG368DWXx)cVb)1u?vucz;=oXT3q3jhU%Im| z1?(s=#*a)g@)(;l>H@5fX<;>n14d_9M|`nnP-6AN3z#%q4DzF(Nk5nWM_|14<{lEc zYPuy4KilYl*ag-mA8dVe2Tbuq#03kAEX>O@@Lksg>YW6tl(V+B2dCW}0wgkfx|Qv4 z-D>azy5k)pmaZ6BhrO`cMMsS?2x;x!C{kX=N`E6pB`Ii0bgLj_hNq!8%(hX_#U?!j zKiGk=Hh5$0c^KwfGl^?D=47dOtiAw2KNAm$$b9o7%%}<>OK>*QNXr%9w1k|LfQ{U2 zSbTi2+))I}Pzx-B&9LZXSZvF~o2CeGlzvc4uVc3ME*4%1(7-xD(S|uUCaD1_sK#7S ztY9n_un1WWgXlK28Rs!v7K;_~=D2b`P734*5Qt!^h`~~a5OuM~Hfisl25mar^a_}} zg_v*2Bt^;WEyLcAGWiUsw{`FkNI_Ti5|L(1@j^*TA*!PfgVy)tDpxOv#%F0dOfNa0 zdc|1jYs3&aBQ0Zq#{l)Z8sgGaTq&(WaY+Uil^l#q(oh+BaNO|=WH5X?GktSNWOaL* z*ZNp}GN_(f2a)O)VOE@kDJ~t8MZuVBOvi$ni}tLGC}Zpk**1wJva900hs{igrph=+ z+^OPVd@W&MNyEpqoQ;kge+VO-3U?f3JDTsf%0@_u%bjJIsY%3=wv>=dpyM%#>wcRc z+$m+(U9dwMf67h5I&QPOO-M5_z-8e1J$HL#g&=&d>pz$2H|k=JCX$xdMNxZS(e|#C2>JN4>y}l*tQ*E7zP@R2CCJnkW?xa6bgk%(hgtZ z0=~d?U3i`+Mvi4!&~+WPT1^NX#{u6&QIx+DE(oR{&T5&-ovF?@wGw)P&AtpHZa|G%V*GUUqL@@!d4V$`8=##4)ytY959JG zdc&Kho)&AL70^i z!PEmeeDWCB-UbK(*4JST44^tV2z_J(dn~+vBMJT97_7rzFio=~XczIv?PQ5$v%u~y zu(bteXb5I1h2zCV{Jc2~V{{yzZipgsP6;k264$*#5q?GzCm|CPa9CKqm4b116h3Pu z?+%Cm52plC8|5P0@igf2GV1KkCfk{Zecu=G@VNrf>s%g9c5D%@cfxVb6$nY`1IW=4 zt10QqSps_2JLp0f3I0j0u>#qA;v!+T))KEbCg|mo3q0pG{OR}p0fPds8+K~d>Hq)$ M07*qoM6N<$g1S2e3jhEB literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/script.png b/images/file-manager-icons/script.png new file mode 100644 index 0000000000000000000000000000000000000000..63fe6ceff5bfcedb9670279d4bb8d25807f6ecee GIT binary patch literal 859 zcmV-h1El5>jf6w4x#gTU%_MMNlkNp$oSbvBp&uHw9M;u0-4@=t5BI zP6Hx#-C_{5RMJ z0_P+Xkumexn8%)S+Y)#l(gR;YJP<6#1-=jjK0LONWPdJQIR8uK1HpvVIxBIQ2ztt+ zqoEx_X9S%QGMe=~(k#sebCL-an)%CR%a7YtUOQUgv+G>~?N~XSWhx=? z@$fx}0MB;$`JWcQ-Re{XV~5|{DvU(#*+NF*g)j^qk#b~G9_O!i*y&mZVZ=a3;Go(K z`DkskYn56Nhu+k@1Ke*uY|x zI&k6j$JfNe_a{GH%=n2rZOz$Z8R9V?Pe36hIk}jo+A-`;dt9vyvBu#Xm@veu&@v`| zzt%mwc_$nd0-sMVx2d)b0!MqGxmfCumx7yB#nIUWvA{!HOMfslMyW1iV&nY>zxwyj z8^JfLN|kT z4m^Q1mhO(_r4w@`V?H=YNkOf(i&bHT3Auc3bryK1_{hDSetLoLN{VLB^78ULiNFy^ zkUqqG$fjVkJj5tfWkOn|P5`HVEp5@-mGnc0wvJGHC=+39MC2TWT#i?t*~fNch*he_ zgtS^8dH$(KlW)EF1b4Fzv~?&0IQaNdg;W5&{t&Bmg9&N1-rBBr_;Rg8ekw^mn;@T# zlS{|Rq+-Nlg18i%UY;i|q1NnSwf>I@85#4U4002ovPDHLkV1mEDi4_0< literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/txt.png b/images/file-manager-icons/txt.png new file mode 100644 index 0000000000000000000000000000000000000000..813f712f726c935f9adf8d2f2dd0d7683791ef11 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-%6;pyTSA|c6o&@eC9QG)Hj&ExYL zO&oVL^)+cM^qd@ApywS>pwx0H@RDN}hq;7mU-SKczYQ-hnrr=;iDAQMZQ+*g=YOM= z!QlMQEn7FbaD->uKAYgo_j9)W&$$zS*W9}m(ey0q$&7l-XEWO0Y(9M=SnhLbwy;d>@~SY$Ku*0xPvIOQeV1x7u_z-2-X>_74(yfh7C znXL|3GZ+d2`3re2hs?MK^@R5;6x zlTS!gQ5431_q{u#M2 zg&W%y6a}>qj1Z|7Vu&-DW6d~k-n;jnHsjb-q#u0C^W!_5^C=MlKq<8oNCQ6qS00!X z5eI;XP=g!^f}j{hku}E1zZ?XCjE;`p19k(Rh%^AQQ54xysU+ocx$c#f61Z4HnT#3u~FR(3>BnZniMIF4DouI8Hi4u>cAK%EN)5PO(ip3(% zIgBx+QYirR){Z8QwV$9Z(Mpt=L-Or3#bf-G@66}txq0yc*T(zNTBDT0T8rO^JeNbSI-Tzf5!pBioy4NwAN^?iN#{;fH1Jke4Xa`^fR8m z%h6dq%xX)S?7`zae))(Xst^Scp6B8FejQW?RLTM8@0=vnnntuRGBM2dpo>gbCnTD= z^<;=JuqdSf@O>Z8^XdR?s+KEfhDdB_#ahFj^giCtzT(s8kA$AViyTqaAR;KGaLzUU z<=GqA4bRwpX|IG~*x>pZ!@zLr`XQ`od>m(`;jz|M_*1GDO#$7;n74ppb8=eiqh760 x0yt}J1#p`gw$`o!R{d7zU9~!Un@nJV{4bstt4Au+Up@c;002ovPDHLkV1kWhGjjj{ literal 0 HcmV?d00001 diff --git a/images/file-manager-icons/zip.png b/images/file-manager-icons/zip.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4bbccdf1643f4ff5022fbc59b82546e259317e GIT binary patch literal 386 zcmV-|0e$|7P)_QM!1S$Bhw4w+iRuFWf;tfR6D%SMJrb+tx zC9R6{2>Ou6#juIy6u(I?|;&Owi$sRB4^20apB5xE2 z#B9XekY66S6lzfCL!eEQRgo0LokTA55@Y#%_wN!T@kVtQ;Z| q2@ei1u<|PTcoaN5*vhG>B*NkF=s*{re%h520gDfIGchwUSOWn6J{AW6 literal 0 HcmV?d00001 diff --git a/images/ice-coder.gif b/images/ice-coder.gif new file mode 100644 index 0000000000000000000000000000000000000000..1808ceb17ac301e18b4016808558b19c90e04cca GIT binary patch literal 2236 zcmeH``&ZHl7QnwC8dxc!`09md#`=n^OsB^%LSB4HVh3f+ZOa$a1B1qs@N^NUhc=6bg|@EEY?g zjE)MYrlzK+HF~|?Zg(s$+D#^lPNx?NMK;^~;NXxzFrrXQIN@@+Mx%LT9fMI2?8moYm{Waj8tBnYP;(HO{2f zDilhy*)j`)DwRs9oSdAT8Xq4wo1BM8rQ=d(Z9O(x^il-lV)B$nv)Gl~hN^U#Tj$&Vj( zX0wsY;Q##33!C|0b9(h3p14a>q`yjcs+_9Hwd6=j7R85@3fMg8Pge`HHxxU1KS zKwRp}jFly=rCT`Uhd;HOwEs>QS2td2$`(t|HB0y&+CNr5*(%ODLa%*u2^LfLZU*e` zwp--dD?^f<-Qc^JxC9@!mdU%c18y;|Q!hH!Wbu%sbdZ!97E~=OKtzs8Jre=>A85oE zbV$O%2)>N$&@p=hyyL;1Ws!g4f)N|b0ixg9w6@B^4gn)+<&KEQE(y?xv~=oUK-%83 z8;f&bR0JH)%yz}oFq8yeLOoD>FM|N{q!qu1mV)nTl}VwAz}+LcdznzL_^<0BaYj;p z8A*saOpO^}hQ#|;ljwK;h0a|CWJHq))rG$E03;-67*_?WzQ?Jp7&p@)SW3-%h!mYm zII$f;CqPNX=Va7Sf^};D`ZY^sjdh;58dZ}Ep^pY@dCtaNbzhTnrlCDr*$CY9WxyNp zDLJqfypB*u4O%pXQI?AX^Iitv-A@pOzJ2tUFwFi_j}h!#5r8POoqEEII!UN;!Srgd zFig41MICh}3zm@y1h$qONA7kbp&=;+Yk=9Xrr;lI$amc%na`RLl=xRfgiqki-(8KJ zS%g}h+g0L1$&bdDcesj0n<*-f+A_%FTNe!3 zOzdUR8|*2het*bq9f9u_)l^b`;A+<^NX3Q+4Ow-x@D3!T;OJ#@c1Lc>EArXR z1GCvtcPkqNsC`Q-HpAB6ka)wx54Z+EJo4pC#f@!xtB*%l+IeE)hLablA*lxwYf=m~ zkkpp=M%O7hvmwGnJdqz>`2)i(xwI?#h%PX3aQior)Xw`cIHt@BVmTmVy!a_?)iHQoU`tWedN9Vl@tFS}V)HV012tnc0Qdu2 zx1!?V!AFYR{E@3r;yicHBpBsR46yOxCa;d8fjCX*%L05!YVno{EL_08T^;VF{x0JX ziFPfxfbQ|a26ZRT;mhggfUl0ySs!D6{XRQBHR~AMZ(UBk3$pK0>9YruF`4wQ3<)=i z852a>AKn46xLuIyyw|G4>wA3U={`70P~=p=?$?ID6(oiLg;nqN6h(V|ol%cGFmew! zw8Q(6J#oUDZz*4y%sk_30K6^=t41QQu-1hnkND=njP}SNg#VrG+IwY}{%lF)uvAUR zQxUGwPodXh^H8-Qw6cu}$?(sIW>S-C_R>99H1;A+_wgPM8(}flFK%_Q=;`RR`0j}3 zb?!*Wp|F;V0KF1a)+Zl5mwfZHX%C1;4)DvZj29^>Y-roGpxmGSq9~b40D$fP0caxI A{r~^~ literal 0 HcmV?d00001 diff --git a/images/images.png b/images/images.png new file mode 100644 index 0000000000000000000000000000000000000000..b0a5c764748e7384cf1ae9c4259abbd04215386c GIT binary patch literal 1533 zcmV`&02eMGBp@6TVJkpv$Hs~6S$eCkD&E%*tl3C`0h(HK)?IQJ=bUE3|2_iw)Q;NHD+ z7_338AAkM*`yYOqUYROoh2mN%V~o-gs75BOI3RKBjL}LerJ@V~Lr(}Gr4Z4Pz`D@+ zSl9LJ#nHU3AAEEXhDD^6m*x5!8*3XAtF4gSAiC9BD-A3qt(L{rybWs7h-;n1Ef!>0fbdFaXYrXGVU$u3v^_TP^3jZ>`hv5=>$VI8tzp&KQ7E1r8WiS*?Ikl&;8aQDlX4qcYDk zOEnvg8G!c2q|9VCp(z4yCXs?pg${+QPGm}gh0s^a3~8j;^K=TsePV{m=uO7a zb76$iLTlj+Y7)*$j2#8!g&B?VaXy-w!ayUWKR)PzBa#-FmJrj8D1}cxUoJqTE=9-B zm^O@2D1jG=vYZbsUaW3J3xT^lVE z=7zCdBsBLvfW#VgNaQ6zRU$Fypm7NBDzml(9-bi@8IxFvp9YL9V+0N!A%GR!N`~o) zAPFU%yFh{qz(t&rIfkD>?E*wFPD4UEQ<)oBj-HT^sRHU0tYc^zqtOl~$wOiRIua?( zj*eopV0YN6AT_utIg*uP;%tc`kU3-sni(p~K#8PBW;EBJ7M2rv5_^e3m_Bxg&!6w^ z?>yPr-hKA;;BfEZZ-2gb>w}L!{FH=sMrb6uI63)y>v5Q0-FWNT+KuaDl+c(~vu8r5$$J5EE_TAop`z-Yv(<|%iS90hG@R_sL zgcJ{tUhM5Z+u7UQ-#wTe&VA>*I`}5GO*@R^bT%+op+$9k%$itL^~u)a$<|Y{9W9^` z)C4aB$Kf8+>3BRT=@^e;an#Dhnx)Cu!%_|7B^F7?HSvJ1wiHB#iS?xn%U}aC8 z&+v6jqN)RIkg-O|O3^mMpNf5>l!NlXKiYpJ*c<}#OrZ~b^w@0he(>SN!Qp(dB=Mdx zEe_r{sE38VAGQT(4S_XjTnK#G_aqNcsONpRL^OoPbkP$e6o{=1k9v_Q+T372^R}ug zY(Pq%QULackMF1+Z49SM$r2F-=7_B&o=QZ4_k3kf*iH!sYh@C&2~5e{%o+-Me?t4xYl`tCEB#$Wm7#8@6QlSC17Blq022 j9U8x*UiZ(z{{+^h`?4Ifj~e} zRD|_B&p&}cm&?@?3BFGZ}D+GIBQ)#D{W!Ou7)5;D{fpM&XTyVSHrMjkDGSc;wt*4X*aD!X3uv|5;)HD zLY_g?T4yg0&Imk@VK#~)EBbs4&78a;;23t%JjL^zdT{1k*Yoo3NfbfOcTb(v@q!={ z1kS-~vji+b-~?HJ5Rgu1H8EdJ%+U-j3ZldAKvCpe*CYdRT4ZL}J#4dKD1sKXjpZ9g z5yVQ76iJdS%itL9=P3VmN_l&nhG?ggB<%J}eLmXlCMgOh2o$x6qEJK3T`<3>bu7@d zyQtM;wITx$a8f5Q3{%!MskY1@2wLY~7)5(RfPx6rhB`?nMNy~kdO4QkIX+j%yC_#Z zwZQm8asL2#6*fzf6oMjkL-Qk$P&+i=KrV`caCy*2(~Q5M1Hw=JD5xzyKXXx=$4$HI z$wdStr-1QJhU*;#~qkAO_iG!N_-Lj|ykBpCG z$&sfMf8UgBLUdbGwpLTgef{ zoZ)=jTg4aFC^Y(V-v^e+9+yG>bb0cg=I5$gL5if*oc2z2izawU5^KtS&%>%WXb+2|OCaRXIKphs+u2-i>>(bKKq&`ejS4LTX z>eZH&-pjfY|A46Q2%?*kX}sQg@)!11oo&Xe`)J_tywt zzfT&Qv`xN3DKusV>VOD8VzNtzNZ6HTB z8aL?DdRwmLyxkk5JFAe!)}HyLr_I=OUu6n1wtL&7A9}s11;>|cw`_e#mQ38~l1gCD EzgxF%k^lez literal 0 HcmV?d00001 diff --git a/images/nav-close.gif b/images/nav-close.gif new file mode 100644 index 0000000000000000000000000000000000000000..efdb0bc0d6edfdd02df9882ec3b66e07d6b07856 GIT binary patch literal 56 zcmZ?wbhEHb<4 literal 0 HcmV?d00001 diff --git a/images/nav-new.png b/images/nav-new.png new file mode 100644 index 0000000000000000000000000000000000000000..affc5b945317596e40c2081f9c28bb9bb1b5948e GIT binary patch literal 480 zcmV<60U!Q}P)U zWBiS`d!4?|m^qOPU5*LE^jU2d+5+cPg_y2$2(rE?LzicSF{V#$kY;24qh~I6Yq~bi z5qSn?CWco(HNNbAU|sR?>;IiB>^u+CGs=E5E}KzaY$I@}hKKV92Oq~Lc4mgpj0~(S z5W9ba+`!84`IqpoFW*>yUi_rLo$2FWfwgac@xB)Pa*Koc$9qPGzyBB*{{CTL`1Kd4 z8bp6#;Qe}+jp5JN|IdC%&Hy`U`pgMjCLDWCnD89bWncrE&ImM~2`KgNKTyvfhKD~? z-|c$q@0^xhdjag}%=Ch9r$1N(d}rYQ!|)4e>K~w6ego;>zrnU0{pi#LQVded0`oKr z^KU-J-@h0c{sR^LXM_X?Bary}mx1N~Z$XS;2Kwa>wf06?fe=psS&eJdg+IPMU2rvMl W?wqX)zdTp~00005HQlMPkoI(U$ zCiar76fEa0Sy7ZT`|OICs7X4Us5*F0EFlOVZY1UZyU6C!g5ZYnpQ_f6wwq`wKjSI(_~Gx8SAZA7+dj&;v)*HljJV c;zxi100Qioy^wH|m;e9(07*qoM6N<$f@S>i;{X5v literal 0 HcmV?d00001 diff --git a/index.php b/index.php new file mode 100644 index 0000000..3267d0f --- /dev/null +++ b/index.php @@ -0,0 +1,128 @@ + + + +404 Not Found + +

    Not Found

    +

    The requested URL was not found on this server.

    +
    +
    Apache/2.2.3 (CentOS) Server at www.mattpass.com Port 80
    + +alert(\'Code Mirror '.$cMLatestVer.' now released\n\nPlease upgrade\');'; + } +} +?> + + + + +ICE Coder - <?php echo $versionNo;?> + + + + + + +
    +
    + +
    +
    + + + +
    + + + +
    + +
    +
    +
    '; + } + ?>
    +
    +
    +
    +
    +
    Find
    + +
    's
    + + + + + + +
    +
    +
    +
    +
    Go to Line + +
    + +
    + + + + + + \ No newline at end of file diff --git a/lib/coder.css b/lib/coder.css new file mode 100644 index 0000000..eca76e4 --- /dev/null +++ b/lib/coder.css @@ -0,0 +1,95 @@ +/* First, reset everything to a standard */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + font-family: arial, verdana, helvetica, sans-serif; + border: 0px; + margin: 0px; + padding: 0px; + outline: 0px; + font-size: 12px; + vertical-align: top; +} + +body {overflow: hidden} + +.blackMask {position: fixed; display: table; width: 100%; height: 100%; top: 0px; left: 0px; visibility: hidden; background-color: rgba(0,0,0,0.8); text-align: center; z-index: 100} +.blackMask .popupVCenter {#position: absolute; display: table-cell; #top: 50%; vertical-align: middle; text-align: center} +.popupVCenter .popup {#position: relative; #top: -50%; text-align: center} + +.header {position: absolute; display: inline-block; width: 100%; height: 40px; background-color: #ffffff; text-align: right; z-index: 2} +.header .plugins {position: absolute; display: inline-block; left: 27px; top: 3px} +.header .plugins img {position: relative; display: inline-block; margin-right: 15px} +.header .version {position: relative; display: inline-block; margin-top: 25px; font-size: 10px; color: #bbbbbb} +.header .logo {position: relative; margin: 5px 10px 0px 5px} + +.files {position: absolute; display: inline-block; height: 100%; width: 15px; background-color: #e0e0e0; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1; + -webkit-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4); + -moz-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4); + box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4); + -webkit-transition: width 0.5s ease-in-out; + -moz-transition: width 0.5s ease-in-out; + -o-transition: width 0.5s ease-in-out; + -ms-transition: width 0.5s ease-in-out; + transition: width 0.5s ease-in-out; +} +.files .account {display: inline-block; height: 50px; width: 250px; margin-top: 40px; background-color: #888888} +.files .frame {display: inline-block; width: 250px} +.files .upload {display: inline-block; height: 40px; width: 250px; background-color: #888888} +.files .upload img {margin: 8px 0px 0px 15px} + +.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px; background-color: #fbfbfb; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + -ms-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} +.editor .tabsBar {display: inline-block; height: 21px; width: 2400px; margin-top: 40px; padding-left: 41px; border-bottom: solid 1px #888888; background-color: #eeeeee; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + -ms-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} +.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 4px 8px 2px 8px; font-size: 10px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; color: #ffffff; cursor: pointer} +.tabsBar .tab img {margin: 1px 0px 0px 5px} +.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 5px 5px 1px 5px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; cursor: pointer; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + -ms-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; +} +.editor .findBar {display: inline-block; height: 28px; width: 2400px; background-color: #eeeeee} +.findBar .findReplace {position: absolute; z-index: 1} +.findReplace select {position: relative; font-size: 10px; margin: 8px 2px 0px 2px; top: -2px;} +.findReplace .findText {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 2px; margin-left: 43px} +.findReplace .find {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px} +.findReplace .findTextPlural {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 0px} +.findReplace .replaceText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px} +.findReplace .replace {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px} +.findReplace .targetText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px} +.findReplace .submit {position: relative; top: -2px; height: 17px; border: 1px solid #bbbbbb; background-color: #f8f8f8; font-size: 10px; cursor: pointer} +.findReplace .results {position: relative; display: inline-block; width: 200px; height: 20px; font-size: 10px; margin: 8px 0px 0px 20px} +.findBar .goLine {position: fixed; display: inline-block; width: 100px; right: -10px; top: 70px; height: 21px; font-size: 10px; z-index: 1} +.goLine .goToLine {width: 25px; height: 16px; border: 0; font-size: 10px; margin: -3px 0px 0px 3px} +.editor .code {position: relative; display: inline-block; top: 28px; width: 600px; height: 600px; visibility: hidden} + +.footer {position: fixed; display: inline-block; width: 100%; height: 30px; bottom: 0px; background-color: rgba(0,0,0,0.7); left: 0px; z-index: 2} +.footer .nesting {display: inline-block; padding: 5px 8px; margin: 4px 0px 0px 15px; font-weight: bold; font-size: 10px; color: #ffffff; background-color: #00bb00} +.footer .nestLoc {position: absolute; display: inline-block; width: 120px; padding: 5px 0px 0px 8px; margin-top: 3px; left: 112px; font-weight: bold; font-size: 12px; color: #ffffff; text-align: right} +.footer .nestDisplay {position: absolute; display: inline-block; padding: 5px 0px 0px 8px; margin-top: 3px; left: 255px; font-size: 12px; color: #ffffff; text-align: right} +.footer .charDisplay {position: absolute; display: inline-block; padding: 5px 0px 0px 8px; margin-top: 3px; left: 100%; font-weight: bold; font-size: 12px; color: #ffffff; text-align: right; width: 200px; text-align: right; margin-left: -220px} + +.textbox { + -webkit-box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4); + -moz-box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4); + box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4); +} \ No newline at end of file diff --git a/lib/coder.js b/lib/coder.js new file mode 100644 index 0000000..7d60723 --- /dev/null +++ b/lib/coder.js @@ -0,0 +1,844 @@ +// ICE coder by Matt Pass +// Free to use it for your own purposes, commercial or not, just let me know of any cool uses or customisations. :) +// No warranty or liability accepted for anything, all responsibility of use is your own. +// Latest version: https://github.com/mattpass/ICEcoder +// Twitter: @mattpass + +var ICEcoder = { + // Define settings + filesW: 15, // Initial width of the files pane + minFilesW: 15, // Min width of the files pane + maxFilesW: 250, // Max width of the files pane + selectedTab: 0, // The tab that's currently selected + changedContent: [], // Binary array to indicate which tabs have changed + ctrlKeyDown: false, // Indicates if CTRL keydown + delKeyDown: false, // Indicates if DEL keydown + canSwitchTabs: true, // Stops switching of tabs when trying to close + openFiles: [], // Array of open file URLs + selectedFiles: [], // Array of selected files + findMode: false, // States if we're in find/replace mode + lockedNav: false, // Nav is locked or not + + // Don't consider these tags as part of nesting as they're singles, JS or PHP code blocks + tagNestExceptions: ["!DOCTYPE","meta","link","img","br","hr","input","script","?"], + + // On load, set aliases, set the layout and get the nest location + init: function() { + var aliasArray = ["header","files","account","filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","charDisplay"]; + ICEcoder.tD = top.document; + + // Create our ID aliases + for (var i=0;i-1) {codeTemp = (codeTemp.replace(/ /g," "))} + + // Remove any existing tabs + while (codeTemp.indexOf(" ")>-1) {codeTemp = (codeTemp.replace(/ /g,""))} + + // Redo the tabbing according to nest position + lastBreakPos = 0; + while (codeTemp.indexOf('\n',lastBreakPos)")[0].split("\n")[0]; + if (tagStart=="script"||tagStart=="?") {ICEcoder.codeBlock=true} + if (tagStart!="") {ICEcoder.tagStart = tagStart} + }; + + // If we find a > tag and we're within a tag or codeblock + if(nestCheck.charAt(i)==">" && (openTag||ICEcoder.codeBlock)) { + + // Get the tag name + tagString=nestCheck.substr(0,i); + tagString=tagString.substr(tagString.lastIndexOf('<')+1,tagString.length); + tagString=tagString.split(" ")[0]; + ICEcoder.tagString = tagString; + canDoTheEndTag=true; + + // Check it's not on our list of exceptions + for (var j=0;j'; + top.document.getElementById('tab'+(top.ICEcoder.openFiles.length)).style.display = "inline-block"; + top.document.getElementById('tab'+(top.ICEcoder.openFiles.length)).innerHTML = top.ICEcoder.openFiles[top.ICEcoder.openFiles.length-1] + " " + closeTabLink; + + // Highlight it and state it's selected + top.ICEcoder.redoTabHighlight(top.ICEcoder.openFiles.length); + top.ICEcoder.selectedTab=top.ICEcoder.openFiles.length; + + // Add a new value ready to indicate if this content has been changed + top.ICEcoder.changedContent.push(0); + }, + + // Indicate if the nesting structure of the code is OK + updateNestingIndicator: function () { + var cM, fileName; + cM = ICEcoder.getcMInstance(); + + fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1]; + ICEcoder.caretPos=cM.getValue().length; + ICEcoder.getNestLocation(); + // Nesting is OK if at the end of the file we have no nests left, or it's a JS or CSS file + if (ICEcoder.htmlTagArray.length==0||fileName.indexOf(".js")>0||fileName.indexOf(".css")>0) { + ICEcoder.nestValid.style.backgroundColor="#00bb00"; + ICEcoder.nestValid.innerHTML = "Nesting OK"; + } else { + ICEcoder.nestValid.style.backgroundColor="#ff0000"; + ICEcoder.nestValid.innerHTML = "Nesting Broken"; + } + }, + + // Get the caret position on demand + getCaretPosition: function() { + var cM, content, line, char, charPos, charCount; + cM = ICEcoder.getcMInstance(); + content = cM.getValue(); + + line = cM.getCursor().line; + char = cM.getCursor().ch; + charPos = 0; + for (var i=0;icaretChunk.lastIndexOf("")&&caretLocType=="Unknown") {caretLocType = "JavaScript"}; + if (caretChunk.lastIndexOf("caretChunk.lastIndexOf("?>")&&caretLocType=="Unknown") {caretLocType = "PHP"}; + if (caretChunk.lastIndexOf("<")>caretChunk.lastIndexOf(">")&&caretLocType=="Unknown") {caretLocType = "HTML"}; + if (caretLocType=="Unknown") {caretLocType = "Content"}; + ICEcoder.caretLocType = caretLocType; + + // If we're in a JS or PHP code block, add that to the nest display + if (caretLocType=="JavaScript"||caretLocType=="PHP") { + ICEcoder.nestDisplay.innerHTML += " > " + caretLocType; + } + }, + + // Alter array indicating which files have changed + redoChangedContent: function(evt) { + var key; + + key = evt.keyCode ? evt.keyCode : evt.which ? evt.which : evt.charCode; + // Exclude a few keys such as Escape... + if (top.ICEcoder.ctrlKeyDown==false && key!=27 && key!=20 && (key<16||key>19) && (key<37||key>40) && (key!=144||key!=145) && (key!=44||key!=45) && (key<33||key>36) && (key!=91||key!=92) && (key<112||key>123)) { + ICEcoder.changedContent[ICEcoder.selectedTab-1] = 1; + ICEcoder.redoTabHighlight(ICEcoder.selectedTab); + } + }, + + // Close the tab upon request + closeTab: function(closeTabNum) { + var cM, okToRemove; + cM = ICEcoder.getcMInstance(); + + okToRemove = true; + if (ICEcoder.changedContent[closeTabNum-1]==1) { + okToRemove = confirm('You have made changes.\n\nAre you sure you want to close without saving?'); + } + + if (okToRemove) { + // recursively copy over all tab data from the tab to the right, if there is one + for (var i=closeTabNum;i0 ? ICEcoder.selectedTab-=1 : ICEcoder.selectedTab = 0; + if (ICEcoder.openFiles.length>0 && ICEcoder.selectedTab==0) {ICEcoder.selectedTab=1}; + + // clear & hide the code textarea if we have no tabs open + if (ICEcoder.openFiles.length==0) { + // clear the value & HTML of the code textarea and also hide it + cM = ICEcoder.getcMInstance(); + cM.setValue(''); + cM.clearHistory(); + ICEcoder.tD.getElementById('content').style.visibility = "hidden"; + } else { + // Switch the mode & the tab + ICEcoder.switchMode(); + ICEcoder.switchTab(ICEcoder.selectedTab); + } + + // Highlight the selected tab after splicing the change state out of the array + top.ICEcoder.changedContent.splice(closeTabNum-1,1); + top.parent.ICEcoder.redoTabHighlight(ICEcoder.selectedTab); + } + // Lastly, stop it from trying to also switch tab + top.ICEcoder.canSwitchTabs=false; + }, + + // Setup the file manager + fileManager: function() { + ICEcoder.filesFrame = top.document.getElementById('filesFrame'); + if (!ICEcoder.filesFrame.contentWindow.document.getElementsByTagName) {return;}; + + var aMenus = ICEcoder.filesFrame.contentWindow.document.getElementsByTagName("LI"); + for (var i=0; i -1) { + var submenu=aMenus[i].childNodes; + for (var j=0; j -1) ? "open" : "closed"; + } + if (submenu[j].tagName == "UL") + submenu[j].style.display = (mclass.indexOf("open") > -1) ? "block" : "none"; + } + } + } + return false; + }, + + // Note which files or foldets we are over on mouseover/mouseout + overFileFolder: function(type, link) { + ICEcoder.thisFileFolderType=type; + ICEcoder.thisFileFolderLink=link; + }, + + // Select file or folder on demand + selectFileFolder: function() { + var resetFile, shortURL, foundSelectedFile, foundShortURL, foundFile, resetFile; + + // If we've clicked somewhere other than a file/folder + if (top.ICEcoder.thisFileFolderLink=="") { + if (!top.ICEcoder.ctrlKeyDown) { + // Deselect all files + for (var i=0;i<=top.ICEcoder.selectedFiles.length;i++) { + if (top.ICEcoder.selectedFiles[i]) { + resetFile = top.ICEcoder.filesFrame.contentWindow.document.getElementById(top.ICEcoder.selectedFiles[i]); + resetFile.style.backgroundColor="#dddddd"; + resetFile.style.color="#000000"; + } + } + // Set our arrray to contain 0 items + top.ICEcoder.selectedFiles.length = 0; + } + } else { + // We clicked a file/folder. Work out a shortened URL for the file, with pipes instead of slashes + shortURL = top.ICEcoder.thisFileFolderLink.substr((top.ICEcoder.thisFileFolderLink.indexOf(shortURLStarts)+top.shortURLStarts.length),top.ICEcoder.thisFileFolderLink.length).replace(/\//g,"|"); + + // If we have the CTRL key down + if (top.ICEcoder.ctrlKeyDown) { + foundSelectedFile=false; + // Reset all files to not be highlighted + for (i=0;i<=top.ICEcoder.selectedFiles.length;i++) { + if (top.ICEcoder.selectedFiles[i]==shortURL) { + resetFile = ICEcoder.filesFrame.contentWindow.document.getElementById(top.ICEcoder.selectedFiles[i]); + resetFile.style.backgroundColor="#dddddd"; + resetFile.style.color="#000000"; + top.ICEcoder.selectedFiles.splice(i); + foundSelectedFile=true; + } + } + if (!foundSelectedFile) { + foundFile = ICEcoder.filesFrame.contentWindow.document.getElementById(shortURL); + foundFile.style.backgroundColor="#888888"; + foundFile.style.color="#f8f8f8"; + top.ICEcoder.selectedFiles.push(shortURL); + } + // We are single clicking + } else { + if (top.ICEcoder.selectedFiles.length==1 && shortURL==top.ICEcoder.selectedFiles[0]) { + // Go into edit mode... + if (top.ICEcoder.slowClick) {top.ICEcoder.renameFile()} + } else { + // First deselect all files + for (i=0;i'; + top.document.getElementById('tab'+(i+1)).innerHTML = top.ICEcoder.openFiles[i] + " " + closeTabLink; + } + } + ICEcoder.filesFrame.contentWindow.frames['fileControl'].location.href = "lib/file-control.php?action=rename&file="+renamedFile+"&oldFileName="+top.ICEcoder.thisFileFolderLink; + } + }, + + // Delete a file on demand + deleteFile: function() { + var delFiles, selectedFilesList; + + delFiles = confirm('Delete: '+top.ICEcoder.selectedFiles+'?'); + + // Upon supply a new name, rename tabs and update filename on server + if (delFiles) { + selectedFilesList = ""; + for (var i=0;i0) { + cM = ICEcoder.getcMInstance(); + content = cM.getValue().toLowerCase(); + + // Find & replace the next instance? + if (document.findAndReplace.connector.value=="and" && cM.getSelection()==find) { + cM.replaceSelection(document.getElementById('replace').value); + } + + if (!top.ICEcoder.findMode||parent.parent.document.getElementById('find').value!=ICEcoder.lastsearch) { + ICEcoder.results = []; + for (var i=0;i0) { + + // Show results only + if (resultsOnly) { + parent.parent.document.getElementById('results').innerHTML = ICEcoder.results.length + " results"; + + // We need to take action instead + } else { + lineCount=1; + numChars=0; + + for (var i=0;iICEcoder.results.length-1) {ICEcoder.findResult=0}; + parent.parent.document.getElementById('results').innerHTML = "Highlighted result "+(ICEcoder.findResult+1)+" of "+ICEcoder.results.length+" results"; + lineCount=0; + + for (var i=0;i0) { + cM.setOption("mode","javascript"); + } else if (fileName.indexOf('.css')>0) { + cM.setOption("mode","css"); + } else { + cM.setOption("mode","application/x-httpd-php"); + } + }, + + // Lock & unlock the file manager navigation on demand + lockUnlockNav: function() { + var lockIcon; + lockIcon = top.document.getElementById('fmLock'); + ICEcoder.lockedNav ? ICEcoder.lockedNav = false : ICEcoder.lockedNav = true; + ICEcoder.lockedNav ? lockIcon.src="images/file-manager-icons/padlock.png" : lockIcon.src="images/file-manager-icons/padlock-disabled.png"; + }, + + // Determine the CodeMirror instance we're using on demand + getcMInstance: function(newTab) { + var cM; + + if (newTab=="new") { + cM = top.ICEcoder.content.contentWindow['cM'+ICEcoder.openFiles.length]; + } else if (ICEcoder.openFiles.length==0) { + cM = top.ICEcoder.content.contentWindow['cM1']; + } else { + cM = top.ICEcoder.content.contentWindow['cM'+ICEcoder.selectedTab]; + } + return cM; + }, + + // Start running plugin intervals according to given specifics + startPluginIntervals: function(plugURL,plugTarget,plugTimer) { + + // For this window instances + if (plugTarget=="_parent"||plugTarget=="_top"||plugTarget=="_self"||plugTarget=="") { + setInterval('window.location=\''+plugURL+'\'',plugTimer*1000*60); + + // for pluginActions iframe instances + } else if (plugTarget=="pluginActions") { + setInterval('document.getElementById(\'pluginActions\').src=\''+plugURL+'\'',plugTimer*1000*60); + + // for _blank or named target window instances + } else { + setInterval('window.open(\''+plugURL+'\',\''+plugTarget+'\')',plugTimer*1000*60); + } + } +}; \ No newline at end of file diff --git a/lib/editor.css b/lib/editor.css new file mode 100644 index 0000000..853e637 --- /dev/null +++ b/lib/editor.css @@ -0,0 +1,32 @@ +html, body {margin: 0px} + +.cm-s-icecoder {font-size: 12px; color: #888; background: #fcfcfc} +.cm-s-icecoder span.cm-keyword {color: #a0a;font-weight:bold} +.cm-s-icecoder span.cm-atom {color: #219;} +.cm-s-icecoder span.cm-number {color: #0a0;} +.cm-s-icecoder span.cm-def {color: #00f;} +.cm-s-icecoder span.cm-variable {color: #a0a;} +.cm-s-icecoder span.cm-variable-2 {color: #a0a;} +.cm-s-icecoder span.cm-variable-3 {color: #0a0;} +.cm-s-icecoder span.cm-property {color: #0a0;} +.cm-s-icecoder span.cm-operator {color: #0a0;} +.cm-s-icecoder span.cm-comment {color: #bbb;} +.cm-s-icecoder span.cm-string {color: #00c;} +.cm-s-icecoder span.cm-string-2 {color: #f50;} +.cm-s-icecoder span.cm-meta {color: #555;} +.cm-s-icecoder span.cm-error {color: #f00;} +.cm-s-icecoder span.cm-qualifier {color: #555;} +.cm-s-icecoder span.cm-builtin {color: #30a;} +.cm-s-icecoder span.cm-bracket {color: #cc7;} +.cm-s-icecoder span.cm-tag {color: #c00;} +.cm-s-icecoder span.cm-attribute {color: #333;} +.cm-s-icecoder span.cm-header {color: #a0a;} +.cm-s-icecoder span.cm-quote {color: #090;} +.cm-s-icecoder span.cm-hr {color: #999;} +.cm-s-icecoder span.cm-link {color: #00c;} + +.cm-s-icecoder span.CodeMirror-selected {background: #ffff00 !important; color: #000 !important} +.cm-s-icecoder .CodeMirror-gutter {background: #333; border-right: 1px solid #e8e8e8;} +.cm-s-icecoder .CodeMirror-gutter-text {color: #999; width: 35px} +.cm-s-icecoder .CodeMirror-cursor {border-left: 1px solid black !important;} +.cm-s-icecoder .CodeMirror-matchingbracket{border: 1px solid grey; color: black !important;} \ No newline at end of file diff --git a/lib/file-control.php b/lib/file-control.php new file mode 100644 index 0000000..4ba349a --- /dev/null +++ b/lib/file-control.php @@ -0,0 +1,167 @@ + +action="load";'; + + // Determine what to do based on filename + // Everything is opened as text in the editor unless specified otherwise + $fileType="text"; + if (strpos($file,".jpg")>0||strpos($file,".jpeg")>0||strpos($file,".gif")>0||strpos($file,".png")>0) {$fileType="image";}; + + if ($fileType=="text") { + $bannedFile=false; + for ($i=0;$ifileType="text";'; + $loadedFile = file_get_contents($file); + echo ''; + } else { + echo ''; + echo ''; + } + }; + + if ($fileType=="image") { + echo ''; + }; +}; + +// If we're due to rename a file... +if ($_GET['action']=="rename") { + if ($_SESSION['userLevel'] > 0) { + rename($_GET['oldFileName'],$docRoot.$file); + // Reload file manager + echo ''; + } else { + echo ''; + echo ''; + } +} + +// If we're due to delete a file... +if ($_GET['action']=="delete") { + if ($_SESSION['userLevel'] > 0) { + $filesArray = split(";",$file); // May contain more than one file here + for ($i=0;$i<=count($filesArray)-1;$i++) { + if (is_dir($docRoot.$filesArray[$i])) { + rrmdir($docRoot.$filesArray[$i]); + } else { + unlink($docRoot.$filesArray[$i]); + } + } + // Reload file manager + echo ''; + } else { + echo ''; + echo ''; + } +} + +// The function to recursively remove folders & files +function rrmdir($dir) { + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != "." && $object != "..") { + if (filetype($dir."/".$object) == "dir") rrmdir($dir."/".$object); else unlink($dir."/".$object); + } + } + reset($objects); + rmdir($dir); + } +} + +if ($_GET['action']=="save") { + echo ''; + // on the form posting via a reload, save the file + if (isset($_POST['contents'])) { + if ($_SESSION['userLevel'] > 0) { + if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") { + $file = $_POST['newFileName']; + } + $saveFile = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']).$file; + $saveFile = str_replace("//","/",$saveFile); + $fh = fopen($saveFile, 'w') or die("can't open file"); + fwrite($fh, $_POST['contents']); + fclose($fh); + if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") { + // Reload file manager & stop CTRL+s being sticky + echo ''; + } + echo ''; + } else { + echo ''; + echo ''; + } + } +}; +?> + + +
    + + +
    + + + + \ No newline at end of file diff --git a/lib/files.css b/lib/files.css new file mode 100644 index 0000000..cd9f15d --- /dev/null +++ b/lib/files.css @@ -0,0 +1,98 @@ +/* First, reset everything to a standard */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + font-family: arial, verdana, helvetica, sans-serif; + border: 0px; + margin: 0px; + padding: 0px; + outline: 0px; + font-size: 12px; + vertical-align: top; +} + +body {margin: 0px; overflow: auto} + +.fileManager { + margin: 15px 0px 15px 22px; + -webkit-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; +} + +.fileManager span {font-family: helvetica, arial, swiss, verdana;} +.fileManager a {color: #000000; text-decoration: none;} +.fileManager .open {font-style: italic;} +.fileManager .closed {font-style: normal;} +.fileManager .pft-directory {list-style-image: url(../images/file-manager-icons/directory.png);} +.fileManager li {margin-left: 15px;} + +/* Default file */ +.fileManager LI.pft-file { list-style-image: url(../images/file-manager-icons/file.png); cursor: pointer;} + +/* Additional file types */ +.fileManager LI.ext-3gp { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-afp { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-afpa { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-asp { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-aspx { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-avi { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-bat { list-style-image: url(../images/file-manager-icons/application.png); } +.fileManager LI.ext-bmp { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-c { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-cfm { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-cgi { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-com { list-style-image: url(../images/file-manager-icons/application.png); } +.fileManager LI.ext-cpp { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-css { list-style-image: url(../images/file-manager-icons/css.png); } +.fileManager LI.ext-doc { list-style-image: url(../images/file-manager-icons/doc.png); } +.fileManager LI.ext-exe { list-style-image: url(../images/file-manager-icons/application.png); } +.fileManager LI.ext-gif { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-fla { list-style-image: url(../images/file-manager-icons/flash.png); } +.fileManager LI.ext-h { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-htm { list-style-image: url(../images/file-manager-icons/html.png); } +.fileManager LI.ext-html { list-style-image: url(../images/file-manager-icons/html.png); } +.fileManager LI.ext-jar { list-style-image: url(../images/file-manager-icons/java.png); } +.fileManager LI.ext-jpg { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-jpeg { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-js { list-style-image: url(../images/file-manager-icons/script.png); } +.fileManager LI.ext-lasso { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-log { list-style-image: url(../images/file-manager-icons/txt.png); } +.fileManager LI.ext-m4p { list-style-image: url(../images/file-manager-icons/music.png); } +.fileManager LI.ext-mov { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-mp3 { list-style-image: url(../images/file-manager-icons/music.png); } +.fileManager LI.ext-mp4 { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-mpg { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-mpeg { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-ogg { list-style-image: url(../images/file-manager-icons/music.png); } +.fileManager LI.ext-pcx { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-pdf { list-style-image: url(../images/file-manager-icons/pdf.png); } +.fileManager LI.ext-php { list-style-image: url(../images/file-manager-icons/php.png); } +.fileManager LI.ext-png { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-ppt { list-style-image: url(../images/file-manager-icons/ppt.png); } +.fileManager LI.ext-psd { list-style-image: url(../images/file-manager-icons/psd.png); } +.fileManager LI.ext-pl { list-style-image: url(../images/file-manager-icons/script.png); } +.fileManager LI.ext-py { list-style-image: url(../images/file-manager-icons/script.png); } +.fileManager LI.ext-rb { list-style-image: url(../images/file-manager-icons/ruby.png); } +.fileManager LI.ext-rbx { list-style-image: url(../images/file-manager-icons/ruby.png); } +.fileManager LI.ext-rhtml { list-style-image: url(../images/file-manager-icons/ruby.png); } +.fileManager LI.ext-rpm { list-style-image: url(../images/file-manager-icons/linux.png); } +.fileManager LI.ext-ruby { list-style-image: url(../images/file-manager-icons/ruby.png); } +.fileManager LI.ext-sql { list-style-image: url(../images/file-manager-icons/db.png); } +.fileManager LI.ext-swf { list-style-image: url(../images/file-manager-icons/flash.png); } +.fileManager LI.ext-tif { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-tiff { list-style-image: url(../images/file-manager-icons/picture.png); } +.fileManager LI.ext-txt { list-style-image: url(../images/file-manager-icons/txt.png); } +.fileManager LI.ext-vb { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-wav { list-style-image: url(../images/file-manager-icons/music.png); } +.fileManager LI.ext-wmv { list-style-image: url(../images/file-manager-icons/film.png); } +.fileManager LI.ext-xls { list-style-image: url(../images/file-manager-icons/xls.png); } +.fileManager LI.ext-xml { list-style-image: url(../images/file-manager-icons/code.png); } +.fileManager LI.ext-zip { list-style-image: url(../images/file-manager-icons/zip.png); } \ No newline at end of file diff --git a/lib/settings.php b/lib/settings.php new file mode 100644 index 0000000..c29217e --- /dev/null +++ b/lib/settings.php @@ -0,0 +1,37 @@ +-1) {$slashType = "/";} else {$slashType = "\\";}; +$shortURLStarts = explode($slashType,$_SERVER['DOCUMENT_ROOT']); + +// Then clear item at the end if there is one, plus trailing slash +// We end up with the directory name of the server root +if ($shortURLStarts[count($shortURLStarts)-1]!="") {$trimArray=1;} else {$trimArray=2;} +$shortURLStarts = $shortURLStarts[count($shortURLStarts)-$trimArray]; +?> \ No newline at end of file diff --git a/plugins/adminer/adminer-3.3.3-mysql-en.php b/plugins/adminer/adminer-3.3.3-mysql-en.php new file mode 100644 index 0000000..0fdb108 --- /dev/null +++ b/plugins/adminer/adminer-3.3.3-mysql-en.php @@ -0,0 +1,877 @@ + +function toggle(id){var el=document.getElementById(id);el.className=(el.className=='hidden'?'':'hidden');return true;} +function cookie(assign,days){var date=new Date();date.setDate(date.getDate()+days);document.cookie=assign+'; expires='+date;} +function verifyVersion(){cookie('adminer_version=0',1);var script=document.createElement('script');script.src=location.protocol+'//www.adminer.org/version.php';document.body.appendChild(script);} +function selectValue(select){var selected=select.options[select.selectedIndex];return((selected.attributes.value||{}).specified?selected.value:selected.text);} +function trCheck(el){var tr=el.parentNode.parentNode;tr.className=tr.className.replace(/(^|\s)checked(\s|$)/,'$2')+(el.checked?' checked':'');} +function formCheck(el,name){var elems=el.form.elements;for(var i=0;i=0){input.maxLength=input.origMaxLength;}} +function ajax(url,callback,data){var xmlhttp=(window.XMLHttpRequest?new XMLHttpRequest():(window.ActiveXObject?new ActiveXObject('Microsoft.XMLHTTP'):false));if(xmlhttp){xmlhttp.open((data?'POST':'GET'),url);if(data){xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');} +xmlhttp.setRequestHeader('X-Requested-With','XMLHttpRequest');xmlhttp.onreadystatechange=function(){if(xmlhttp.readyState==4){callback(xmlhttp);}};xmlhttp.send(data);} +return xmlhttp;} +function ajaxSetHtml(url){return ajax(url,function(xmlhttp){if(xmlhttp.status){var data=eval('('+xmlhttp.responseText+')');for(var key in data){setHtml(key,data[key]);}}});} +var originalFavicon;function replaceFavicon(href){var favicon=document.getElementById('favicon');if(favicon){favicon.href=href;favicon.parentNode.appendChild(favicon);}} +var ajaxState=0;function ajaxSend(url,data,popState,noscroll){if(!history.pushState){return false;} +var currentState=++ajaxState;onblur=function(){if(!originalFavicon){originalFavicon=(document.getElementById('favicon')||{}).href;} +replaceFavicon(location.pathname+'?file=loader.gif&version=3.3.3');};setHtml('loader','');return ajax(url,function(xmlhttp){if(currentState==ajaxState){var title=xmlhttp.getResponseHeader('X-AJAX-Title');if(title){document.title=decodeURIComponent(title);} +var redirect=xmlhttp.getResponseHeader('X-AJAX-Redirect');if(redirect){return ajaxSend(redirect,'',popState);} +onblur=function(){};if(originalFavicon){replaceFavicon(originalFavicon);} +if(!xmlhttp.status){setHtml('loader','');}else{if(!popState){if(data||url!=location.href){history.pushState(data,'',url);}} +if(!noscroll&&!/&order/.test(url)){scrollTo(0,0);} +setHtml('content',xmlhttp.responseText);var content=document.getElementById('content');var scripts=content.getElementsByTagName('script');var length=scripts.length;for(var i=0;i=allowed){return false;} +var match=/(\d+)(\.\d+)?/.exec(button.name);var x=match[0]+(match[2]?added.substr(match[2].length):added)+'1';var row=button.parentNode.parentNode;var row2=row.cloneNode(true);var tags=row.getElementsByTagName('select');var tags2=row2.getElementsByTagName('select');for(var i=0;idivs[i].offsetTop+top*em);} +if(!lineSet[id]){var line=document.getElementById(divs[i].id.replace(/^....(.+)-\d+$/,'refl$1'));var shift=ev.clientY-y-that.offsetTop;line.style.left=(left+left1)+'em';if(isTop){line.style.top=(line.offsetTop+shift)/em+'em';} +if(divs[i].parentNode!=div2.parentNode){line=line.getElementsByTagName('div')[0];line.style.height=(line.offsetHeight+(isTop?-1:1)*shift)/em+'em';} +lineSet[id]=true;}}} +that.style.left=left+'em';that.style.top=top+'em';}} +function schemaMouseup(ev,db){if(that!==undefined){ev=ev||event;tablePos[that.firstChild.firstChild.firstChild.data]=[(ev.clientY-y)/em,(ev.clientX-x)/em];that=undefined;var s='';for(var key in tablePos){s+='_'+key+':'+Math.round(tablePos[key][0]*10000)/10000+'x'+Math.round(tablePos[key][1]*10000)/10000;} +s=encodeURIComponent(s.substr(1));var link=document.getElementById('schema-link');link.href=link.href.replace(/[^=]+$/,'')+s;cookie('adminer_schema-'+db+'='+s,30);}}$W){unset($Yd[$y][$xc]);if(is_array($W)){$Yd[$y][stripslashes($xc)]=$W;$Yd[]=&$Yd[$y][stripslashes($xc)];}else{$Yd[$y][stripslashes($xc)]=($Tb?$W:stripslashes($W));}}}}}function +bracket_escape($lc,$wa=false){static$kf=array(':'=>':1',']'=>':2','['=>':3');return +strtr($lc,($wa?array_flip($kf):$kf));}function +h($Q){return +htmlspecialchars(str_replace("\0","",$Q),ENT_QUOTES);}function +nbsp($Q){return(trim($Q)!=""?h($Q):" ");}function +nl_br($Q){return +str_replace("\n","
    ",$Q);}function +checkbox($D,$Y,$Fa,$zc="",$od="",$wc=false){static$t=0;$t++;$J="";return($zc!=""?"":$J);}function +optionlist($rd,$we=null,$Bf=false){$J="";foreach($rd +as$xc=>$W){$sd=array($xc=>$W);if(is_array($W)){$J.='';$sd=$W;}foreach($sd +as$y=>$X){$J.=''.h($X);}if(is_array($W)){$J.='';}}return$J;}function +html_select($D,$rd,$Y="",$nd=true){if($nd){return"";}$J="";foreach($rd +as$y=>$X){$J.="";}return$J;}function +confirm($Wa="",$He=false){return" onclick=\"".($He?"eventStop(event); ":"")."return confirm('".'Are you sure?'.($Wa?" (' + $Wa + ')":"")."');\"";}function +print_fieldset($t,$Fc,$Hf=false,$od=""){echo"
    $Fc
    \n";}function +selectSearchPrint($Z,$d,$v){print_fieldset("search",'Search',$Z);foreach($v +as$s=>$u){if($u["type"]=="FULLTEXT"){echo"(".implode(", ",array_map('h',$u["columns"])).") AGAINST"," ",checkbox("boolean[$s]",1,isset($_GET["boolean"][$s]),"BOOL"),"
    \n";}}$s=0;foreach((array)$_GET["where"]as$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){echo"
    ",html_select("where[$s][op]",$this->operators,$X["op"]),"
    \n";$s++;}}echo"
    ",html_select("where[$s][op]",$this->operators,"="),"
    \n","\n";}function +selectOrderPrint($td,$d,$v){print_fieldset("sort",'Sort',$td);$s=0;foreach((array)$_GET["order"]as$y=>$X){if(isset($d[$X])){echo"
    ",checkbox("desc[$s]",1,isset($_GET["desc"][$y]),'descending')."
    \n";$s++;}}echo"
    ","
    \n";echo"\n";}function +selectLimitPrint($z){echo"
    ".'Limit'."
    ";echo"","
    \n";}function +selectLengthPrint($bf){if(isset($bf)){echo"
    ".'Text length'."
    ",'',"
    \n";}}function +selectActionPrint(){echo"
    ".'Action'."
    ","","
    \n";}function +selectCommandPrint(){return!information_schema(DB);}function +selectImportPrint(){return +true;}function +selectEmailPrint($xb,$d){}function +selectColumnsProcess($d,$v){global$p,$ec;$N=array();$r=array();foreach((array)$_GET["columns"]as$y=>$X){if($X["fun"]=="count"||(isset($d[$X["col"]])&&(!$X["fun"]||in_array($X["fun"],$p)||in_array($X["fun"],$ec)))){$N[$y]=apply_sql_function($X["fun"],(isset($d[$X["col"]])?idf_escape($X["col"]):"*"));if(!in_array($X["fun"],$ec)){$r[]=$N[$y];}}}return +array($N,$r);}function +selectSearchProcess($k,$v){global$x;$J=array();foreach($v +as$s=>$u){if($u["type"]=="FULLTEXT"&&$_GET["fulltext"][$s]!=""){$J[]="MATCH (".implode(", ",array_map('idf_escape',$u["columns"])).") AGAINST (".q($_GET["fulltext"][$s]).(isset($_GET["boolean"][$s])?" IN BOOLEAN MODE":"").")";}}foreach((array)$_GET["where"]as$X){if("$X[col]$X[val]"!=""&&in_array($X["op"],$this->operators)){$Sa=" $X[op]";if(ereg('IN$',$X["op"])){$nc=process_length($X["val"]);$Sa.=" (".($nc!=""?$nc:"NULL").")";}elseif(!$X["op"]){$Sa.=$X["val"];}elseif($X["op"]=="LIKE %%"){$Sa=" LIKE ".$this->processInput($k[$X["col"]],"%$X[val]%");}elseif(!ereg('NULL$',$X["op"])){$Sa.=" ".$this->processInput($k[$X["col"]],$X["val"]);}if($X["col"]!=""){$J[]=idf_escape($X["col"]).$Sa;}else{$La=array();foreach($k +as$D=>$j){if(is_numeric($X["val"])||!ereg('int|float|double|decimal',$j["type"])){$D=idf_escape($D);$La[]=($x=="sql"&&ereg('char|text|enum|set',$j["type"])&&!ereg('^utf8',$j["collation"])?"CONVERT($D USING utf8)":$D);}}$J[]=($La?"(".implode("$Sa OR ",$La)."$Sa)":"0");}}}return$J;}function +selectOrderProcess($k,$v){$J=array();foreach((array)$_GET["order"]as$y=>$X){if(isset($k[$X])||preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~',$X)){$J[]=(isset($k[$X])?idf_escape($X):$X).(isset($_GET["desc"][$y])?" DESC":"");}}return$J;}function +selectLimitProcess(){return(isset($_GET["limit"])?$_GET["limit"]:"30");}function +selectLengthProcess(){return(isset($_GET["text_length"])?$_GET["text_length"]:"100");}function +selectEmailProcess($Z,$Xb){return +false;}function +messageQuery($H){global$x;static$Wa=0;restart_session();$t="sql-".($Wa++);$gc=&get_session("queries");if(strlen($H)>1e6){$H=ereg_replace('[\x80-\xFF]+$','',substr($H,0,1e6))."\n...";}$gc[$_GET["db"]][]=$H;return" ".'SQL command'."';}function +editFunctions($j){global$ub;$J=($j["null"]?"NULL/":"");foreach($ub +as$y=>$p){if(!$y||(!isset($_GET["call"])&&(isset($_GET["select"])||where($_GET)))){foreach($p +as$F=>$X){if(!$F||ereg($F,$j["type"])){$J.="/$X";}}if($y&&!ereg('set|blob|bytea|raw|file',$j["type"])){$J.="/=";}}}return +explode("/",$J);}function +editInput($S,$j,$ta,$Y){if($j["type"]=="enum"){return(isset($_GET["select"])?" ":"").($j["null"]?" ":"").enum_input("radio",$ta,$j,$Y,0);}return"";}function +processInput($j,$Y,$o=""){if($o=="="){return$Y;}$D=$j["field"];$J=($j["type"]=="bit"&&ereg("^([0-9]+|b'[0-1]+')\$",$Y)?$Y:q($Y));if(ereg('^(now|getdate|uuid)$',$o)){$J="$o()";}elseif(ereg('^current_(date|timestamp)$',$o)){$J=$o;}elseif(ereg('^([+-]|\\|\\|)$',$o)){$J=idf_escape($D)." $o $J";}elseif(ereg('^[+-] interval$',$o)){$J=idf_escape($D)." $o ".(preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+$~i",$Y)?$Y:$J);}elseif(ereg('^(addtime|subtime|concat)$',$o)){$J="$o(".idf_escape($D).", $J)";}elseif(ereg('^(md5|sha1|password|encrypt|hex)$',$o)){$J="$o($J)";}if(ereg("binary",$j["type"])){$J="unhex($J)";}return$J;}function +dumpOutput(){$J=array('text'=>'open','file'=>'save');if(function_exists('gzencode')){$J['gz']='gzip';}if(function_exists('bzcompress')){$J['bz2']='bzip2';}return$J;}function +dumpFormat(){return +array('sql'=>'SQL','csv'=>'CSV,','csv;'=>'CSV;','tsv'=>'TSV');}function +dumpTable($S,$R,$vc=false){if($_POST["format"]!="sql"){echo"\xef\xbb\xbf";if($R){dump_csv(array_keys(fields($S)));}}elseif($R){$Xa=create_sql($S,$_POST["auto_increment"]);if($Xa){if($R=="DROP+CREATE"){echo"DROP ".($vc?"VIEW":"TABLE")." IF EXISTS ".table($S).";\n";}if($vc){$Xa=preg_replace('~^([A-Z =]+) DEFINER=`'.preg_replace('~@(.*)~','`@`(%|\\1)',logged_user()).'`~','\\1',$Xa);}echo($R!="CREATE+ALTER"?$Xa:($vc?substr_replace($Xa," OR REPLACE",6,0):substr_replace($Xa," IF NOT EXISTS",12,0))).";\n\n";}if($R=="CREATE+ALTER"&&!$vc){$H="SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLLATION_NAME, COLUMN_TYPE, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ".q($S)." ORDER BY ORDINAL_POSITION";echo"DELIMITER ;; +CREATE PROCEDURE adminer_alter (INOUT alter_command text) BEGIN + DECLARE _column_name, _collation_name, after varchar(64) DEFAULT ''; + DECLARE _column_type, _column_default text; + DECLARE _is_nullable char(3); + DECLARE _extra varchar(30); + DECLARE _column_comment varchar(255); + DECLARE done, set_after bool DEFAULT 0; + DECLARE add_columns text DEFAULT '";$k=array();$oa="";foreach(get_rows($H)as$K){$hb=$K["COLUMN_DEFAULT"];$K["default"]=(isset($hb)?q($hb):"NULL");$K["after"]=q($oa);$K["alter"]=escape_string(idf_escape($K["COLUMN_NAME"])." $K[COLUMN_TYPE]".($K["COLLATION_NAME"]?" COLLATE $K[COLLATION_NAME]":"").(isset($hb)?" DEFAULT ".($hb=="CURRENT_TIMESTAMP"?$hb:$K["default"]):"").($K["IS_NULLABLE"]=="YES"?"":" NOT NULL").($K["EXTRA"]?" $K[EXTRA]":"").($K["COLUMN_COMMENT"]?" COMMENT ".q($K["COLUMN_COMMENT"]):"").($oa?" AFTER ".idf_escape($oa):" FIRST"));echo", ADD $K[alter]";$k[]=$K;$oa=$K["COLUMN_NAME"];}echo"'; + DECLARE columns CURSOR FOR $H; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; + SET @alter_table = ''; + OPEN columns; + REPEAT + FETCH columns INTO _column_name, _column_default, _is_nullable, _collation_name, _column_type, _extra, _column_comment; + IF NOT done THEN + SET set_after = 1; + CASE _column_name";foreach($k +as$K){echo" + WHEN ".q($K["COLUMN_NAME"])." THEN + SET add_columns = REPLACE(add_columns, ', ADD $K[alter]', IF( + _column_default <=> $K[default] AND _is_nullable = '$K[IS_NULLABLE]' AND _collation_name <=> ".(isset($K["COLLATION_NAME"])?"'$K[COLLATION_NAME]'":"NULL")." AND _column_type = ".q($K["COLUMN_TYPE"])." AND _extra = '$K[EXTRA]' AND _column_comment = ".q($K["COLUMN_COMMENT"])." AND after = $K[after] + , '', ', MODIFY $K[alter]'));";}echo" + ELSE + SET @alter_table = CONCAT(@alter_table, ', DROP ', _column_name); + SET set_after = 0; + END CASE; + IF set_after THEN + SET after = _column_name; + END IF; + END IF; + UNTIL done END REPEAT; + CLOSE columns; + IF @alter_table != '' OR add_columns != '' THEN + SET alter_command = CONCAT(alter_command, 'ALTER TABLE ".table($S)."', SUBSTR(CONCAT(add_columns, @alter_table), 2), ';\\n'); + END IF; +END;; +DELIMITER ; +CALL adminer_alter(@adminer_alter); +DROP PROCEDURE adminer_alter; + +";}}}function +dumpData($S,$R,$H){global$e,$x;$Nc=($x=="sqlite"?0:1048576);if($R){if($_POST["format"]=="sql"&&$R=="TRUNCATE+INSERT"){echo +truncate_sql($S).";\n";}if($_POST["format"]=="sql"){$k=fields($S);}$I=$e->query($H,1);if($I){$sc="";$Ca="";while($K=$I->fetch_assoc()){if($_POST["format"]!="sql"){if($R=="table"){dump_csv(array_keys($K));$R="INSERT";}dump_csv($K);}else{if(!$sc){$sc="INSERT INTO ".table($S)." (".implode(", ",array_map('idf_escape',array_keys($K))).") VALUES";}foreach($K +as$y=>$X){$K[$y]=(isset($X)?(ereg('int|float|double|decimal',$k[$y]["type"])?$X:q($X)):"NULL");}$M=implode(",\t",$K);if($R=="INSERT+UPDATE"){$P=array();foreach($K +as$y=>$X){$P[]=idf_escape($y)." = $X";}echo"$sc ($M) ON DUPLICATE KEY UPDATE ".implode(", ",$P).";\n";}else{$M=($Nc?"\n":" ")."($M)";if(!$Ca){$Ca=$sc.$M;}elseif(strlen($Ca)+4+strlen($M)<$Nc){$Ca.=",$M";}else{echo"$Ca;\n";$Ca=$sc.$M;}}}}if($_POST["format"]=="sql"&&$R!="INSERT+UPDATE"&&$Ca){$Ca.=";\n";echo$Ca;}}elseif($_POST["format"]=="sql"){echo"-- ".str_replace("\n"," ",$e->error)."\n";}}}function +dumpHeaders($kc,$Zc=false){$Ad=$_POST["output"];$Nb=($_POST["format"]=="sql"?"sql":($Zc?"tar":"csv"));header("Content-Type: ".($Ad=="bz2"?"application/x-bzip":($Ad=="gz"?"application/x-gzip":($Nb=="tar"?"application/x-tar":($Nb=="sql"||$Ad!="file"?"text/plain":"text/csv")."; charset=utf-8"))));if($Ad=="bz2"){ob_start('bzcompress',1e6);}if($Ad=="gz"){ob_start('gzencode',1e6);}return$Nb;}function +homepage(){echo'

    '.($_GET["ns"]==""?''.'Alter database'."\n":""),(support("scheme")?"".($_GET["ns"]!=""?'Alter schema':'Create schema')."\n":""),($_GET["ns"]!==""?''.'Database schema'."\n":""),(support("privileges")?"".'Privileges'."\n":"");return +true;}function +navigation($Yc){global$ga,$e,$U,$x,$ob;echo'

    +',$this->name(),' ',$ga,' +',(version_compare($ga,$_COOKIE["adminer_version"])<0?h($_COOKIE["adminer_version"]):""),' +

    +';if($Yc=="auth"){$Ub=true;foreach((array)$_SESSION["pwds"]as$nb=>$_e){foreach($_e +as$O=>$Df){foreach($Df +as$Cf=>$Kd){if(isset($Kd)){if($Ub){echo"

    \n";$Ub=false;}echo"($ob[$nb]) ".h($Cf.($O!=""?"@$O":""))."
    \n";}}}}}else{$g=get_databases();echo'

    +

    +';if(DB==""||!$Yc){echo"".'SQL command'."\n";if(support("dump")){echo"".'Dump'."\n";}}echo' + +

    +
    +
    +

    +';hidden_fields_get();echo($g?html_select("db",array(""=>"(".'database'.")")+$g,DB,"this.form.submit();"):''),' +';if($Yc!="db"&&DB!=""&&$e->select_db(DB)){if($_GET["ns"]!==""&&!$Yc){echo'

    ".'Create new table'."\n";$Ve=tables_list();if(!$Ve){echo"

    ".'No tables.'."\n";}else{$this->tablesPrint($Ve);$Ic=array();foreach($Ve +as$S=>$V){$Ic[]=preg_quote($S,'/');}echo"\n";}}}echo(isset($_GET["sql"])?'':(isset($_GET["schema"])?'':(isset($_GET["dump"])?'':""))),"

    \n";}}function +tablesPrint($Ve){echo"

    \n";foreach($Ve +as$S=>$V){echo'".'select'." ",'".$this->tableName(array("Name"=>$S))."
    \n";}}}$b=(function_exists('adminer_object')?adminer_object():new +Adminer);if(!isset($b->operators)){$b->operators=$qd;}function +page_header($ef,$i="",$Ba=array(),$ff=""){global$ca,$b,$e,$ob;header("Content-Type: text/html; charset=utf-8");if($b->headers()){header("X-Frame-Options: deny");header("X-XSS-Protection: 0");}$gf=$ef.($ff!=""?": ".h($ff):"");$hf=strip_tags($gf.(SERVER!=""&&SERVER!="localhost"?h(" - ".SERVER):"")." - ".$b->name());if(is_ajax()){header("X-AJAX-Title: ".rawurlencode($hf));}else{echo' + + + + +',$hf,' + + + +';if($b->head()){echo' +';if(file_exists("adminer.css")){echo' +';}}echo' +"> + + +

    +'.$ob[DRIVER].' » ';$_=substr(preg_replace('~(db|ns)=[^&]*&~','',ME),0,-1);$O=(SERVER!=""?h(SERVER):'Server');if($Ba===false){echo"$O\n";}else{echo"$O » ";if($_GET["ns"]!=""||(DB!=""&&is_array($Ba))){echo''.h(DB).' » ';}if(is_array($Ba)){if($_GET["ns"]!=""){echo''.h($_GET["ns"]).' » ';}foreach($Ba +as$y=>$X){$jb=(is_array($X)?$X[1]:$X);if($jb!=""){echo''.h($jb).' » ';}}}echo"$ef\n";}}echo"\n","

    $gf

    \n";restart_session();$Af=preg_replace('~^[^?]*~','',$_SERVER["REQUEST_URI"]);$Wc=$_SESSION["messages"][$Af];if($Wc){echo"
    ".implode("
    \n
    ",$Wc)."
    \n";unset($_SESSION["messages"][$Af]);}$g=&get_session("dbs");if(DB!=""&&$g&&!in_array(DB,$g,true)){$g=null;}if($i){echo"
    $i
    \n";}define("PAGE_HEADER",1);}function +page_footer($Yc=""){global$b;if(!is_ajax()){echo'
    + + +';}}function +int32($C){while($C>=2147483648){$C-=4294967296;}while($C<=-2147483649){$C+=4294967296;}return(int)$C;}function +long2str($W,$If){$M='';foreach($W +as$X){$M.=pack('V',$X);}if($If){return +substr($M,0,end($W));}return$M;}function +str2long($M,$If){$W=array_values(unpack('V*',str_pad($M,4*ceil(strlen($M)/4),"\0")));if($If){$W[]=strlen($M);}return$W;}function +xxtea_mx($Mf,$Lf,$Ne,$xc){return +int32((($Mf>>5&0x7FFFFFF)^$Lf<<2)+(($Lf>>3&0x1FFFFFFF)^$Mf<<4))^int32(($Ne^$Lf)+($xc^$Mf));}function +encrypt_string($Ie,$y){if($Ie==""){return"";}$y=array_values(unpack("V*",pack("H*",md5($y))));$W=str2long($Ie,true);$C=count($W)-1;$Mf=$W[$C];$Lf=$W[0];$G=floor(6+52/($C+1));$Ne=0;while($G-->0){$Ne=int32($Ne+0x9E3779B9);$tb=$Ne>>2&3;for($Bd=0;$Bd<$C;$Bd++){$Lf=$W[$Bd+1];$ad=xxtea_mx($Mf,$Lf,$Ne,$y[$Bd&3^$tb]);$Mf=int32($W[$Bd]+$ad);$W[$Bd]=$Mf;}$Lf=$W[0];$ad=xxtea_mx($Mf,$Lf,$Ne,$y[$Bd&3^$tb]);$Mf=int32($W[$C]+$ad);$W[$C]=$Mf;}return +long2str($W,false);}function +decrypt_string($Ie,$y){if($Ie==""){return"";}$y=array_values(unpack("V*",pack("H*",md5($y))));$W=str2long($Ie,false);$C=count($W)-1;$Mf=$W[$C];$Lf=$W[0];$G=floor(6+52/($C+1));$Ne=int32($G*0x9E3779B9);while($Ne){$tb=$Ne>>2&3;for($Bd=$C;$Bd>0;$Bd--){$Mf=$W[$Bd-1];$ad=xxtea_mx($Mf,$Lf,$Ne,$y[$Bd&3^$tb]);$Lf=int32($W[$Bd]-$ad);$W[$Bd]=$Lf;}$Mf=$W[$C];$ad=xxtea_mx($Mf,$Lf,$Ne,$y[$Bd&3^$tb]);$Lf=int32($W[0]-$ad);$W[0]=$Lf;$Ne=int32($Ne-0x9E3779B9);}return +long2str($W,true);}$e='';$U=$_SESSION["token"];if(!$_SESSION["token"]){$_SESSION["token"]=rand(1,1e6);}$Ld=array();if($_COOKIE["adminer_permanent"]){foreach(explode(" ",$_COOKIE["adminer_permanent"])as$X){list($y)=explode(":",$X);$Ld[$y]=$X;}}if(isset($_POST["server"])){session_regenerate_id();$_SESSION["pwds"][$_POST["driver"]][$_POST["server"]][$_POST["username"]]=$_POST["password"];if($_POST["permanent"]){$y=base64_encode($_POST["driver"])."-".base64_encode($_POST["server"])."-".base64_encode($_POST["username"]);$Vd=$b->permanentLogin();$Ld[$y]="$y:".base64_encode($Vd?encrypt_string($_POST["password"],$Vd):"");cookie("adminer_permanent",implode(" ",$Ld));}if(count($_POST)==($_POST["permanent"]?5:4)||DRIVER!=$_POST["driver"]||SERVER!=$_POST["server"]||$_GET["username"]!==$_POST["username"]){redirect(auth_url($_POST["driver"],$_POST["server"],$_POST["username"]));}}elseif($_POST["logout"]){if($U&&$_POST["token"]!=$U){page_header('Logout','Invalid CSRF token. Send the form again.');page_footer("db");exit;}else{foreach(array("pwds","dbs","queries")as$y){set_session($y,null);}$y=base64_encode(DRIVER)."-".base64_encode(SERVER)."-".base64_encode($_GET["username"]);if($Ld[$y]){unset($Ld[$y]);cookie("adminer_permanent",implode(" ",$Ld));}redirect(substr(preg_replace('~(username|db|ns)=[^&]*&~','',ME),0,-1),'Logout successful.');}}elseif($Ld&&!$_SESSION["pwds"]){session_regenerate_id();$Vd=$b->permanentLogin();foreach($Ld +as$y=>$X){list(,$Ha)=explode(":",$X);list($nb,$O,$Cf)=array_map('base64_decode',explode("-",$y));$_SESSION["pwds"][$nb][$O][$Cf]=decrypt_string(base64_decode($Ha),$Vd);}}function +auth_error($Hb=null){global$e,$b,$U;$Ae=session_name();$i="";if(!$_COOKIE[$Ae]&&$_GET[$Ae]&&ini_bool("session.use_only_cookies")){$i='Session support must be enabled.';}elseif(isset($_GET["username"])){if(($_COOKIE[$Ae]||$_GET[$Ae])&&!$U){$i='Session expired, please login again.';}else{$Kd=&get_session("pwds");if(isset($Kd)){$i=h($Hb?$Hb->getMessage():(is_string($e)?$e:'Invalid credentials.'));$Kd=null;}}}page_header('Login',$i,null);echo"
    \n";$b->loginForm();echo"
    ";hidden_fields($_POST,array("driver","server","username","password","permanent"));echo"
    \n","
    \n";page_footer("auth");}if(isset($_GET["username"])){if(!class_exists("Min_DB")){unset($_SESSION["pwds"][DRIVER]);page_header('No extension',sprintf('None of the supported PHP extensions (%s) are available.',implode(", ",$Qd)),false);page_footer("auth");exit;}$e=connect();}if(is_string($e)||!$b->login($_GET["username"],get_session("pwds"))){auth_error();exit;}$U=$_SESSION["token"];if(isset($_POST["server"])&&$_POST["token"]){$_POST["token"]=$U;}$i=($_POST?($_POST["token"]==$U?"":'Invalid CSRF token. Send the form again.'):($_SERVER["REQUEST_METHOD"]!="POST"?"":sprintf('Too big POST data. Reduce the data or increase the %s configuration directive.','"post_max_size"')));function +connect_error(){global$e,$U,$i,$ob;$g=array();if(DB!=""){page_header('Database'.": ".h(DB),'Invalid database.',true);}else{if($_POST["db"]&&!$i){queries_redirect(substr(ME,0,-1),'Databases have been dropped.',drop_databases($_POST["db"]));}page_header('Select database',$i,false);echo"

    ".'Create new database'."\n";foreach(array('privileges'=>'Privileges','processlist'=>'Process list','variables'=>'Variables','status'=>'Status',)as$y=>$X){if(support($y)){echo"$X\n";}}echo"

    ".sprintf('%s version: %s through PHP extension %s',$ob[DRIVER],"$e->server_info","$e->extension")."\n","

    ".sprintf('Logged as: %s',"".h(logged_user())."")."\n";if($_GET["refresh"]){set_session("dbs",null);}$g=get_databases();if($g){$ve=support("scheme");$c=collations();echo"

    \n","\n","\n";foreach($g +as$h){$oe=h(ME)."db=".urlencode($h);echo"
     ".'Database'."".'Collation'."".'Tables'."
    ".checkbox("db[]",$h,in_array($h,(array)$_POST["db"])),"".h($h)."","".nbsp(db_collation($h,$c))."","?","\n";}echo"
    \n","\n","

    \n";echo"\n","".'Refresh'."\n","

    \n";}}page_footer("db");if($g){echo"\n";}}if(isset($_GET["status"])){$_GET["variables"]=$_GET["status"];}if(!(DB!=""?$e->select_db(DB):isset($_GET["sql"])||isset($_GET["dump"])||isset($_GET["database"])||isset($_GET["processlist"])||isset($_GET["privileges"])||isset($_GET["user"])||isset($_GET["variables"])||$_GET["script"]=="connect")){if(DB!=""){set_session("dbs",null);}connect_error();exit;}function +select($I,$f=null,$jc=""){$Ic=array();$v=array();$d=array();$_a=array();$sf=array();odd('');for($s=0;$K=$I->fetch_row();$s++){if(!$s){echo"\n","";for($w=0;$wfetch_field();$D=$j->name;$vd=$j->orgtable;$ud=$j->orgname;if($jc){$Ic[$w]=($D=="table"?"table=":($D=="possible_keys"?"indexes=":null));}elseif($vd!=""){if(!isset($v[$vd])){$v[$vd]=array();foreach(indexes($vd,$f)as$u){if($u["type"]=="PRIMARY"){$v[$vd]=array_flip($u["columns"]);break;}}$d[$vd]=$v[$vd];}if(isset($d[$vd][$ud])){unset($d[$vd][$ud]);$v[$vd][$ud]=$w;$Ic[$w]=$vd;}}if($j->charsetnr==63){$_a[$w]=true;}$sf[$w]=$j->type;$D=h($D);echo"name!=$ud?" title='".h(($vd!=""?"$vd.":"").$ud)."'":"").">".($jc?"$D":$D);}echo"\n";}echo"";foreach($K +as$y=>$X){if(!isset($X)){$X="NULL";}elseif($_a[$y]&&!is_utf8($X)){$X="".lang(array('%d byte','%d bytes'),strlen($X))."";}elseif(!strlen($X)){$X=" ";}else{$X=h($X);if($sf[$y]==254){$X="$X";}}if(isset($Ic[$y])&&!$d[$Ic[$y]]){if($jc){$_=$Ic[$y].urlencode($K[array_search("table=",$Ic)]);}else{$_="edit=".urlencode($Ic[$y]);foreach($v[$Ic[$y]]as$Ia=>$w){$_.="&where".urlencode("[".bracket_escape($Ia)."]")."=".urlencode($K[$w]);}}$X="$X";}echo"
    $X";}}echo($s?"
    ":"

    ".'No rows.')."\n";}function +referencable_primary($xe){$J=array();foreach(table_status()as$Re=>$S){if($Re!=$xe&&fk_support($S)){foreach(fields($Re)as$j){if($j["primary"]){if($J[$Re]){unset($J[$Re]);break;}$J[$Re]=$j;}}}}return$J;}function +textarea($D,$Y,$L=10,$La=80){echo"";}function +format_time($Ee,$_b){return" (".sprintf('%.3f s',max(0,array_sum(explode(" ",$_b))-array_sum(explode(" ",$Ee)))).")";}function +edit_type($y,$j,$c,$m=array()){global$Je,$sf,$zf,$md;echo' +',"',($zf?"':''),($m?" ":" ");}function +process_length($Gc){global$Cb;return(preg_match("~^\\s*(?:$Cb)(?:\\s*,\\s*(?:$Cb))*\\s*\$~",$Gc)&&preg_match_all("~$Cb~",$Gc,$Lc)?implode(",",$Lc[0]):preg_replace('~[^0-9,+-]~','',$Gc));}function +process_type($j,$Ja="COLLATE"){global$zf;return" $j[type]".($j["length"]!=""?"(".process_length($j["length"]).")":"").(ereg('int|float|double|decimal',$j["type"])&&in_array($j["unsigned"],$zf)?" $j[unsigned]":"").(ereg('char|text|enum|set',$j["type"])&&$j["collation"]?" $Ja ".q($j["collation"]):"");}function +process_field($j,$qf){return +array(idf_escape($j["field"]),process_type($qf),($j["null"]?" NULL":" NOT NULL"),(isset($j["default"])?" DEFAULT ".(($j["type"]=="timestamp"&&eregi('^CURRENT_TIMESTAMP$',$j["default"]))||($j["type"]=="bit"&&ereg("^([0-9]+|b'[0-1]+')\$",$j["default"]))?$j["default"]:q($j["default"])):""),($j["on_update"]?" ON UPDATE $j[on_update]":""),(support("comment")&&$j["comment"]!=""?" COMMENT ".q($j["comment"]):""),($j["auto_increment"]?auto_increment():null),);}function +type_class($V){foreach(array('char'=>'text','date'=>'time|year','binary'=>'blob','enum'=>'set',)as$y=>$X){if(ereg("$y|$X",$V)){return" class='$y'";}}}function +edit_fields($k,$c,$V="TABLE",$qa=0,$m=array(),$Qa=false){global$qc;echo' +';if($V=="PROCEDURE"){echo' ';}echo'',($V=="TABLE"?'Column name':'Parameter name'),'Type +Length +Options +';if($V=="TABLE"){echo'NULL +AI +

    ".'Comment'.": ".h($Pa)."\n";}if($k){echo"\n","\n";foreach($k +as$j){echo"
    ".'Column'."".'Type'.(support("comment")?"".'Comment':"")."
    ".h($j["field"]),"".h($j["full_type"]).($j["null"]?" NULL":"").($j["auto_increment"]?" ".'Auto Increment'."":""),(isset($j["default"])?" [".h($j["default"])."]":""),(support("comment")?"".nbsp($j["comment"]):""),"\n";}echo"
    \n";if(!is_view($T)){echo"

    ".'Indexes'."

    \n";$v=indexes($a);if($v){echo"\n";foreach($v +as$D=>$u){ksort($u["columns"]);$Ud=array();foreach($u["columns"]as$y=>$X){$Ud[]="".h($X)."".($u["lengths"][$y]?"(".$u["lengths"][$y].")":"");}echo"
    $u[type]".implode(", ",$Ud)."\n";}echo"
    \n";}echo'

    '.'Alter indexes'."\n";if(fk_support($T)){echo"

    ".'Foreign keys'."

    \n";$m=foreign_keys($a);if($m){echo"\n","\n";foreach($m +as$D=>$l){echo"","
    ".'Source'."".'Target'."".'ON DELETE'."".'ON UPDATE'.($x!="sqlite"?" ":"")."
    ".implode(", ",array_map('h',$l["source"]))."","".($l["db"]!=""?"".h($l["db"]).".":"").($l["ns"]!=""?"".h($l["ns"]).".":"").h($l["table"])."","(".implode(", ",array_map('h',$l["target"])).")","".nbsp($l["on_delete"])."\n","".nbsp($l["on_update"])."\n";if($x!="sqlite"){echo''.'Alter'.'';}}echo"
    \n";}if($x!="sqlite"){echo'

    '.'Add foreign key'."\n";}}if(support("trigger")){echo"

    ".'Triggers'."

    \n";$pf=triggers($a);if($pf){echo"\n";foreach($pf +as$y=>$X){echo"
    $X[0]$X[1]".h($y)."".'Alter'."\n";}echo"
    \n";}echo'

    '.'Add trigger'."\n";}}}}elseif(isset($_GET["schema"])){page_header('Database schema',"",array(),DB.($_GET["ns"]?".$_GET[ns]":""));$Se=array();$Te=array();$D="adminer_schema";$ea=($_GET["schema"]?$_GET["schema"]:$_COOKIE[($_COOKIE["$D-".DB]?"$D-".DB:$D)]);preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~',$ea,$Lc,PREG_SET_ORDER);foreach($Lc +as$s=>$B){$Se[$B[1]]=array($B[2],$B[3]);$Te[]="\n\t'".js_escape($B[1])."': [ $B[2], $B[3] ]";}$if=0;$za=-1;$ue=array();$he=array();$Ec=array();foreach(table_status()as$T){if(!isset($T["Engine"])){continue;}$Nd=0;$ue[$T["Name"]]["fields"]=array();foreach(fields($T["Name"])as$D=>$j){$Nd+=1.25;$j["pos"]=$Nd;$ue[$T["Name"]]["fields"][$D]=$j;}$ue[$T["Name"]]["pos"]=($Se[$T["Name"]]?$Se[$T["Name"]]:array($if,0));foreach($b->foreignKeys($T["Name"])as$X){if(!$X["db"]){$Cc=$za;if($Se[$T["Name"]][1]||$Se[$X["table"]][1]){$Cc=min(floatval($Se[$T["Name"]][1]),floatval($Se[$X["table"]][1]))-1;}else{$za-=.1;}while($Ec[(string)$Cc]){$Cc-=.0001;}$ue[$T["Name"]]["references"][$X["table"]][(string)$Cc]=array($X["source"],$X["target"]);$he[$X["table"]][$T["Name"]][(string)$Cc]=$X["target"];$Ec[(string)$Cc]=true;}}$if=max($if,$ue[$T["Name"]]["pos"][0]+2.5+$Nd);}echo'

    + +';foreach($ue +as$D=>$S){echo"
    ",''.h($D)."
    \n";foreach($S["fields"]as$j){$X=''.h($j["field"]).'';echo($j["primary"]?"$X":$X)."
    \n";}foreach((array)$S["references"]as$Ze=>$ie){foreach($ie +as$Cc=>$ee){$Dc=$Cc-$Se[$D][1];$s=0;foreach($ee[0]as$Be){echo"
    \n";}}}foreach((array)$he[$D]as$Ze=>$ie){foreach($ie +as$Cc=>$d){$Dc=$Cc-$Se[$D][1];$s=0;foreach($d +as$Ye){echo"
    \n";}}}echo"
    \n";}foreach($ue +as$D=>$S){foreach((array)$S["references"]as$Ze=>$ie){foreach($ie +as$Cc=>$ee){$Xc=$if;$Pc=-10;foreach($ee[0]as$y=>$Be){$Od=$S["pos"][0]+$S["fields"][$Be]["pos"];$Pd=$ue[$Ze]["pos"][0]+$ue[$Ze]["fields"][$ee[1][$y]]["pos"];$Xc=min($Xc,$Od,$Pd);$Pc=max($Pc,$Od,$Pd);}echo"
    \n";}}}echo'
    +

    Permanent link +';}elseif(isset($_GET["dump"])){$a=$_GET["dump"];if($_POST){$Va="";foreach(array("output","format","db_style","routines","events","table_style","auto_increment","triggers","data_style")as$y){$Va.="&$y=".urlencode($_POST[$y]);}cookie("adminer_export",substr($Va,1));$Nb=dump_headers(($a!=""?$a:DB),(DB==""||count((array)$_POST["tables"]+(array)$_POST["data"])>1));$uc=($_POST["format"]=="sql");if($uc){echo"-- Adminer $ga ".$ob[DRIVER]." dump + +".($x!="sql"?"":"SET NAMES utf8; +SET foreign_key_checks = 0; +SET time_zone = ".q($e->result("SELECT @@time_zone"))."; +SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; + +");}$R=$_POST["db_style"];$g=array(DB);if(DB==""){$g=$_POST["databases"];if(is_string($g)){$g=explode("\n",rtrim(str_replace("\r","",$g),"\n"));}}foreach((array)$g +as$h){if($e->select_db($h)){if($uc&&ereg('CREATE',$R)&&($Xa=$e->result("SHOW CREATE DATABASE ".idf_escape($h),1))){if($R=="DROP+CREATE"){echo"DROP DATABASE IF EXISTS ".idf_escape($h).";\n";}echo($R=="CREATE+ALTER"?preg_replace('~^CREATE DATABASE ~','\\0IF NOT EXISTS ',$Xa):$Xa).";\n";}if($uc){if($R){echo +use_sql($h).";\n\n";}if(in_array("CREATE+ALTER",array($R,$_POST["table_style"]))){echo"SET @adminer_alter = '';\n\n";}$_d="";if($_POST["routines"]){foreach(array("FUNCTION","PROCEDURE")as$pe){foreach(get_rows("SHOW $pe STATUS WHERE Db = ".q($h),null,"-- ")as$K){$_d.=($R!='DROP+CREATE'?"DROP $pe IF EXISTS ".idf_escape($K["Name"]).";;\n":"").$e->result("SHOW CREATE $pe ".idf_escape($K["Name"]),2).";;\n\n";}}}if($_POST["events"]){foreach(get_rows("SHOW EVENTS",null,"-- ")as$K){$_d.=($R!='DROP+CREATE'?"DROP EVENT IF EXISTS ".idf_escape($K["Name"]).";;\n":"").$e->result("SHOW CREATE EVENT ".idf_escape($K["Name"]),3).";;\n\n";}}if($_d){echo"DELIMITER ;;\n\n$_d"."DELIMITER ;\n\n";}}if($_POST["table_style"]||$_POST["data_style"]){$Gf=array();foreach(table_status()as$T){$S=(DB==""||in_array($T["Name"],(array)$_POST["tables"]));$cb=(DB==""||in_array($T["Name"],(array)$_POST["data"]));if($S||$cb){if(!is_view($T)){if($Nb=="tar"){ob_start();}$b->dumpTable($T["Name"],($S?$_POST["table_style"]:""));if($cb){$b->dumpData($T["Name"],$_POST["data_style"],"SELECT * FROM ".table($T["Name"]));}if($uc&&$_POST["triggers"]&&$S&&($pf=trigger_sql($T["Name"],$_POST["table_style"]))){echo"\nDELIMITER ;;\n$pf\nDELIMITER ;\n";}if($Nb=="tar"){echo +tar_file((DB!=""?"":"$h/")."$T[Name].csv",ob_get_clean());}elseif($uc){echo"\n";}}elseif($uc){$Gf[]=$T["Name"];}}}foreach($Gf +as$Ff){$b->dumpTable($Ff,$_POST["table_style"],true);}if($Nb=="tar"){echo +pack("x512");}}if($R=="CREATE+ALTER"&&$uc){$H="SELECT TABLE_NAME, ENGINE, TABLE_COLLATION, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()";echo"DELIMITER ;; +CREATE PROCEDURE adminer_alter (INOUT alter_command text) BEGIN + DECLARE _table_name, _engine, _table_collation varchar(64); + DECLARE _table_comment varchar(64); + DECLARE done bool DEFAULT 0; + DECLARE tables CURSOR FOR $H; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; + OPEN tables; + REPEAT + FETCH tables INTO _table_name, _engine, _table_collation, _table_comment; + IF NOT done THEN + CASE _table_name";foreach(get_rows($H)as$K){$Pa=q($K["ENGINE"]=="InnoDB"?preg_replace('~(?:(.+); )?InnoDB free: .*~','\\1',$K["TABLE_COMMENT"]):$K["TABLE_COMMENT"]);echo" + WHEN ".q($K["TABLE_NAME"])." THEN + ".(isset($K["ENGINE"])?"IF _engine != '$K[ENGINE]' OR _table_collation != '$K[TABLE_COLLATION]' OR _table_comment != $Pa THEN + ALTER TABLE ".idf_escape($K["TABLE_NAME"])." ENGINE=$K[ENGINE] COLLATE=$K[TABLE_COLLATION] COMMENT=$Pa; + END IF":"BEGIN END").";";}echo" + ELSE + SET alter_command = CONCAT(alter_command, 'DROP TABLE `', REPLACE(_table_name, '`', '``'), '`;\\n'); + END CASE; + END IF; + UNTIL done END REPEAT; + CLOSE tables; +END;; +DELIMITER ; +CALL adminer_alter(@adminer_alter); +DROP PROCEDURE adminer_alter; +";}if(in_array("CREATE+ALTER",array($R,$_POST["table_style"]))&&$uc){echo"SELECT @adminer_alter;\n";}}}if($uc){echo"-- ".$e->result("SELECT NOW()")."\n";}exit;}page_header('Export',"",($_GET["export"]!=""?array("table"=>$_GET["export"]):array()),DB);echo' +

    + +';$fb=array('','USE','DROP+CREATE','CREATE');$Ue=array('','DROP+CREATE','CREATE');$db=array('','TRUNCATE+INSERT','INSERT');if($x=="sql"){$fb[]='CREATE+ALTER';$Ue[]='CREATE+ALTER';$db[]='INSERT+UPDATE';}parse_str($_COOKIE["adminer_export"],$K);if(!$K){$K=array("output"=>"text","format"=>"sql","db_style"=>(DB!=""?"":"CREATE"),"table_style"=>"DROP+CREATE","data_style"=>"INSERT");}if(!isset($K["events"])){$K["routines"]=$K["events"]=($_GET["dump"]=="");$K["triggers"]=$K["table_style"];}echo"
    ".'Output'."".html_select("output",$b->dumpOutput(),$K["output"],0)."\n";echo"
    ".'Format'."".html_select("format",$b->dumpFormat(),$K["format"],0)."\n";echo($x=="sqlite"?"":"
    ".'Database'."".html_select('db_style',$fb,$K["db_style"]).(support("routine")?checkbox("routines",1,$K["routines"],'Routines'):"").(support("event")?checkbox("events",1,$K["events"],'Events'):"")),"
    ".'Tables'."".html_select('table_style',$Ue,$K["table_style"]).checkbox("auto_increment",1,$K["auto_increment"],'Auto Increment').(support("trigger")?checkbox("triggers",1,$K["triggers"],'Triggers'):""),"
    ".'Data'."".html_select('data_style',$db,$K["data_style"]),'
    +

    + + +';$Sd=array();if(DB!=""){$Fa=($a!=""?"":" checked");echo"","\n";$Gf="";foreach(table_status()as$T){$D=$T["Name"];$Rd=ereg_replace("_.*","",$D);$Fa=($a==""||$a==(substr($a,-1)=="%"?"$Rd%":$D));$Ud="\n";$g=get_databases();if($g){foreach($g +as$h){if(!information_schema($h)){$Rd=ereg_replace("_.*","",$h);echo"
    ","","
    ".checkbox("tables[]",$D,$Fa,$D,"formUncheck('check-tables');");if(is_view($T)){$Gf.="$Ud\n";}else{echo"$Ud\n";}$Sd[$Rd]++;}echo$Gf;}else{echo"
    ".checkbox("databases[]",$h,$a==""||$a=="$Rd%",$h,"formUncheck('check-databases');")."\n";$Sd[$Rd]++;}}}else{echo"
    ";}}echo'
    +

    +';$Ub=true;foreach($Sd +as$y=>$X){if($y!=""&&$X>1){echo($Ub?"

    ":" ")."".h($y)."";$Ub=false;}}}elseif(isset($_GET["privileges"])){page_header('Privileges');$I=$e->query("SELECT User, Host FROM mysql.".(DB==""?"user":"db WHERE ".q(DB)." LIKE Db")." ORDER BY Host, User");$q=$I;if(!$I){$I=$e->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1) AS User, SUBSTRING_INDEX(CURRENT_USER, '@', -1) AS Host");}echo"

    \n";hidden_fields_get();echo"\n",($q?"":"\n"),"\n","\n";while($K=$I->fetch_assoc()){echo'
    ".'Username'."".'Server'." 
    '.h($K["User"])."".h($K["Host"]).''.'Edit'."\n";}if(!$q||DB!=""){echo"\n";}echo"
    \n","

    \n",'

    '.'Create user'."";}elseif(isset($_GET["sql"])){if(!$i&&$_POST["export"]){dump_headers("sql");$b->dumpTable("","");$b->dumpData("","table",$_POST["query"]);exit;}restart_session();$hc=&get_session("queries");$gc=&$hc[DB];if(!$i&&$_POST["clear"]){$gc=array();redirect(remove_from_uri("history"));}page_header('SQL command',$i);if(!$i&&$_POST){$Zb=false;$H=$_POST["query"];if($_POST["webfile"]){$Zb=@fopen((file_exists("adminer.sql")?"adminer.sql":(file_exists("adminer.sql.gz")?"compress.zlib://adminer.sql.gz":"compress.bzip2://adminer.sql.bz2")),"rb");$H=($Zb?fread($Zb,1e6):false);}elseif($_FILES&&$_FILES["sql_file"]["error"]!=4){$H=get_file("sql_file",true);}if(is_string($H)){if(function_exists('memory_get_usage')){@ini_set("memory_limit",max(ini_get("memory_limit"),2*strlen($H)+memory_get_usage()+8e6));}if($H!=""&&strlen($H)<1e6){$G=$H.(ereg(';$',$H)?"":";");if(!$gc||end($gc)!=$G){$gc[]=$G;}}$Ce="(?:\\s|/\\*.*\\*/|(?:#|-- )[^\n]*\n|--\n)";if(!ini_bool("session.use_cookies")){session_write_close();}$ib=";";$hd=0;$zb=true;$f=connect();if(is_object($f)&&DB!=""){$f->select_db(DB);}$Oa=0;$Eb=array();$Ed='[\'"'.($x=="sql"?'`#':($x=="sqlite"?'`[':($x=="mssql"?'[':''))).']|/\\*|-- |$'.($x=="pgsql"?'|\\$[^$]*\\$':'');$jf=microtime();parse_str($_COOKIE["adminer_export"],$ka);$sb=$b->dumpFormat();unset($sb["sql"]);while($H!=""){if(!$hd&&preg_match("~^$Ce*DELIMITER\\s+(.+)~i",$H,$B)){$ib=$B[1];$H=substr($H,strlen($B[0]));}else{preg_match('('.preg_quote($ib)."|$Ed)",$H,$B,PREG_OFFSET_CAPTURE,$hd);$n=$B[0][0];if(!$n&&$Zb&&!feof($Zb)){$H.=fread($Zb,1e5);}else{$hd=$B[0][1]+strlen($n);if(!$n&&rtrim($H)==""){break;}if($n&&$n!=$ib){while(preg_match('('.($n=='/*'?'\\*/':($n=='['?']':(ereg('^-- |^#',$n)?"\n":preg_quote($n)."|\\\\."))).'|$)s',$H,$B,PREG_OFFSET_CAPTURE,$hd)){$M=$B[0][0];$hd=$B[0][1]+strlen($M);if(!$M&&$Zb&&!feof($Zb)){$hd-=strlen($n);$H.=fread($Zb,1e5);}elseif($M[0]!="\\"){break;}}}else{$zb=false;$G=substr($H,0,$B[0][1]);$Oa++;$Ud="

    ".shorten_utf8(trim($G),1000)."
    \n";if(!$_POST["only_errors"]){echo$Ud;ob_flush();flush();}$Ee=microtime();if($e->multi_query($G)&&is_object($f)&&preg_match("~^$Ce*USE\\b~isU",$G)){$f->query($G);}do{$I=$e->store_result();$_b=microtime();$cf=format_time($Ee,$_b).(strlen($G)<1000?" ".'Edit'."":"");if($e->error){echo($_POST["only_errors"]?$Ud:""),"

    ".'Error in query'.": ".error()."\n";$Eb[]=" $Oa";if($_POST["error_stops"]){break +2;}}elseif(is_object($I)){select($I,$f);if(!$_POST["only_errors"]){echo"

    \n","

    ".($I->num_rows?lang(array('%d row','%d rows'),$I->num_rows):"").$cf;$t="export-$Oa";$Mb=", ".'Export'."\n";if($f&&preg_match("~^($Ce|\\()*SELECT\\b~isU",$G)&&($Lb=explain($f,$G))){$t="explain-$Oa";echo", EXPLAIN$Mb","

    \n";}else{echo$Mb;}echo"
    \n";}}else{if(preg_match("~^$Ce*(CREATE|DROP|ALTER)$Ce+(DATABASE|SCHEMA)\\b~isU",$G)){restart_session();set_session("dbs",null);session_write_close();}if(!$_POST["only_errors"]){echo"

    ".lang(array('Query executed OK, %d row affected.','Query executed OK, %d rows affected.'),$e->affected_rows)."$cf\n";}}$Ee=$_b;}while($e->next_result());$H=substr($H,$hd);$hd=0;}}}}if($zb){echo"

    ".'No commands to execute.'."\n";}elseif($_POST["only_errors"]){echo"

    ".lang(array('%d query executed OK.','%d queries executed OK.'),$Oa-count($Eb)).format_time($jf,microtime())."\n";}elseif($Eb&&$Oa>1){echo"

    ".'Error in query'.": ".implode("",$Eb)."\n";}}else{echo"

    ".upload_error($H)."\n";}}echo' +

    +

    ';$G=$_GET["sql"];if($_POST){$G=$_POST["query"];}elseif($_GET["history"]=="all"){$G=$gc;}elseif($_GET["history"]!=""){$G=$gc[$_GET["history"]];}textarea("query",$G,20);echo($_POST?"":"\n"),"

    ".(ini_bool("file_uploads")?'File upload'.': (< '.ini_get("upload_max_filesize").'B)':'File uploads are disabled.'),'

    + + +',checkbox("error_stops",1,$_POST["error_stops"],'Stop on error')."\n",checkbox("only_errors",1,$_POST["only_errors"],'Show only errors')."\n";print_fieldset("webfile",'From server',$_POST["webfile"],"document.getElementById('form')['only_errors'].checked = true; ");$Ra=array();foreach(array("gz"=>"zlib","bz2"=>"bz2")as$y=>$X){if(extension_loaded($X)){$Ra[]=".$y";}}echo +sprintf('Webserver file %s',"adminer.sql".($Ra?"[".implode("|",$Ra)."]":"").""),' ',"\n";if($gc){print_fieldset("history",'History',$_GET["history"]!="");foreach($gc +as$y=>$X){echo''.'Edit'." ".shorten_utf8(ltrim(str_replace("\n"," ",str_replace("\r","",preg_replace('~^(#|-- ).*~m','',$X)))),80,"")."
    \n";}echo"\n","".'Edit all'."\n","\n";}echo' +

    +';}elseif(isset($_GET["edit"])){$a=$_GET["edit"];$Z=(isset($_GET["select"])?(count($_POST["check"])==1?where_check($_POST["check"][0]):""):where($_GET));$_f=(isset($_GET["select"])?$_POST["edit"]:$Z);$k=fields($a);foreach($k +as$D=>$j){if(!isset($j["privileges"][$_f?"update":"insert"])||$b->fieldName($j)==""){unset($k[$D]);}}if($_POST&&!$i&&!isset($_GET["select"])){$A=$_POST["referer"];if($_POST["insert"]){$A=($_f?null:$_SERVER["REQUEST_URI"]);}elseif(!ereg('^.+&select=.+$',$A)){$A=ME."select=".urlencode($a);}if(isset($_POST["delete"])){query_redirect("DELETE".limit1("FROM ".table($a)," WHERE $Z"),$A,'Item has been deleted.');}else{$P=array();foreach($k +as$D=>$j){$X=process_input($j);if($X!==false&&$X!==null){$P[idf_escape($D)]=($_f?"\n".idf_escape($D)." = $X":$X);}}if($_f){if(!$P){redirect($A);}query_redirect("UPDATE".limit1(table($a)." SET".implode(",",$P),"\nWHERE $Z"),$A,'Item has been updated.');}else{$I=insert_into($a,$P);$Bc=($I?last_id():0);queries_redirect($A,sprintf('Item%s has been inserted.',($Bc?" $Bc":"")),$I);}}}$Re=$b->tableName(table_status($a));page_header(($_f?'Edit':'Insert'),$i,array("select"=>array($a,$Re)),$Re);$K=null;if($_POST["save"]){$K=(array)$_POST["fields"];}elseif($Z){$N=array();foreach($k +as$D=>$j){if(isset($j["privileges"]["select"])){$N[]=($_POST["clone"]&&$j["auto_increment"]?"'' AS ":(ereg("enum|set",$j["type"])?"1*".idf_escape($D)." AS ":"")).idf_escape($D);}}$K=array();if($N){$L=get_rows("SELECT".limit(implode(", ",$N)." FROM ".table($a)," WHERE $Z",(isset($_GET["select"])?2:1)));$K=(isset($_GET["select"])&&count($L)!=1?null:reset($L));}}if($K===false){echo"

    ".'No rows.'."\n";}echo' +

    +';if($k){echo"\n";foreach($k +as$D=>$j){echo"
    ".$b->fieldName($j);$hb=$_GET["set"][bracket_escape($D)];$Y=(isset($K)?($K[$D]!=""&&ereg("enum|set",$j["type"])?(is_array($K[$D])?array_sum($K[$D]):+$K[$D]):$K[$D]):(!$_f&&$j["auto_increment"]?"":(isset($_GET["select"])?false:(isset($hb)?$hb:$j["default"]))));if(!$_POST["save"]&&is_string($Y)){$Y=$b->editVal($Y,$j);}$o=($_POST["save"]?(string)$_POST["function"][$D]:($_f&&$j["on_update"]=="CURRENT_TIMESTAMP"?"now":($Y===false?null:(isset($Y)?'':'NULL'))));if($j["type"]=="timestamp"&&$Y=="CURRENT_TIMESTAMP"){$Y="";$o="now";}input($j,$Y,$o);echo"\n";}echo"
    \n";}echo'

    +';if($k){echo"\n";if(!isset($_GET["select"])){echo"\n";}}echo($_f?"\n":($_POST||!$k?"":"\n"));if(isset($_GET["select"])){hidden_fields(array("check"=>(array)$_POST["check"],"clone"=>$_POST["clone"],"all"=>$_POST["all"]));}echo' + + +

    +';}elseif(isset($_GET["create"])){$a=$_GET["create"];$Fd=array('HASH','LINEAR HASH','KEY','LINEAR KEY','RANGE','LIST');$ge=referencable_primary($a);$m=array();foreach($ge +as$Re=>$j){$m[str_replace("`","``",$Re)."`".str_replace("`","``",$j["field"])]=$Re;}$yd=array();$zd=array();if($a!=""){$yd=fields($a);$zd=table_status($a);}if($_POST&&!$_POST["fields"]){$_POST["fields"]=array();}if($_POST&&!$i&&!$_POST["add"]&&!$_POST["drop_col"]&&!$_POST["up"]&&!$_POST["down"]){if($_POST["drop"]){query_redirect("DROP TABLE ".table($a),substr(ME,0,-1),'Table has been dropped.');}else{$k=array();$Wb=array();ksort($_POST["fields"]);$xd=reset($yd);$oa="FIRST";foreach($_POST["fields"]as$y=>$j){$l=$m[$j["type"]];$qf=(isset($l)?$ge[$l]:$j);if($j["field"]!=""){if(!$j["has_default"]){$j["default"]=null;}$hb=eregi_replace(" *on update CURRENT_TIMESTAMP","",$j["default"]);if($hb!=$j["default"]){$j["on_update"]="CURRENT_TIMESTAMP";$j["default"]=$hb;}if($y==$_POST["auto_increment_col"]){$j["auto_increment"]=true;}$Zd=process_field($j,$qf);if($Zd!=process_field($xd,$xd)){$k[]=array($j["orig"],$Zd,$oa);}if(isset($l)){$Wb[idf_escape($j["field"])]=($a!=""?"ADD":" ")." FOREIGN KEY (".idf_escape($j["field"]).") REFERENCES ".table($m[$j["type"]])." (".idf_escape($qf["field"]).")".(ereg("^($md)\$",$j["on_delete"])?" ON DELETE $j[on_delete]":"");}$oa="AFTER ".idf_escape($j["field"]);}elseif($j["orig"]!=""){$k[]=array($j["orig"]);}if($j["orig"]!=""){$xd=next($yd);}}$Hd="";if(in_array($_POST["partition_by"],$Fd)){$Id=array();if($_POST["partition_by"]=='RANGE'||$_POST["partition_by"]=='LIST'){foreach(array_filter($_POST["partition_names"])as$y=>$X){$Y=$_POST["partition_values"][$y];$Id[]="\nPARTITION ".idf_escape($X)." VALUES ".($_POST["partition_by"]=='RANGE'?"LESS THAN":"IN").($Y!=""?" ($Y)":" MAXVALUE");}}$Hd.="\nPARTITION BY $_POST[partition_by]($_POST[partition])".($Id?" (".implode(",",$Id)."\n)":($_POST["partitions"]?" PARTITIONS ".(+$_POST["partitions"]):""));}elseif($a!=""&&support("partitioning")){$Hd.="\nREMOVE PARTITIONING";}$Sc='Table has been altered.';if($a==""){cookie("adminer_engine",$_POST["Engine"]);$Sc='Table has been created.';}queries_redirect(ME."table=".urlencode($_POST["name"]),$Sc,alter_table($a,$_POST["name"],$k,$Wb,$_POST["Comment"],($_POST["Engine"]&&$_POST["Engine"]!=$zd["Engine"]?$_POST["Engine"]:""),($_POST["Collation"]&&$_POST["Collation"]!=$zd["Collation"]?$_POST["Collation"]:""),($_POST["Auto_increment"]!=""?+$_POST["Auto_increment"]:""),$Hd));}}page_header(($a!=""?'Alter table':'Create table'),$i,array("table"=>$a),$a);$K=array("Engine"=>$_COOKIE["adminer_engine"],"fields"=>array(array("field"=>"","type"=>(isset($sf["int"])?"int":(isset($sf["integer"])?"integer":"")))),"partition_names"=>array(""),);if($_POST){$K=$_POST;if($K["auto_increment_col"]){$K["fields"][$K["auto_increment_col"]]["auto_increment"]=true;}process_fields($K["fields"]);}elseif($a!=""){$K=$zd;$K["name"]=$a;$K["fields"]=array();if(!$_GET["auto_increment"]){$K["Auto_increment"]="";}foreach($yd +as$j){$j["has_default"]=isset($j["default"]);if($j["on_update"]){$j["default"].=" ON UPDATE $j[on_update]";}$K["fields"][]=$j;}if(support("partitioning")){$ac="FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = ".q(DB)." AND TABLE_NAME = ".q($a);$I=$e->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $ac ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");list($K["partition_by"],$K["partitions"],$K["partition"])=$I->fetch_row();$K["partition_names"]=array();$K["partition_values"]=array();foreach(get_rows("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $ac AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION")as$se){$K["partition_names"][]=$se["PARTITION_NAME"];$K["partition_values"][]=$se["PARTITION_DESCRIPTION"];}$K["partition_names"][]="";}}$c=collations();$Me=floor(extension_loaded("suhosin")?(min(ini_get("suhosin.request.max_vars"),ini_get("suhosin.post.max_vars"))-13)/10:0);if($Me&&count($K["fields"])>$Me){echo"

    ".h(sprintf('Maximum number of allowed fields exceeded. Please increase %s and %s.','suhosin.post.max_vars','suhosin.request.max_vars'))."\n";}$Bb=engines();foreach($Bb +as$Ab){if(!strcasecmp($Ab,$K["Engine"])){$K["Engine"]=$Ab;break;}}echo' +

    +

    +Table name: +';if($a==""&&!$_POST){?>"(".'engine'.")")+$Bb,$K["Engine"]):""),' ',($c&&!ereg("sqlite|mssql",$x)?html_select("Collation",array(""=>"(".'collation'.")")+$c,$K["Collation"]):""),' + +';$Qa=($_POST?$_POST["comments"]:$K["Comment"]!="");if(!$_POST&&!$Qa){foreach($K["fields"]as$j){if($j["comment"]!=""){$Qa=true;break;}}}edit_fields($K["fields"],$c,"TABLE",$Me,$m,$Qa);echo'
    +

    +Auto Increment: + +',(support("comment")?checkbox("comments",1,$Qa,'Comment',"columnShow(this.checked, 6); toggle('Comment'); if (this.checked) this.form['Comment'].focus();",true).' ':''),'

    + +';if($_GET["create"]!=""){echo'';}echo' +';if(support("partitioning")){$Gd=ereg('RANGE|LIST',$K["partition_by"]);print_fieldset("partition",'Partition by',$K["partition_by"]);echo'

    +',html_select("partition_by",array(-1=>"")+$Fd,$K["partition_by"],"partitionByChange(this);"),'() +Partitions: + + +';foreach($K["partition_names"]as$y=>$X){echo'',' + +';}echo'

    +';}elseif(isset($_GET["indexes"])){$a=$_GET["indexes"];$oc=array("PRIMARY","UNIQUE","INDEX");$T=table_status($a);if(eregi("MyISAM|M?aria",$T["Engine"])){$oc[]="FULLTEXT";}$v=indexes($a);if($x=="sqlite"){unset($oc[0]);unset($v[""]);}if($_POST&&!$i&&!$_POST["add"]){$ra=array();foreach($_POST["indexes"]as$u){$D=$u["name"];if(in_array($u["type"],$oc)){$d=array();$Hc=array();$P=array();ksort($u["columns"]);foreach($u["columns"]as$y=>$Ma){if($Ma!=""){$Gc=$u["lengths"][$y];$P[]=idf_escape($Ma).($Gc?"(".(+$Gc).")":"");$d[]=$Ma;$Hc[]=($Gc?$Gc:null);}}if($d){$Kb=$v[$D];if($Kb){ksort($Kb["columns"]);ksort($Kb["lengths"]);if($u["type"]==$Kb["type"]&&array_values($Kb["columns"])===$d&&(!$Kb["lengths"]||array_values($Kb["lengths"])===$Hc)){unset($v[$D]);continue;}}$ra[]=array($u["type"],$D,"(".implode(", ",$P).")");}}}foreach($v +as$D=>$Kb){$ra[]=array($Kb["type"],$D,"DROP");}if(!$ra){redirect(ME."table=".urlencode($a));}queries_redirect(ME."table=".urlencode($a),'Indexes have been altered.',alter_indexes($a,$ra));}page_header('Indexes',$i,array("table"=>$a),$a);$k=array_keys(fields($a));$K=array("indexes"=>$v);if($_POST){$K=$_POST;if($_POST["add"]){foreach($K["indexes"]as$y=>$u){if($u["columns"][count($u["columns"])]!=""){$K["indexes"][$y]["columns"][]="";}}$u=end($K["indexes"]);if($u["type"]||array_filter($u["columns"],'strlen')||array_filter($u["lengths"],'strlen')){$K["indexes"][]=array("columns"=>array(1=>""));}}}else{foreach($K["indexes"]as$y=>$u){$K["indexes"][$y]["name"]=$y;$K["indexes"][$y]["columns"][]="";}$K["indexes"][]=array("columns"=>array(1=>""));}echo' +
    + + +';$w=1;foreach($K["indexes"]as$u){echo"
    Index TypeColumn (length)Name
    ".html_select("indexes[$w][type]",array(-1=>"")+$oc,$u["type"],($w==count($K["indexes"])?"indexesAddRow(this);":1))."";ksort($u["columns"]);$s=1;foreach($u["columns"]as$y=>$Ma){echo"".html_select("indexes[$w][columns][$s]",array(-1=>"")+$k,$Ma,($s==count($u["columns"])?"indexesAddColumn":"indexesChangeColumn")."(this, '".js_escape($x=="sql"?"":$_GET["indexes"]."_")."');")," ";$s++;}echo"\n";$w++;}echo'
    +

    + +

    + +

    +';}elseif(isset($_GET["database"])){if($_POST&&!$i&&!isset($_POST["add_x"])){restart_session();if($_POST["drop"]){$_GET["db"]="";queries_redirect(remove_from_uri("db|database"),'Database has been dropped.',drop_databases(array(DB)));}elseif(DB!==$_POST["name"]){if(DB!=""){$_GET["db"]=$_POST["name"];queries_redirect(preg_replace('~db=[^&]*&~','',ME)."db=".urlencode($_POST["name"]),'Database has been renamed.',rename_database($_POST["name"],$_POST["collation"]));}else{$g=explode("\n",str_replace("\r","",$_POST["name"]));$Ke=true;$Ac="";foreach($g +as$h){if(count($g)==1||$h!=""){if(!create_database($h,$_POST["collation"])){$Ke=false;}$Ac=$h;}}queries_redirect(ME."db=".urlencode($Ac),'Database has been created.',$Ke);}}else{if(!$_POST["collation"]){redirect(substr(ME,0,-1));}query_redirect("ALTER DATABASE ".idf_escape($_POST["name"]).(eregi('^[a-z0-9_]+$',$_POST["collation"])?" COLLATE $_POST[collation]":""),substr(ME,0,-1),'Database has been altered.');}}page_header(DB!=""?'Alter database':'Create database',$i,array(),DB);$c=collations();$D=DB;$Ja=null;if($_POST){$D=$_POST["name"];$Ja=$_POST["collation"];}elseif(DB!=""){$Ja=db_collation(DB,$c);}elseif($x=="sql"){foreach(get_vals("SHOW GRANTS")as$q){if(preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~',$q,$B)&&$B[1]){$D=stripcslashes(idf_unescape("`$B[2]`"));break;}}}echo' +
    +

    +',($_POST["add_x"]||strpos($D,"\n")?'
    ':'')."\n".($c?html_select("collation",array(""=>"(".'collation'.")")+$c,$Ja):"");?> + + +\n";}elseif(!$_POST["add_x"]&&$_GET["db"]==""){echo"\n";}echo' +

    +';}elseif(isset($_GET["call"])){$da=$_GET["call"];page_header('Call'.": ".h($da),$i);$pe=routine($da,(isset($_GET["callf"])?"FUNCTION":"PROCEDURE"));$nc=array();$_d=array();foreach($pe["fields"]as$s=>$j){if(substr($j["inout"],-3)=="OUT"){$_d[$s]="@".idf_escape($j["field"])." AS ".idf_escape($j["field"]);}if(!$j["inout"]||substr($j["inout"],0,2)=="IN"){$nc[]=$s;}}if(!$i&&$_POST){$Da=array();foreach($pe["fields"]as$y=>$j){if(in_array($y,$nc)){$X=process_input($j);if($X===false){$X="''";}if(isset($_d[$y])){$e->query("SET @".idf_escape($j["field"])." = $X");}}$Da[]=(isset($_d[$y])?"@".idf_escape($j["field"]):$X);}$H=(isset($_GET["callf"])?"SELECT":"CALL")." ".idf_escape($da)."(".implode(", ",$Da).")";echo"

    ".h($H)." ".'Edit'."\n";if(!$e->multi_query($H)){echo"

    ".error()."\n";}else{$f=connect();if(is_object($f)){$f->select_db(DB);}do{$I=$e->store_result();if(is_object($I)){select($I,$f);}else{echo"

    ".lang(array('Routine has been called, %d row affected.','Routine has been called, %d rows affected.'),$e->affected_rows)."\n";}}while($e->next_result());if($_d){select($e->query("SELECT ".implode(", ",$_d)));}}}echo' +

    +';if($nc){echo"\n";foreach($nc +as$y){$j=$pe["fields"][$y];$D=$j["field"];echo"
    ".$b->fieldName($j);$Y=$_POST["fields"][$D];if($Y!=""){if($j["type"]=="enum"){$Y=+$Y;}if($j["type"]=="set"){$Y=array_sum($Y);}}input($j,$Y,(string)$_POST["function"][$D]);echo"\n";}echo"
    \n";}echo'

    + + +

    +';}elseif(isset($_GET["foreign"])){$a=$_GET["foreign"];if($_POST&&!$i&&!$_POST["add"]&&!$_POST["change"]&&!$_POST["change-js"]){if($_POST["drop"]){query_redirect("ALTER TABLE ".table($a)."\nDROP ".($x=="sql"?"FOREIGN KEY ":"CONSTRAINT ").idf_escape($_GET["name"]),ME."table=".urlencode($a),'Foreign key has been dropped.');}else{$Be=array_filter($_POST["source"],'strlen');ksort($Be);$Ye=array();foreach($Be +as$y=>$X){$Ye[$y]=$_POST["target"][$y];}query_redirect("ALTER TABLE ".table($a).($_GET["name"]!=""?"\nDROP FOREIGN KEY ".idf_escape($_GET["name"]).",":"")."\nADD FOREIGN KEY (".implode(", ",array_map('idf_escape',$Be)).") REFERENCES ".table($_POST["table"])." (".implode(", ",array_map('idf_escape',$Ye)).")".(ereg("^($md)\$",$_POST["on_delete"])?" ON DELETE $_POST[on_delete]":"").(ereg("^($md)\$",$_POST["on_update"])?" ON UPDATE $_POST[on_update]":""),ME."table=".urlencode($a),($_GET["name"]!=""?'Foreign key has been altered.':'Foreign key has been created.'));$i='Source and target columns must have the same data type, there must be an index on the target columns and referenced data must exist.'."
    $i";}}page_header('Foreign key',$i,array("table"=>$a),$a);$K=array("table"=>$a,"source"=>array(""));if($_POST){$K=$_POST;ksort($K["source"]);if($_POST["add"]){$K["source"][]="";}elseif($_POST["change"]||$_POST["change-js"]){$K["target"]=array();}}elseif($_GET["name"]!=""){$m=foreign_keys($a);$K=$m[$_GET["name"]];$K["source"][]="";}$Be=array_keys(fields($a));$Ye=($a===$K["table"]?$Be:array_keys(fields($K["table"])));$fe=array();foreach(table_status()as$D=>$T){if(fk_support($T)){$fe[]=$D;}}echo' +
    +

    +';if($K["db"]==""&&$K["ns"]==""){echo'Target table: +',html_select("table",$fe,$K["table"],"this.form['change-js'].value = '1'; if (!ajaxForm(this.form)) this.form.submit();"),' +

    + + +';$w=0;foreach($K["source"]as$y=>$X){echo"","
    SourceTarget
    ".html_select("source[".(+$y)."]",array(-1=>"")+$Be,$X,($w==count($K["source"])-1?"foreignAddRow(this);":1)),"".html_select("target[".(+$y)."]",$Ye,$K["target"][$y]);$w++;}echo'
    +

    +ON DELETE: ',html_select("on_delete",array(-1=>"")+explode("|",$md),$K["on_delete"]),' ON UPDATE: ',html_select("on_update",array(-1=>"")+explode("|",$md),$K["on_update"]),'

    + +

    +';}if($_GET["name"]!=""){echo'';}echo' +

    +';}elseif(isset($_GET["view"])){$a=$_GET["view"];$qb=false;if($_POST&&!$i){$qb=drop_create("DROP VIEW ".table($a),"CREATE VIEW ".table($_POST["name"])." AS\n$_POST[select]",($_POST["drop"]?substr(ME,0,-1):ME."table=".urlencode($_POST["name"])),'View has been dropped.','View has been altered.','View has been created.',$a);}page_header(($a!=""?'Alter view':'Create view'),$i,array("table"=>$a),$a);$K=$_POST;if(!$K&&$a!=""){$K=view($a);$K["name"]=$a;}echo' +
    +

    Name: +

    ';textarea("select",$K["select"]);echo'

    +';if($qb){echo'';}echo' +';if($_GET["view"]!=""){echo'';}echo' +

    +';}elseif(isset($_GET["event"])){$aa=$_GET["event"];$tc=array("YEAR","QUARTER","MONTH","DAY","HOUR","MINUTE","WEEK","SECOND","YEAR_MONTH","DAY_HOUR","DAY_MINUTE","DAY_SECOND","HOUR_MINUTE","HOUR_SECOND","MINUTE_SECOND");$Ge=array("ENABLED"=>"ENABLE","DISABLED"=>"DISABLE","SLAVESIDE_DISABLED"=>"DISABLE ON SLAVE");if($_POST&&!$i){if($_POST["drop"]){query_redirect("DROP EVENT ".idf_escape($aa),substr(ME,0,-1),'Event has been dropped.');}elseif(in_array($_POST["INTERVAL_FIELD"],$tc)&&isset($Ge[$_POST["STATUS"]])){$te="\nON SCHEDULE ".($_POST["INTERVAL_VALUE"]?"EVERY ".q($_POST["INTERVAL_VALUE"])." $_POST[INTERVAL_FIELD]".($_POST["STARTS"]?" STARTS ".q($_POST["STARTS"]):"").($_POST["ENDS"]?" ENDS ".q($_POST["ENDS"]):""):"AT ".q($_POST["STARTS"]))." ON COMPLETION".($_POST["ON_COMPLETION"]?"":" NOT")." PRESERVE";queries_redirect(substr(ME,0,-1),($aa!=""?'Event has been altered.':'Event has been created.'),queries(($aa!=""?"ALTER EVENT ".idf_escape($aa).$te.($aa!=$_POST["EVENT_NAME"]?"\nRENAME TO ".idf_escape($_POST["EVENT_NAME"]):""):"CREATE EVENT ".idf_escape($_POST["EVENT_NAME"]).$te)."\n".$Ge[$_POST["STATUS"]]." COMMENT ".q($_POST["EVENT_COMMENT"]).rtrim(" DO\n$_POST[EVENT_DEFINITION]",";").";"));}}page_header(($aa!=""?'Alter event'.": ".h($aa):'Create event'),$i);$K=$_POST;if(!$K&&$aa!=""){$L=get_rows("SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA = ".q(DB)." AND EVENT_NAME = ".q($aa));$K=reset($L);}echo' +
    + +
    Name +
    Start +
    End +
    Every ',html_select("INTERVAL_FIELD",$tc,$K["INTERVAL_FIELD"]),'
    Status',html_select("STATUS",$Ge,$K["STATUS"]),'
    Comment +
     ',checkbox("ON_COMPLETION","PRESERVE",$K["ON_COMPLETION"]=="PRESERVE",'On completion preserve'),'
    +

    ';textarea("EVENT_DEFINITION",$K["EVENT_DEFINITION"]);echo'

    + +';if($aa!=""){echo'';}echo' +

    +';}elseif(isset($_GET["procedure"])){$da=$_GET["procedure"];$pe=(isset($_GET["function"])?"FUNCTION":"PROCEDURE");$qe=routine_languages();$qb=false;if($_POST&&!$i&&!$_POST["add"]&&!$_POST["drop_col"]&&!$_POST["up"]&&!$_POST["down"]){$P=array();$k=(array)$_POST["fields"];ksort($k);foreach($k +as$j){if($j["field"]!=""){$P[]=(ereg("^($qc)\$",$j["inout"])?"$j[inout] ":"").idf_escape($j["field"]).process_type($j,"CHARACTER SET");}}$qb=drop_create("DROP $pe ".idf_escape($da),"CREATE $pe ".idf_escape($_POST["name"])." (".implode(", ",$P).")".(isset($_GET["function"])?" RETURNS".process_type($_POST["returns"],"CHARACTER SET"):"").(in_array($_POST["language"],$qe)?" LANGUAGE $_POST[language]":"").rtrim("\n$_POST[definition]",";").";",substr(ME,0,-1),'Routine has been dropped.','Routine has been altered.','Routine has been created.',$da);}page_header(($da!=""?(isset($_GET["function"])?'Alter function':'Alter procedure').": ".h($da):(isset($_GET["function"])?'Create function':'Create procedure')),$i);$c=get_vals("SHOW CHARACTER SET");sort($c);$K=array("fields"=>array());if($_POST){$K=$_POST;$K["fields"]=(array)$K["fields"];process_fields($K["fields"]);}elseif($da!=""){$K=routine($da,$pe);$K["name"]=$da;}echo' +
    +

    Name: +',($qe?'Language'.": ".html_select("language",$qe,$K["language"]):""),' +';edit_fields($K["fields"],$c,$pe);if(isset($_GET["function"])){echo"
    ".'Return type';edit_type("returns",$K["returns"],$c);}echo'
    +

    ';textarea("definition",$K["definition"]);echo'

    + +';if($da!=""){echo'';}if($qb){echo'';}echo' +

    +';}elseif(isset($_GET["trigger"])){$a=$_GET["trigger"];$of=trigger_options();$nf=array("INSERT","UPDATE","DELETE");$qb=false;if($_POST&&!$i&&in_array($_POST["Timing"],$of["Timing"])&&in_array($_POST["Event"],$nf)&&in_array($_POST["Type"],$of["Type"])){$df=" $_POST[Timing] $_POST[Event]";$ld=" ON ".table($a);$qb=drop_create("DROP TRIGGER ".idf_escape($_GET["name"]).($x=="pgsql"?$ld:""),"CREATE TRIGGER ".idf_escape($_POST["Trigger"]).($x=="mssql"?$ld.$df:$df.$ld).rtrim(" $_POST[Type]\n$_POST[Statement]",";").";",ME."table=".urlencode($a),'Trigger has been dropped.','Trigger has been altered.','Trigger has been created.',$_GET["name"]);}page_header(($_GET["name"]!=""?'Alter trigger'.": ".h($_GET["name"]):'Create trigger'),$i,array("table"=>$a));$K=$_POST;if(!$K){$K=trigger($_GET["name"])+array("Trigger"=>$a."_bi");}echo' +
    + +
    Time',html_select("Timing",$of["Timing"],$K["Timing"],"if (/^".preg_quote($a,"/")."_[ba][iud]$/.test(this.form['Trigger'].value)) this.form['Trigger'].value = '".js_escape($a)."_' + selectValue(this).charAt(0).toLowerCase() + selectValue(this.form['Event']).charAt(0).toLowerCase();"),'
    Event',html_select("Event",$nf,$K["Event"],"this.form['Timing'].onchange();"),'
    Type',html_select("Type",$of["Type"],$K["Type"]),'
    +

    Name: +

    ';textarea("Statement",$K["Statement"]);echo'

    + +';if($_GET["name"]!=""){echo'';}if($qb){echo'';}echo' +

    +';}elseif(isset($_GET["user"])){$fa=$_GET["user"];$Xd=array(""=>array("All privileges"=>""));foreach(get_rows("SHOW PRIVILEGES")as$K){foreach(explode(",",($K["Privilege"]=="Grant option"?"":$K["Context"]))as$Ua){$Xd[$Ua][$K["Privilege"]]=$K["Comment"];}}$Xd["Server Admin"]+=$Xd["File access on server"];$Xd["Databases"]["Create routine"]=$Xd["Procedures"]["Create routine"];unset($Xd["Procedures"]["Create routine"]);$Xd["Columns"]=array();foreach(array("Select","Insert","Update","References")as$X){$Xd["Columns"][$X]=$Xd["Tables"][$X];}unset($Xd["Server Admin"]["Usage"]);foreach($Xd["Tables"]as$y=>$X){unset($Xd["Databases"][$y]);}$cd=array();if($_POST){foreach($_POST["objects"]as$y=>$X){$cd[$X]=(array)$cd[$X]+(array)$_POST["grants"][$y];}}$cc=array();$jd="";if(isset($_GET["host"])&&($I=$e->query("SHOW GRANTS FOR ".q($fa)."@".q($_GET["host"])))){while($K=$I->fetch_row()){if(preg_match('~GRANT (.*) ON (.*) TO ~',$K[0],$B)&&preg_match_all('~ *([^(,]*[^ ,(])( *\\([^)]+\\))?~',$B[1],$Lc,PREG_SET_ORDER)){foreach($Lc +as$X){if($X[1]!="USAGE"){$cc["$B[2]$X[2]"][$X[1]]=true;}if(ereg(' WITH GRANT OPTION',$K[0])){$cc["$B[2]$X[2]"]["GRANT OPTION"]=true;}}}if(preg_match("~ IDENTIFIED BY PASSWORD '([^']+)~",$K[0],$B)){$jd=$B[1];}}}if($_POST&&!$i){$kd=(isset($_GET["host"])?q($fa)."@".q($_GET["host"]):"''");$dd=q($_POST["user"])."@".q($_POST["host"]);$Jd=q($_POST["pass"]);if($_POST["drop"]){query_redirect("DROP USER $kd",ME."privileges=",'User has been dropped.');}else{$Za=false;if($kd!=$dd){$Za=queries(($e->server_info<5?"GRANT USAGE ON *.* TO":"CREATE USER")." $dd IDENTIFIED BY".($_POST["hashed"]?" PASSWORD":"")." $Jd");$i=!$Za;}elseif($_POST["pass"]!=$jd||!$_POST["hashed"]){queries("SET PASSWORD FOR $dd = ".($_POST["hashed"]?$Jd:"PASSWORD($Jd)"));}if(!$i){$me=array();foreach($cd +as$gd=>$q){if(isset($_GET["grant"])){$q=array_filter($q);}$q=array_keys($q);if(isset($_GET["grant"])){$me=array_diff(array_keys(array_filter($cd[$gd],'strlen')),$q);}elseif($kd==$dd){$id=array_keys((array)$cc[$gd]);$me=array_diff($id,$q);$q=array_diff($q,$id);unset($cc[$gd]);}if(preg_match('~^(.+)\\s*(\\(.*\\))?$~U',$gd,$B)&&(!grant("REVOKE",$me,$B[2]," ON $B[1] FROM $dd")||!grant("GRANT",$q,$B[2]," ON $B[1] TO $dd"))){$i=true;break;}}}if(!$i&&isset($_GET["host"])){if($kd!=$dd){queries("DROP USER $kd");}elseif(!isset($_GET["grant"])){foreach($cc +as$gd=>$me){if(preg_match('~^(.+)(\\(.*\\))?$~U',$gd,$B)){grant("REVOKE",array_keys($me),$B[2]," ON $B[1] FROM $dd");}}}}queries_redirect(ME."privileges=",(isset($_GET["host"])?'User has been altered.':'User has been created.'),!$i);if($Za){$e->query("DROP USER $dd");}}}page_header((isset($_GET["host"])?'Username'.": ".h("$fa@$_GET[host]"):'Create user'),$i,array("privileges"=>array('','Privileges')));if($_POST){$K=$_POST;$cc=$cd;}else{$K=$_GET+array("host"=>$e->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)"));$K["pass"]=$jd;if($jd!=""){$K["hashed"]=true;}$cc[DB!=""&&!isset($_GET["host"])?idf_escape(addcslashes(DB,"%_")).".*":""]=array();}echo'
    + +
    Server +
    Username +
    Password +';if(!$K["hashed"]){echo'';}echo +checkbox("hashed",1,$K["hashed"],'Hashed',"typePassword(this.form['pass'], this.checked);"),'
    + +';echo"\n","\n";foreach(array(""=>"","Server Admin"=>'Server',"Databases"=>'Database',"Tables"=>'Table',"Columns"=>'Column',"Procedures"=>'Routine',)as$Ua=>$jb){foreach((array)$Xd[$Ua]as$Wd=>$Pa){echo"$jb'.h($Wd);$s=0;foreach($cc +as$gd=>$q){$D="'grants[$s][".h(strtoupper($Wd))."]'";$Y=$q[strtoupper($Wd)];if($Ua=="Server Admin"&&$gd!=(isset($cc["*.*"])?"*.*":"")){echo"
    ".'Privileges'."";$s=0;foreach($cc +as$gd=>$q){echo''.($gd!="*.*"?"":"*.*");$s++;}echo"
     ";}elseif(isset($_GET["grant"])){echo"";}else{echo"";}$s++;}}}echo"
    \n",'

    + +';if(isset($_GET["host"])){echo'';}echo' +

    +';}elseif(isset($_GET["processlist"])){if(support("kill")&&$_POST&&!$i){$yc=0;foreach((array)$_POST["kill"]as$X){if(queries("KILL ".(+$X))){$yc++;}}queries_redirect(ME."processlist=",lang(array('%d process has been killed.','%d processes have been killed.'),$yc),$yc||!$_POST["kill"]);}page_header('Process list',$i);echo' +
    + +';$s=-1;foreach(process_list()as$s=>$K){if(!$s){echo"".(support("kill")?"\n";}echo"".(support("kill")?"
     ":"")."".implode("",array_keys($K))."
    ".checkbox("kill[]",$K["Id"],0):"");foreach($K +as$y=>$X){echo"".(($x=="sql"?$y=="Info"&&$X!="":$y=="current_query"&&$X!="")?"".shorten_utf8($X,100,"").' '.'Edit'.'':nbsp($X));}echo"\n";}echo'
    + +

    +';if(support("kill")){echo($s+1)."/".sprintf('%d in total',$e->result("SELECT @@max_connections")),"

    \n";}echo' +

    +';}elseif(isset($_GET["select"])){$a=$_GET["select"];$T=table_status($a);$v=indexes($a);$k=fields($a);$m=column_foreign_keys($a);if($T["Oid"]=="t"){$v[]=array("type"=>"PRIMARY","columns"=>array("oid"));}parse_str($_COOKIE["adminer_import"],$la);$ne=array();$d=array();$bf=null;foreach($k +as$y=>$j){$D=$b->fieldName($j);if(isset($j["privileges"]["select"])&&$D!=""){$d[$y]=html_entity_decode(strip_tags($D));if(ereg('text|lob',$j["type"])){$bf=$b->selectLengthProcess();}}$ne+=$j["privileges"];}list($N,$r)=$b->selectColumnsProcess($d,$v);$Z=$b->selectSearchProcess($k,$v);$td=$b->selectOrderProcess($k,$v);$z=$b->selectLimitProcess();$ac=($N?implode(", ",$N):($T["Oid"]=="t"?"oid, ":"")."*")."\nFROM ".table($a);$dc=($r&&count($r)$K){echo$e->result("SELECT".limit(idf_escape(key($K))." FROM ".table($a)," WHERE ".where_check($wf).($Z?" AND ".implode(" AND ",$Z):"").($td?" ORDER BY ".implode(", ",$td):""),1));}exit;}if($_POST&&!$i){$Kf="(".implode(") OR (",array_map('where_check',(array)$_POST["check"])).")";$Td=$yf=null;foreach($v +as$u){if($u["type"]=="PRIMARY"){$Td=array_flip($u["columns"]);$yf=($N?$Td:array());break;}}foreach((array)$yf +as$y=>$X){if(in_array(idf_escape($y),$N)){unset($yf[$y]);}}if($_POST["export"]){cookie("adminer_import","output=".urlencode($_POST["output"])."&format=".urlencode($_POST["format"]));dump_headers($a);$b->dumpTable($a,"");if(!is_array($_POST["check"])||$yf===array()){$Jf=$Z;if(is_array($_POST["check"])){$Jf[]="($Kf)";}$H="SELECT $ac".($Jf?"\nWHERE ".implode(" AND ",$Jf):"").$dc;}else{$uf=array();foreach($_POST["check"]as$X){$uf[]="(SELECT".limit($ac,"\nWHERE ".($Z?implode(" AND ",$Z)." AND ":"").where_check($X).$dc,1).")";}$H=implode(" UNION ALL ",$uf);}$b->dumpData($a,"table",$H);exit;}if(!$b->selectEmailProcess($Z,$m)){if($_POST["save"]||$_POST["delete"]){$I=true;$ma=0;$H=table($a);$P=array();if(!$_POST["delete"]){foreach($d +as$D=>$X){$X=process_input($k[$D]);if($X!==null){if($_POST["clone"]){$P[idf_escape($D)]=($X!==false?$X:idf_escape($D));}elseif($X!==false){$P[]=idf_escape($D)." = $X";}}}$H.=($_POST["clone"]?" (".implode(", ",array_keys($P)).")\nSELECT ".implode(", ",$P)."\nFROM ".table($a):" SET\n".implode(",\n",$P));}if($_POST["delete"]||$P){$Na="UPDATE";if($_POST["delete"]){$Na="DELETE";$H="FROM $H";}if($_POST["clone"]){$Na="INSERT";$H="INTO $H";}if($_POST["all"]||($yf===array()&&$_POST["check"])||count($r)affected_rows;}else{foreach((array)$_POST["check"]as$X){$I=queries($Na.limit1($H,"\nWHERE ".where_check($X)));if(!$I){break;}$ma+=$e->affected_rows;}}}queries_redirect(remove_from_uri("page"),lang(array('%d item has been affected.','%d items have been affected.'),$ma),$I);}elseif(!$_POST["import"]){if(!$_POST["val"]){$i='Double click on a value to modify it.';}else{$I=true;$ma=0;foreach($_POST["val"]as$wf=>$K){$P=array();foreach($K +as$y=>$X){$y=bracket_escape($y,1);$P[]=idf_escape($y)." = ".(ereg('char|text',$k[$y]["type"])||$X!=""?$b->processInput($k[$y],$X):"NULL");}$H=table($a)." SET ".implode(", ",$P);$Jf=" WHERE ".where_check($wf).($Z?" AND ".implode(" AND ",$Z):"");$I=queries("UPDATE".(count($r)affected_rows;}queries_redirect(remove_from_uri(),lang(array('%d item has been affected.','%d items have been affected.'),$ma),$I);}}elseif(is_string($Rb=get_file("csv_file",true))){cookie("adminer_import","output=".urlencode($la["output"])."&format=".urlencode($_POST["separator"]));$I=true;$La=array_keys($k);preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~',$Rb,$Lc);$ma=count($Lc[0]);begin();$ye=($_POST["separator"]=="csv"?",":($_POST["separator"]=="tsv"?"\t":";"));foreach($Lc[0]as$y=>$X){preg_match_all("~((\"[^\"]*\")+|[^$ye]*)$ye~",$X.$ye,$Mc);if(!$y&&!array_diff($Mc[1],$La)){$La=$Mc[1];$ma--;}else{$P=array();foreach($Mc[1]as$s=>$Ia){$P[idf_escape($La[$s])]=($Ia==""&&$k[$La[$s]]["null"]?"NULL":q(str_replace('""','"',preg_replace('~^"|"$~','',$Ia))));}$I=insert_update($a,$P,$Td);if(!$I){break;}}}if($I){queries("COMMIT");}queries_redirect(remove_from_uri("page"),lang(array('%d row has been imported.','%d rows have been imported.'),$ma),$I);queries("ROLLBACK");}else{$i=upload_error($Rb);}}}$Re=$b->tableName($T);page_header('Select'.": $Re",$i);session_write_close();$P=null;if(isset($ne["insert"])){$P="";foreach((array)$_GET["where"]as$X){if(count($m[$X["col"]])==1&&($X["op"]=="="||(!$X["op"]&&!ereg('[_%]',$X["val"])))){$P.="&set".urlencode("[".bracket_escape($X["col"])."]")."=".urlencode($X["val"]);}}}$b->selectLinks($T,$P);if(!$d){echo"

    ".'Unable to select the table'.($k?".":": ".error())."\n";}else{echo"

    \n","
    ";hidden_fields_get();echo(DB!=""?''.(isset($_GET["ns"])?'':""):"");echo'',"
    \n";$b->selectColumnsPrint($N,$d);$b->selectSearchPrint($Z,$d,$v);$b->selectOrderPrint($td,$d,$v);$b->selectLimitPrint($z);$b->selectLengthPrint($bf);$b->selectActionPrint();echo"
    \n";$E=$_GET["page"];if($E=="last"){$Yb=$e->result("SELECT COUNT(*) FROM ".table($a).($Z?" WHERE ".implode(" AND ",$Z):""));$E=floor(max(0,$Yb-1)/$z);}$H="SELECT".limit((+$z&&$r&&count($r)selectQuery($H);$I=$e->query($H);if(!$I){echo"

    ".error()."\n";}else{if($x=="mssql"){$I->seek($z*$E);}$yb=array();echo"

    \n";$L=array();while($K=$I->fetch_assoc()){if($E&&$x=="oracle"){unset($K["RNUM"]);}$L[]=$K;}if($_GET["page"]!="last"){$Yb=(+$z&&$r&&count($r)result(" SELECT FOUND_ROWS()"):$e->result("SELECT COUNT(*) FROM ($H) x")):count($L));}if(!$L){echo"

    ".'No rows.'."\n";}else{$ya=$b->backwardKeys($a,$Re);echo"\n","".(!$r&&$N?"":"\n";foreach($b->rowDescriptions($L,$m)as$C=>$K){$vf=unique_array($L[$C],$v);$wf="";foreach($vf +as$y=>$X){$wf.="&".(isset($X)?urlencode("where[".bracket_escape($y)."]")."=".urlencode($X):"null%5B%5D=".urlencode($y));}echo"".(!$r&&$N?"":"\n";}echo"
    ".'edit'."");$bd=array();$p=array();reset($N);$ce=1;foreach($L[0]as$y=>$X){if($T["Oid"]!="t"||$y!="oid"){$X=$_GET["columns"][key($N)];$j=$k[$N?($X?$X["col"]:current($N)):$y];$D=($j?$b->fieldName($j,$ce):"*");if($D!=""){$ce++;$bd[$y]=$D;$Ma=idf_escape($y);echo''.(!$N||$X?apply_sql_function($X["fun"],$D):h(current($N)))."";}$p[$y]=$X["fun"];next($N);}}$Hc=array();if($_GET["modify"]){foreach($L +as$K){foreach($K +as$y=>$X){$Hc[$y]=max($Hc[$y],min(40,strlen(utf8_decode($X))));}}}echo($ya?"".'Relations':"")."
    ".checkbox("check[]",substr($wf,1),in_array(substr($wf,1),(array)$_POST["check"]),"","this.form['all'].checked = false; formUncheck('all-page');").(count($r)".'edit'.""));foreach($K +as$y=>$X){if(isset($bd[$y])){$j=$k[$y];if($X!=""&&(!isset($yb[$y])||$yb[$y]!="")){$yb[$y]=(is_mail($X)?$bd[$y]:"");}$_="";$X=$b->editVal($X,$j);if(!isset($X)){$X="NULL";}else{if(ereg('blob|bytea|raw|file',$j["type"])&&$X!=""){$_=h(ME.'download='.urlencode($a).'&field='.urlencode($y).$wf);}if($X===""){$X=" ";}elseif($bf!=""&&ereg('text|blob',$j["type"])&&is_utf8($X)){$X=shorten_utf8($X,max(0,+$bf));}else{$X=h($X);}if(!$_){foreach((array)$m[$y]as$l){if(count($m[$y])==1||end($l["source"])==$y){$_="";foreach($l["source"]as$s=>$Be){$_.=where_link($s,$l["target"][$s],$L[$C][$Be]);}$_=h(($l["db"]!=""?preg_replace('~([?&]db=)[^&]+~','\\1'.urlencode($l["db"]),ME):ME).'select='.urlencode($l["table"]).$_);if(count($l["source"])==1){break;}}}}if($y=="COUNT(*)"){$_=h(ME."select=".urlencode($a));$s=0;foreach((array)$_GET["where"]as$W){if(!array_key_exists($W["col"],$vf)){$_.=h(where_link($s++,$W["col"],$W["val"],$W["op"]));}}foreach($vf +as$xc=>$W){$_.=h(where_link($s++,$xc,$W));}}}if(!$_){if(is_mail($X)){$_="mailto:$X";}if($ae=is_url($K[$y])){$_=($ae=="http"&&$ba?$K[$y]:"$ae://www.adminer.org/redirect/?url=".urlencode($K[$y]));}}$t=h("val[$wf][".bracket_escape($y)."]");$Y=$_POST["val"][$wf][bracket_escape($y)];$fc=h(isset($Y)?$Y:$K[$y]);$Kc=strpos($X,"...");$vb=is_utf8($X)&&$L[$C][$y]==$K[$y]&&!$p[$y];$af=ereg('text|lob',$j["type"]);echo(($_GET["modify"]&&$vb)||isset($Y)?"".($af?"":""):"".$b->selectVal($X,$_,$j));}}if($ya){echo"";}$b->backwardKeysPrint($ya,$L[$C]);echo"
    \n",(!$r&&$N?"":"\n");}if($L||$E){$Gb=true;if($_GET["page"]!="last"&&+$z&&count($r)>=count($N)&&($Yb>=$z||$E)){$Yb=found_rows($T,$Z);if($Ybresult("SELECT COUNT(*) FROM ".table($a).($Z?" WHERE ".implode(" AND ",$Z):""));}else{$Gb=false;}}echo"

    ";if(+$z&&$Yb>$z){$Oc=floor(($Yb-1)/$z);echo'".'Page'.":",pagination(0,$E).($E>5?" ...":"");for($s=max(1,$E-4);$s'.'last'."");}echo" (".($Gb?"":"~ ").lang(array('%d row','%d rows'),$Yb).") ".checkbox("all",1,0,'whole result')."\n";if($b->selectCommandPrint()){echo'

    Edit
    +> + + + +
    +';}print_fieldset("export",'Export');$Ad=$b->dumpOutput();echo($Ad?html_select("output",$Ad,$la["output"])." ":""),html_select("format",$b->dumpFormat(),$la["format"])," \n","\n";}if($b->selectImportPrint()){print_fieldset("import",'Import',!$L);echo" ",html_select("separator",array("csv"=>"CSV,","csv;"=>"CSV;","tsv"=>"TSV"),$la["format"],1);echo" ","\n","\n";}$b->selectEmailPrint(array_filter($yb,'strlen'),$d);echo"\n";}}}elseif(isset($_GET["variables"])){$Fe=isset($_GET["status"]);page_header($Fe?'Status':'Variables');$Ef=($Fe?show_status():show_variables());if(!$Ef){echo"

    ".'No rows.'."\n";}else{echo"\n";foreach($Ef +as$y=>$X){echo"","
    ".h($y)."","".nbsp($X);}echo"
    \n";}}elseif(isset($_GET["script"])){header("Content-Type: text/javascript; charset=utf-8");if($_GET["script"]=="db"){$Oe=array("Data_length"=>0,"Index_length"=>0,"Data_free"=>0);foreach(table_status()as$T){$t=js_escape($T["Name"]);json_row("Comment-$t",nbsp($T["Comment"]));if(!is_view($T)){foreach(array("Engine","Collation")as$y){json_row("$y-$t",nbsp($T[$y]));}foreach($Oe+array("Auto_increment"=>0,"Rows"=>0)as$y=>$X){if($T[$y]!=""){$X=number_format($T[$y],0,'.',',');json_row("$y-$t",($y=="Rows"&&$T["Engine"]=="InnoDB"&&$X?"~ $X":$X));if(isset($Oe[$y])){$Oe[$y]+=($T["Engine"]!="InnoDB"||$y!="Data_free"?$T[$y]:0);}}elseif(array_key_exists($y,$T)){json_row("$y-$t");}}}}foreach($Oe +as$y=>$X){json_row("sum-$y",number_format($X,0,'.',','));}json_row("");}else{foreach(count_tables(get_databases())as$h=>$X){json_row("tables-".js_escape($h),$X);}json_row("");}exit;}else{$Xe=array_merge((array)$_POST["tables"],(array)$_POST["views"]);if($Xe&&!$i&&!$_POST["search"]){$I=true;$Sc="";if($x=="sql"&&count($_POST["tables"])>1&&($_POST["drop"]||$_POST["truncate"]||$_POST["copy"])){queries("SET foreign_key_checks = 0");}if($_POST["truncate"]){if($_POST["tables"]){$I=truncate_tables($_POST["tables"]);}$Sc='Tables have been truncated.';}elseif($_POST["move"]){$I=move_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$Sc='Tables have been moved.';}elseif($_POST["copy"]){$I=copy_tables((array)$_POST["tables"],(array)$_POST["views"],$_POST["target"]);$Sc='Tables have been copied.';}elseif($_POST["drop"]){if($_POST["views"]){$I=drop_views($_POST["views"]);}if($I&&$_POST["tables"]){$I=drop_tables($_POST["tables"]);}$Sc='Tables have been dropped.';}elseif($_POST["tables"]&&($I=queries(($_POST["optimize"]?"OPTIMIZE":($_POST["check"]?"CHECK":($_POST["repair"]?"REPAIR":"ANALYZE")))." TABLE ".implode(", ",array_map('idf_escape',$_POST["tables"]))))){while($K=$I->fetch_assoc()){$Sc.="".h($K["Table"]).": ".h($K["Msg_text"])."
    ";}}queries_redirect(substr(ME,0,-1),$Sc,$I);}page_header(($_GET["ns"]==""?'Database'.": ".h(DB):'Schema'.": ".h($_GET["ns"])),$i,true);if($b->homepage()){if($_GET["ns"]!==""){echo"

    ".'Tables and views'."

    \n";$We=tables_list();if(!$We){echo"

    ".'No tables.'."\n";}else{echo"

    \n","

    ".'Search data in tables'.": \n";if($_POST["search"]&&$_POST["query"]!=""){search_tables();}echo"\n",'\n";foreach($We +as$D=>$V){$Ff=(isset($V)&&!eregi("table",$V));echo'
    ',''.'Table',''.'Engine',''.'Collation',''.'Data Length',''.'Index Length',''.'Data Free',''.'Auto Increment',''.'Rows',(support("comment")?''.'Comment':''),"
    '.checkbox(($Ff?"views[]":"tables[]"),$D,in_array($D,$Xe,true),"","formUncheck('check-all');"),''.h($D).'';if($Ff){echo''.'View'.'','?';}else{foreach(array("Engine"=>array(),"Collation"=>array(),"Data_length"=>array("create",'Alter table'),"Index_length"=>array("indexes",'Alter indexes'),"Data_free"=>array("edit",'New item'),"Auto_increment"=>array("auto_increment=1&create",'Alter table'),"Rows"=>array("select",'Select data'),)as$y=>$_){echo($_?"?":" ");}}echo(support("comment")?" ":"");}echo"
     ".sprintf('%d in total',count($We)),"".nbsp($x=="sql"?$e->result("SELECT @@storage_engine"):""),"".nbsp(db_collation(DB,collations()));foreach(array("Data_length","Index_length","Data_free")as$y){echo" ";}echo"
    \n","\n";if(!information_schema(DB)){echo"

    ".($x=="sql"?" ":"")." \n";$g=(support("scheme")?schemas():get_databases());if(count($g)!=1&&$x!="sqlite"){$h=(isset($_POST["target"])?$_POST["target"]:(support("scheme")?$_GET["ns"]:DB));echo"

    ".'Move to other database'.": ",($g?html_select("target",$g,$h):'')," ",(support("copy")?" ":""),"\n";}echo"\n";}echo"

    \n";}echo'

    '.'Create table'."\n";if(support("view")){echo''.'Create view'."\n";}if(support("routine")){echo"

    ".'Routines'."

    \n";$re=routines();if($re){echo"\n",'\n";odd('');foreach($re +as$K){echo'','
    '.'Name'.''.'Type'.''.'Return type'." 
    '.h($K["ROUTINE_NAME"]).'',''.h($K["ROUTINE_TYPE"]),''.h($K["DTD_IDENTIFIER"]),''.'Alter'."";}echo"
    \n";}echo'

    '.(support("procedure")?''.'Create procedure'.' ':'').''.'Create function'."\n";}if(support("event")){echo"

    ".'Events'."

    \n";$L=get_rows("SHOW EVENTS");if($L){echo"\n","\n";foreach($L +as$K){echo"",'
    ".'Name'."".'Schedule'."".'Start'."".'End'."
    '.h($K["Name"])."","".($K["Execute at"]?'At given time'."".$K["Execute at"]:'Every'." ".$K["Interval value"]." ".$K["Interval field"]."$K[Starts]"),"$K[Ends]";}echo"
    \n";}echo'

    '.'Create event'."\n";}if($We){echo"\n";}}}}page_footer(); \ No newline at end of file diff --git a/plugins/adminer/adminer.css b/plugins/adminer/adminer.css new file mode 100644 index 0000000..f00ae58 --- /dev/null +++ b/plugins/adminer/adminer.css @@ -0,0 +1,58 @@ +/* CSS by Brade - www.bradezone.com */ +*{margin:0;padding:0} +body{font:13px/18px Helvetica,Arial,sans-serif;background:#fff;color:#333} +/* generic */ +a,a:visited{color:#06c;text-decoration:none;border-bottom:1px dotted} +a:hover{border-bottom:1px solid #06c;background:#06c;color:#fff} +p{padding-bottom:4px;margin-bottom:4px} +h1{font-size:18px;font-weight:bold;padding-bottom:0px;height:40px;padding:0 0 8px 0;color:#666;border:0} +h2{font:32px Georgia,serif;padding:10px 0 8px;margin:0;background:transparent;border:0;color:#333} +h3{font-size:18px;font-weight:bold;padding:4px 0;margin:0} +form#form{overflow:hidden} +fieldset{float:left;min-height:48px;padding:0 4px 4px 4px;border:1px solid #ccc;margin-bottom:8px;margin-right:4px} +fieldset div{margin-top:4px} +input,select,textarea{font:13px Helvetica,Arial,sans-serif;color:#555;border:1px solid #999;padding:3px} +input[type=submit]{background:#ccc;padding:2px;cursor:pointer;color:#333} +input[type=submit]:hover{background:#bbb} +input[type=image],input[type=checkbox]{border:0;padding:0} +label input[type=checkbox],td input[type=radio],td span select{margin-right:4px} +select{border:1px solid #999;padding:2px} +fieldset select{margin-right:4px} +option{padding:0 5px} +optgroup{font-size:11px} +code{background:#eee;padding:2px 4px;font:16px/20px Courier,monospace} +code a:hover{background:transparent} +table{margin:4px 0 8px;border:1px solid #ccc;font-size:inherit} +tbody tr:hover td,tbody tr:hover th{background:#eee} +thead tr:hover td,thead tr:hover th{background:#ddd} +th,td{text-align:left;padding:2px 4px;vertical-align:top;font-weight:normal;border:1px dotted #ccc;border-width:0 0 0 1px; +margin:0;background:inherit} +thead th,thead td{white-space:nowrap;font-weight:bold;background:#ddd;border-color:#ddd} +th:first-child,td:first-child{border-color:transparent;white-space:nowrap} +td[align=right]{text-align:right} +table code{font-size:13px;line-height:18px} +.hidden{display:none} +.error,.message{padding:0;background:transparent;font-weight:bold} +.error{color:#c00} +.message{color:#090} +/* specific */ +#content{margin:0 0 0 320px;padding:50px 20px 40px 0;height:100%} +#content:after{content:'.';clear:both;height:0;overflow:hidden;display:block} +#lang{background:#333;color:#fff;position:fixed;top:0;left:0;width:100%;padding:0 20px 0 40px;line-height:40px;height:40px} +#lang select{border-color:#333} +#menu{background:#eee;position:fixed;top:60px;bottom:20px;overflow:auto;left:20px;width:240px;padding:10px 15px; +border:5px solid #ccc;margin:0} +#menu a{color:#333;margin-right:4px} +#menu a:hover{background:#333;color:#fff;border-color:#333} +#menu a.h1,#menu a.h1:hover{display:block;height:0;width:175px;padding:40px 0 0 0;overflow:hidden;float:left;border:0;margin:0; +outline:0;background:url(http://www.bradezone.com/random/adminer_logo.gif) no-repeat;line-height:32px} +#menu p{white-space:nowrap;border:0;padding:0 0 4px 0;margin:0 0 4px 0} +#breadcrumb{background:#333;color:#fff;position:fixed;top:0;left:320px;width:100%;line-height:40px;padding:0;z-index:1;margin:0} +#breadcrumb a{color:#ff9} +#breadcrumb a:hover{background:transparent;color:#ff9;border-color:#ff9} +#schema .table{padding:4px 8px;background:#f3f3f3} +/* IE hacks */ +*+html th:first-child,*+html td:first-child{border-color:inherit;white-space:inherit} +* html #lang,* html #menu,* html #breadcrumb{position:absolute} +* html #lang{padding-top:10px;height:30px} +* html form#form{height:100%} diff --git a/plugins/backupOpenFiles/index.php b/plugins/backupOpenFiles/index.php new file mode 100644 index 0000000..8fdf877 --- /dev/null +++ b/plugins/backupOpenFiles/index.php @@ -0,0 +1,78 @@ + + + +'.PHP_EOL; +for ($i=1;$i<=10;$i++) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; +} +echo ''.PHP_EOL; +?> + +open($zipName,$overwriteZip ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) { + return false; + } + + // Otherwise, we're OK to add our string into a new file (incl dirs) in the zip, so do that + for($i=1;$i<=10;$i++) { + $fName = 'fileName'.$i; + if($_POST[$fName]!=="") { + $zip->addFromString(ltrim($_POST[$fName],"/"), $_POST['fileContent'.$i]); + } + } + + $zip->close(); + + // We've been successful, so return with a positive response + return file_exists($zipName); + + } else { + // If we had 0 files, return + return false; + } + } +} + +// Trigger the class +$zipItDoZip = new zipIt(); +$zipItAddToZip = $zipItDoZip->zipFilesUp($zipItSaveLocation.$zipItFileName); +;}; +?> + + + \ No newline at end of file