index.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. <?php
  2. /*
  3. FusionPBX
  4. Version: MPL 1.1
  5. The contents of this file are subject to the Mozilla Public License Version
  6. 1.1 (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.mozilla.org/MPL/
  9. Software distributed under the License is distributed on an "AS IS" basis,
  10. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. for the specific language governing rights and limitations under the
  12. License.
  13. The Original Code is FusionPBX
  14. The Initial Developer of the Original Code is
  15. Mark J Crane <[email protected]>
  16. Portions created by the Initial Developer are Copyright (C) 2008-2024
  17. the Initial Developer. All Rights Reserved.
  18. Contributor(s):
  19. Mark J Crane <[email protected]>
  20. James Rose <[email protected]>
  21. */
  22. //includes files
  23. require_once dirname(__DIR__, 2) . "/resources/require.php";
  24. require_once "resources/check_auth.php";
  25. //check permissions
  26. if (permission_exists('edit_view')) {
  27. //access granted
  28. }
  29. else {
  30. echo "access denied";
  31. exit;
  32. }
  33. //add multi-lingual support
  34. $language = new text;
  35. $text = $language->get();
  36. //set the directory title and mode
  37. switch ($_GET["dir"]) {
  38. case 'xml':
  39. $title = 'XML';
  40. $mode = 'xml';
  41. $dir = 'xml';
  42. break;
  43. case 'provision':
  44. $title = 'Provision';
  45. $mode = 'xml';
  46. $dir = 'provision';
  47. break;
  48. case 'php':
  49. $title = 'PHP';
  50. $mode = 'php';
  51. $dir = 'php';
  52. break;
  53. case 'scripts':
  54. $title = 'Scripts';
  55. $mode = 'lua';
  56. $dir = 'scripts';
  57. break;
  58. case 'grammar':
  59. $title = 'Grammar';
  60. $mode = 'xml';
  61. $dir = 'grammar';
  62. break;
  63. default:
  64. $mode = 'text';
  65. $dir = '';
  66. }
  67. //save the sanitized value
  68. $_SESSION['app']['edit']['dir'] = $dir;
  69. //load editor preferences/defaults
  70. $setting_size = $settings->get('editor', 'font_size', '12px');
  71. $setting_theme = $settings->get('editor', 'theme', 'cobalt');
  72. $setting_invisibles = $settings->get('editor', 'invisibles','false');
  73. $setting_indenting = $settings->get('editor', 'indent_guides','false');
  74. $setting_numbering = $settings->get('editor', 'line_numbers','true');
  75. //get and then set the favicon
  76. $favicon = $settings->get('theme', 'favicon', PROJECT_ROOT .'/themes/default/favicon.ico');
  77. //create a token
  78. $key_name = '/app/edit/'.$mode;
  79. $_SESSION['keys'][$key_name] = bin2hex(random_bytes(32));
  80. $_SESSION['token'] = hash_hmac('sha256', $key_name, $_SESSION['keys'][$key_name]);
  81. //The buffer must be empty
  82. while(ob_get_level() > 0)
  83. ob_get_clean();
  84. ?><!doctype html>
  85. <html>
  86. <head>
  87. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  88. <title><?php echo $title; ?></title>
  89. <link rel="icon" type="image/x-icon" href="<?php echo $favicon; ?>">
  90. <link rel='stylesheet' type='text/css' href='<?php echo PROJECT_PATH; ?>/resources/fontawesome/css/all.min.css.php'>
  91. <script language="JavaScript" type="text/javascript" src="<?php echo PROJECT_PATH; ?>/resources/jquery/jquery-3.6.1.min.js"></script>
  92. <script language="JavaScript" type="text/javascript">
  93. function submit_check() {
  94. if (document.getElementById('filepath').value != '') {
  95. document.getElementById('editor_source').value = editor.getSession().getValue();
  96. return true;
  97. }
  98. focus_editor();
  99. return false;
  100. }
  101. function toggle_option(opt) {
  102. switch (opt) {
  103. case 'numbering': toggle_option_do('showLineNumbers'); toggle_option_do('fadeFoldWidgets'); break;
  104. case 'invisibles': toggle_option_do('showInvisibles'); break;
  105. case 'indenting': toggle_option_do('displayIndentGuides'); break;
  106. }
  107. focus_editor();
  108. }
  109. function toggle_option_do(opt_name) {
  110. var opt_val = editor.getOption(opt_name);
  111. editor.setOption(opt_name, ((opt_val) ? false : true));
  112. }
  113. function toggle_sidebar() {
  114. var td_sidebar = document.getElementById('sidebar');
  115. if (td_sidebar.style.display == '') {
  116. document.getElementById('td_save').style.paddingLeft = '12px';
  117. td_sidebar.style.display = 'none';
  118. }
  119. else {
  120. document.getElementById('td_save').style.paddingLeft = '0';
  121. td_sidebar.style.display = '';
  122. }
  123. focus_editor();
  124. }
  125. function insert_clip(before, after) {
  126. var selected_text = editor.session.getTextRange(editor.getSelectionRange());
  127. editor.insert(before + selected_text + after);
  128. focus_editor();
  129. }
  130. function focus_editor() {
  131. editor.focus();
  132. }
  133. function http_request(url, form_data) {
  134. var http = new XMLHttpRequest();
  135. http.open('POST', url, true);
  136. //http.onload = function(e) { ... };
  137. http.onload = function(e) {
  138. if (this.status == 200) {
  139. //data sent successfully
  140. alert(this.responseText);
  141. }
  142. else {
  143. alert('<?php echo $text['message-problem']; ?>');
  144. }
  145. };
  146. http.send(form_data);
  147. }
  148. function save() {
  149. var form_data = new FormData();
  150. form_data.append('filepath', document.getElementById('filepath').value);
  151. form_data.append('content', editor.getSession().getValue());
  152. form_data.append('token',document.getElementById('token').value);
  153. form_data.append('mode',"<?php echo $mode; ?>");
  154. http_request('file_save.php', form_data);
  155. }
  156. </script>
  157. <style>
  158. div#editor {
  159. box-shadow: 0 5px 15px #333;
  160. }
  161. i.ace_control {
  162. cursor: pointer;
  163. margin-right: 5px;
  164. opacity: 0.5;
  165. }
  166. i.ace_control:hover {
  167. opacity: 1.0;
  168. }
  169. </style>
  170. </head>
  171. <body style="padding: 0; margin: 0; overflow: hidden;">
  172. <div id="frame" style="display: flex; height: 100vh; width: 100vw;">
  173. <!-- Sidebar -->
  174. <div id="sidebar" style="width: 300px; height: 100%; display: flex; flex-direction: column;">
  175. <div id="file_list" style="border: none; height: 65%; width: 100%; overflow: auto;">
  176. Loading...
  177. </div>
  178. <div id="clip_list" style="border: none; border-top: 1px solid #ccc; height: calc(35% - 1px); width: 100%; overflow: auto;">
  179. Loading...
  180. </div>
  181. </div>
  182. <!-- Main Content -->
  183. <div id="ace_content" style="flex: 1; height: 100%; display: flex; flex-direction: column;">
  184. <!-- Editor Controls -->
  185. <form style="margin: 0;" name="frm_edit" id="frm_edit" method="post" action="file_save.php" onsubmit="return submit_check();">
  186. <textarea name="content" id="editor_source" style="display: none;"></textarea>
  187. <input type="hidden" name="filepath" id="filepath" value="">
  188. <input type="hidden" name="token" id="token" value="<?php echo $_SESSION['token']; ?>">
  189. <div id="editor-controls" style="display: flex; align-items: center; width: 100%; height: 30px;">
  190. <div id="td_save" style="display: inline-flex; align-items: center;">
  191. <i class="fas fa-save fa-lg ace_control" title="<?php echo $text['label-save_changes']; ?>" onclick="save();"></i>
  192. </div>
  193. <div style="flex: 1; padding: 0 15px 0 18px;">
  194. <input id="current_file" type="text" style="height: 23px; width: 100%;">
  195. </div>
  196. <div style="width: 1px; height: 40px;"></div>
  197. <div style="padding-left: 6px;">
  198. <i class="fas fa-window-maximize fa-lg fa-rotate-270 ace_control" title="<?php echo $text['label-toggle_side_bar']; ?>" onclick="toggle_sidebar();"></i>
  199. </div>
  200. <div style="padding-left: 6px;">
  201. <i class="fas fa-list-ul fa-lg ace_control" title="<?php echo $text['label-toggle_line_numbers']; ?>" onclick="toggle_option('numbering');"></i>
  202. </div>
  203. <div style="padding-left: 6px;">
  204. <i class="fas fa-eye-slash fa-lg ace_control" title="<?php echo $text['label-toggle_invisibles']; ?>" onclick="toggle_option('invisibles');"></i>
  205. </div>
  206. <div style="padding-left: 6px;">
  207. <i class="fas fa-indent fa-lg ace_control" title="<?php echo $text['label-toggle_indent_guides']; ?>" onclick="toggle_option('indenting');"></i>
  208. </div>
  209. <div style="padding-left: 6px;">
  210. <i class="fas fa-search fa-lg ace_control" title="<?php echo $text['label-find_replace']; ?>" onclick="editor.execCommand('replace');"></i>
  211. </div>
  212. <div style="padding-left: 6px;">
  213. <i class="fas fa-chevron-down fa-lg ace_control" title="<?php echo $text['label-go_to_line']; ?>" onclick="editor.execCommand('gotoline');"></i>
  214. </div>
  215. <div style="padding-left: 15px;">
  216. <select id="mode" style="height: 23px; max-width: 70px;" onchange="editor.getSession().setMode('ace/mode/' + this.options[this.selectedIndex].value); focus_editor();">
  217. <?php
  218. $modes['php'] = 'PHP';
  219. $modes['css'] = 'CSS';
  220. $modes['html'] = 'HTML';
  221. $modes['javascript'] = 'JS';
  222. $modes['json'] = 'JSON';
  223. $modes['ini'] = 'Conf';
  224. $modes['lua'] = 'Lua';
  225. $modes['text'] = 'Text';
  226. $modes['xml'] = 'XML';
  227. $modes['sql'] = 'SQL';
  228. $modes['sh'] = 'SH';
  229. $modes['smarty'] = 'Smarty';
  230. $modes['svg'] = 'SVG';
  231. $modes['makefile'] = 'Makefile';
  232. $modes['c_cpp'] = 'C';
  233. $modes['c_cpp'] = 'CPP';
  234. $modes['pgsql'] = 'PGSQL';
  235. foreach ($modes as $value => $label) {
  236. $selected = ($value == $mode) ? 'selected' : null;
  237. echo "<option value='".$value."' ".$selected.">".$label."</option>\n";
  238. }
  239. ?>
  240. </select>
  241. </div>
  242. <div style="padding-left: 4px;">
  243. <select id="size" style="height: 23px;" onchange="document.getElementById('editor').style.fontSize = this.options[this.selectedIndex].value; focus_editor();">
  244. <?php
  245. $sizes = explode(',','9px,10px,11px,12px,14px,16px,18px,20px');
  246. if (!in_array($setting_size, $sizes)) {
  247. echo "<option value='".$setting_size."'>".$setting_size."</option>\n";
  248. echo "<option value='' disabled='disabled'></option>\n";
  249. }
  250. foreach ($sizes as $size) {
  251. $selected = ($size == $setting_size) ? 'selected' : null;
  252. echo "<option value='".$size."' ".$selected.">".$size."</option>\n";
  253. }
  254. ?>
  255. </select>
  256. </div>
  257. <div style="padding-left: 4px; padding-right: 4px;">
  258. <select id="theme" style="height: 23px; max-width: 100px;" onchange="editor.setTheme('ace/theme/' + this.options[this.selectedIndex].value); focus_editor();">
  259. <?php
  260. $themes['Bright']['chrome']= 'Chrome';
  261. $themes['Bright']['clouds']= 'Clouds';
  262. $themes['Bright']['crimson_editor']= 'Crimson Editor';
  263. $themes['Bright']['dawn']= 'Dawn';
  264. $themes['Bright']['dreamweaver']= 'Dreamweaver';
  265. $themes['Bright']['eclipse']= 'Eclipse';
  266. $themes['Bright']['github']= 'GitHub';
  267. $themes['Bright']['iplastic']= 'IPlastic';
  268. $themes['Bright']['solarized_light']= 'Solarized Light';
  269. $themes['Bright']['textmate']= 'TextMate';
  270. $themes['Bright']['tomorrow']= 'Tomorrow';
  271. $themes['Bright']['xcode']= 'XCode';
  272. $themes['Bright']['kuroir']= 'Kuroir';
  273. $themes['Bright']['katzenmilch']= 'KatzenMilch';
  274. $themes['Bright']['sqlserver']= 'SQL Server';
  275. $themes['Dark']['ambiance']= 'Ambiance';
  276. $themes['Dark']['chaos']= 'Chaos';
  277. $themes['Dark']['clouds_midnight']= 'Clouds Midnight';
  278. $themes['Dark']['cobalt']= 'Cobalt';
  279. $themes['Dark']['idle_fingers']= 'idle Fingers';
  280. $themes['Dark']['kr_theme']= 'krTheme';
  281. $themes['Dark']['merbivore']= 'Merbivore';
  282. $themes['Dark']['merbivore_soft']= 'Merbivore Soft';
  283. $themes['Dark']['mono_industrial']= 'Mono Industrial';
  284. $themes['Dark']['monokai']= 'Monokai';
  285. $themes['Dark']['pastel_on_dark']= 'Pastel on dark';
  286. $themes['Dark']['solarized_dark']= 'Solarized Dark';
  287. $themes['Dark']['terminal']= 'Terminal';
  288. $themes['Dark']['tomorrow_night']= 'Tomorrow Night';
  289. $themes['Dark']['tomorrow_night_blue']= 'Tomorrow Night Blue';
  290. $themes['Dark']['tomorrow_night_bright']= 'Tomorrow Night Bright';
  291. $themes['Dark']['tomorrow_night_eighties']= 'Tomorrow Night 80s';
  292. $themes['Dark']['twilight']= 'Twilight';
  293. $themes['Dark']['vibrant_ink']= 'Vibrant Ink';
  294. foreach ($themes as $optgroup => $theme) {
  295. echo "<optgroup label='".$optgroup."'>\n";
  296. foreach ($theme as $value => $label) {
  297. $selected = (strtolower($label) == strtolower($setting_theme)) ? 'selected' : null;
  298. echo "<option value='".$value."' ".$selected.">".$label."</option>\n";
  299. }
  300. echo "</optgroup>\n";
  301. }
  302. ?>
  303. </select>
  304. </div>
  305. </div>
  306. </form>
  307. <!-- Editor -->
  308. <div id="editor" style="text-align: left; width: 100%; height: calc(100% - 30px); font-size: 12px;"></div>
  309. </div>
  310. </div>
  311. <script src="<?php echo PROJECT_PATH; ?>/resources/ace/ace.js" charset="utf-8"></script>
  312. <script src="<?php echo PROJECT_PATH; ?>/resources/ace/ext-inline_autocomplete.js"></script>
  313. <script>
  314. // Load ACE extensions
  315. ace.require("ace/ext/language_tools");
  316. // Initialize ACE Editor
  317. var editor = ace.edit("editor");
  318. editor.setOptions({
  319. mode: 'ace/mode/<?=$mode?>',
  320. theme: 'ace/theme/'+document.getElementById('theme').options[document.getElementById('theme').selectedIndex].value,
  321. selectionStyle: 'text',
  322. cursorStyle: 'smooth',
  323. showInvisibles: <?=$setting_invisibles?>,
  324. displayIndentGuides: <?=$setting_indenting?>,
  325. showLineNumbers: <?=$setting_numbering?>,
  326. showGutter: true,
  327. scrollPastEnd: true,
  328. fadeFoldWidgets: <?=$setting_numbering?>,
  329. showPrintMargin: false,
  330. highlightGutterLine: false,
  331. useSoftTabs: false,
  332. enableBasicAutocompletion: true,
  333. enableLiveAutocompletion: <?php echo ($mode === 'php') ? 'true' : 'false'; ?>,
  334. enableSnippets: <?php echo 'true' ?>
  335. });
  336. // Prevent form submission with Enter key
  337. <?php key_press('enter', 'down', '#current_file', null, null, 'return false;', false); ?>
  338. // Save file with Ctrl+S
  339. <?php key_press('ctrl+s', 'down', 'window', null, null, "save(); return false;", false); ?>
  340. // Open file manager/clip library pane with Ctrl+Q
  341. <?php key_press('ctrl+q', 'down', 'window', null, null, 'toggle_sidebar(); focus_editor(); return false;', false); ?>
  342. // Remove unwanted shortcuts
  343. editor.commands.bindKey("Ctrl-T", null); // Disable new browser tab shortcut
  344. // Levenshtein distance algorithm
  345. function levenshteinDistance(a, b) {
  346. let m = a.length, n = b.length;
  347. let dp = [];
  348. for (let i = 0; i <= m; i++) {
  349. dp[i] = [i];
  350. }
  351. for (let j = 0; j <= n; j++) {
  352. dp[0][j] = j;
  353. }
  354. for (let i = 1; i <= m; i++) {
  355. for (let j = 1; j <= n; j++) {
  356. if (a[i - 1] === b[j - 1]) {
  357. dp[i][j] = dp[i - 1][j - 1];
  358. } else {
  359. dp[i][j] = Math.min(
  360. dp[i - 1][j] + 1, // deletion
  361. dp[i][j - 1] + 1, // insertion
  362. dp[i - 1][j - 1] + 1 // substitution
  363. );
  364. }
  365. }
  366. }
  367. return dp[m][n];
  368. }
  369. // Example function to find the closest matching class key
  370. function findClosestMatch(refName, phpMethods) {
  371. let bestMatch = null;
  372. let bestDistance = Infinity;
  373. let lowerRef = refName.toLowerCase();
  374. // Loop through all classes in phpMethods
  375. for (let key in phpMethods) {
  376. // Assume the simple class name is the last segment after a backslash
  377. let parts = key.split("\\");
  378. let simpleName = parts[parts.length - 1].toLowerCase();
  379. let distance = levenshteinDistance(lowerRef, simpleName);
  380. if (distance < bestDistance) {
  381. bestDistance = distance;
  382. bestMatch = key;
  383. }
  384. }
  385. return bestMatch;
  386. }
  387. // Function to fetch PHP class methods using fetch() with promises
  388. async function fetch_php_methods() {
  389. try {
  390. let response = await fetch('/app/edit/resources/get_php_methods.php');
  391. if (!response.ok) throw new Error("Failed to load PHP methods.");
  392. return await response.json();
  393. } catch (error) {
  394. console.error("Error fetching PHP methods:", error);
  395. return {}; // Return empty object on failure
  396. }
  397. }
  398. // Initialize ACE auto-completion after fetching PHP methods
  399. async function init_ace_completion() {
  400. const php_methods = await fetch_php_methods();
  401. // Custom completer for PHP class methods
  402. var php_class_completer = {
  403. getCompletions: function(editor, session, pos, prefix, callback) {
  404. // Define current_class_name by extracting the basename of the current file without extension.
  405. var current_file_path = document.getElementById('current_file').value;
  406. var current_file_name = current_file_path.split('/').pop();
  407. // Remove the extension (everything after the last dot)
  408. var current_class_name = current_file_name.replace(/\.[^/.]+$/, "");
  409. // Get the current line text
  410. var line = session.getLine(pos.row);
  411. // Use regex to detect object (->) or static (::) access.
  412. // This regex captures either "$this" or any other word.
  413. const object_match = line.match(/(\$this|\w+)\s*->\s*\w*$/);
  414. const static_match = line.match(/(self|static|\w+)::\w*$/);
  415. // Extract the referenced name; if it's "$this", use the current_class_name.
  416. var ref_name = object_match ? object_match[1] : (static_match ? static_match[1] : null);
  417. if (ref_name === '$this' | ref_name === 'self' | ref_name === 'static') {
  418. ref_name = current_class_name;
  419. }
  420. // If not a class, maybe a user function; use the prefix.
  421. if (prefix.length > 0) ref_name = prefix;
  422. if (!ref_name) return callback(null, []);
  423. // Find the closest matching class using fuzzy matching.
  424. var matched_class = findClosestMatch(ref_name, php_methods);
  425. if (!matched_class) return callback(null, []);
  426. // Map the methods of the matched class into completions.
  427. var completions = php_methods[matched_class].map(function(method) {
  428. // If static syntax is used but the method is not static, skip it.
  429. if (static_match !== null && !method.static) {
  430. return {};
  431. }
  432. // Map the item to the documentation
  433. var item = {
  434. caption: method.name + method.params,
  435. snippet: method.name + method.params.replace(/\$/g, "\\$"),
  436. meta: method.meta,
  437. docHTML: method.doc ? method.doc : "No Documentation"
  438. };
  439. // TODO: fix italics
  440. // Use italics in pop-up for static methods
  441. if (method.static) {
  442. item.className = "ace_static_method";
  443. }
  444. //return the mapped json object
  445. return item;
  446. });
  447. callback(null, completions);
  448. }
  449. };
  450. // Initialize ACE Editor
  451. ace.require("ace/ext/language_tools");
  452. // Replace the current list of completions with our custom one so we don't have every single word in the document listed as a completion option
  453. editor.completers = [php_class_completer];
  454. // Ensure font size is set
  455. document.getElementById('editor').style.fontSize = '<?=$setting_size?>';
  456. focus_editor();
  457. }
  458. if (<?php echo ($mode === 'php') ? 'true' : 'false'; ?>) {
  459. // Run auto-completion setup
  460. init_ace_completion();
  461. }
  462. </script>
  463. </body>
  464. <script>
  465. fetch('clip_list.php')
  466. .then(response => {
  467. if (!response.ok) {
  468. throw new Error('Network response was not ok');
  469. }
  470. return response.text();
  471. })
  472. .then(html => {
  473. document.getElementById('clip_list').innerHTML = html;
  474. })
  475. .catch(error => {
  476. console.error('Error fetching clip_list:', error);
  477. });
  478. async function loadFileList() {
  479. try {
  480. const response = await fetch('file_list.php');
  481. if (!response.ok) {
  482. throw new Error('Network response not okay');
  483. }
  484. const html = await response.text();
  485. document.getElementById('file_list').innerHTML = html;
  486. } catch (error) {
  487. console.error('Error fetching files:', error);
  488. }
  489. }
  490. function makeRequest(url, strpost) {
  491. var http_request = false;
  492. if (window.XMLHttpRequest) { // Mozilla, Safari, ...
  493. http_request = new XMLHttpRequest();
  494. if (http_request.overrideMimeType) {
  495. http_request.overrideMimeType('text/xml');
  496. // See note below about this line
  497. }
  498. } else if (window.ActiveXObject) { // IE
  499. try {
  500. http_request = new ActiveXObject("Msxml2.XMLHTTP");
  501. } catch (e) {
  502. try {
  503. http_request = new ActiveXObject("Microsoft.XMLHTTP");
  504. } catch (e) {}
  505. }
  506. }
  507. if (!http_request) {
  508. alert('<?=$text['message-give-up']?>');
  509. return false;
  510. }
  511. http_request.onreadystatechange = function() { returnContent(http_request); };
  512. if (http_request.overrideMimeType) {
  513. http_request.overrideMimeType('text/html');
  514. }
  515. http_request.open('POST', url, true);
  516. if (strpost.length == 0) {
  517. //http_request.send(null);
  518. http_request.send('name=value&foo=bar');
  519. }
  520. else {
  521. http_request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  522. http_request.send(strpost);
  523. }
  524. }
  525. function returnContent(http_request) {
  526. if (http_request.readyState === 4) {
  527. if (http_request.status === 200) {
  528. document.getElementById('editor_source').value=http_request.responseText;
  529. editor.getSession().setValue(document.getElementById('editor_source').value);
  530. editor.gotoLine(1);
  531. editor.scrollToLine(1, true, true, function() {});
  532. editor.focus();
  533. }
  534. else {
  535. alert('<?=$text['message-problem']?>');
  536. }
  537. }
  538. }
  539. // ---------------------------------------------
  540. // --- http://www.codeproject.com/jscript/dhtml_treeview.asp
  541. // --- Name: Easy DHTML Treeview --
  542. // --- Author: D.D. de Kerf --
  543. // --- Version: 0.2 Date: 13-6-2001 --
  544. // ---------------------------------------------
  545. function Toggle(node) {
  546. // Unfold the branch if it isn't visible
  547. if (node.nextSibling.style.display == 'none') {
  548. node.nextSibling.style.display = 'block';
  549. }
  550. // Collapse the branch if it IS visible
  551. else {
  552. node.nextSibling.style.display = 'none';
  553. }
  554. }
  555. // Load files from server
  556. loadFileList();
  557. </script>
  558. </html>