Project

General

Profile

Download (10.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * diag_edit.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

    
22
##|+PRIV
23
##|*IDENT=page-diagnostics-edit
24
##|*NAME=Diagnostics: Edit File
25
##|*DESCR=Allow access to the 'Diagnostics: Edit File' page.
26
##|*WARN=standard-warning-root
27
##|*MATCH=diag_edit.php*
28
##|*MATCH=browser.php*
29
##|*MATCH=vendor/filebrowser/browser.php*
30
##|-PRIV
31

    
32
$pgtitle = array(gettext("Diagnostics"), gettext("Edit File"));
33
require_once("guiconfig.inc");
34

    
35
if ($_POST['action']) {
36
	switch ($_POST['action']) {
37
		case 'load':
38
			if (strlen($_POST['file']) < 1) {
39
				print('|5|');
40
				print_info_box(gettext("No file name specified."), 'danger');
41
				print('|');
42
			} elseif (is_dir($_POST['file'])) {
43
				print('|4|');
44
				print_info_box(gettext("Loading a directory is not supported."), 'danger');
45
				print('|');
46
			} elseif (!is_file($_POST['file'])) {
47
				print('|3|');
48
				print_info_box(gettext("File does not exist or is not a regular file."), 'danger');
49
				print('|');
50
			} else {
51
				$data = file_get_contents(urldecode($_POST['file']));
52
				if ($data === false) {
53
					print('|1|');
54
					print_info_box(gettext("Failed to read file."), 'danger');
55
					print('|');
56
				} else {
57
					$data = base64_encode($data);
58
					print("|0|{$_POST['file']}|{$data}|");
59
				}
60
			}
61
			exit;
62

    
63
		case 'save':
64
			if (strlen($_POST['file']) < 1) {
65
				print('|');
66
				print_info_box(gettext("No file name specified."), 'danger');
67
				print('|');
68
			} else {
69
				$_POST['data'] = str_replace("\r", "", base64_decode($_POST['data']));
70
				$ret = file_put_contents($_POST['file'], $_POST['data']);
71
				if ($_POST['file'] == "/conf/config.xml" || $_POST['file'] == "/cf/conf/config.xml") {
72
					if (file_exists("/tmp/config.cache")) {
73
						unlink("/tmp/config.cache");
74
					}
75
					disable_security_checks();
76
				}
77
				if ($ret === false) {
78
					print('|');
79
					print_info_box(gettext("Failed to write file."), 'danger');
80
					print('|');
81
				} elseif ($ret != strlen($_POST['data'])) {
82
					print('|');
83
					print_info_box(gettext("Error while writing file."), 'danger');
84
					print('|');
85
				} else {
86
					print('|');
87
					print_info_box(gettext("File saved successfully."), 'success');
88
					print('|');
89
				}
90
			}
91
			exit;
92
	}
93
	exit;
94
}
95

    
96
require_once("head.inc");
97

    
98
print_callout(gettext("The capabilities offered here can be dangerous. No support is available. Use them at your own risk!"), 'danger', gettext('Advanced Users Only'));
99

    
100
?>
101
<!-- file status box -->
102
<div style="display:none; background:#eeeeee;" id="fileStatusBox">
103
	<div id="fileStatus"></div>
104
</div>
105

    
106
<div class="panel panel-default">
107
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Save / Load a File from the Filesystem")?></h2></div>
108
	<div class="panel-body">
109
		<div class="content">
110
			<form>
111
				<p><input type="text" class="form-control" id="fbTarget" placeholder="<?=gettext('Path to file to be edited')?>"/></p>
112
				<div class="btn-group">
113
					<p>
114
						<button type="button" class="btn btn-default btn-sm" onclick="loadFile();"	value="<?=gettext('Load')?>">
115
							<i class="fa fa-file-text-o"></i>
116
							<?=gettext('Load')?>
117
						</button>
118
						<button type="button" class="btn btn-default btn-sm" id="fbOpen"		value="<?=gettext('Browse')?>">
119
							<i class="fa fa-list"></i>
120
							<?=gettext('Browse')?>
121
						</button>
122
						<button type="button" class="btn btn-default btn-sm" onclick="saveFile();"	value="<?=gettext('Save')?>">
123
							<i class="fa fa-save"></i>
124
							<?=gettext('Save')?>
125
						</button>
126
					</p>
127
				</div>
128
				<p class="pull-right">
129
					<button id="btngoto" class="btn btn-default btn-sm"><i class="fa fa-forward"></i><?=gettext("GoTo Line #")?></button> <input type="number" id="gotoline" size="6" style="padding: 3px 0px;"/>
130
				</p>
131
			</form>
132

    
133
			<div id="fbBrowser" style="display:none; border:1px dashed gray; width:98%; padding:10px"></div>
134

    
135
			<script type="text/javascript">
136
			//<![CDATA[
137
			window.onload=function() {
138
				document.getElementById("fileContent").wrap='off';
139
			}
140
			//]]>
141
			</script>
142
			<textarea id="fileContent" name="fileContent" class="form-control" rows="30" cols="20"></textarea>
143
		</div>
144
	</div>
145
</div>
146

    
147
<script type="text/javascript">
148
//<![CDATA[
149
	events.push(function(){
150

    
151
		function showLine(tarea, lineNum) {
152

    
153
			lineNum--; // array starts at 0
154
			var lines = tarea.value.split("\n");
155

    
156
			// calculate start/end
157
			var startPos = 0, endPos = tarea.value.length;
158
			for (var x = 0; x < lines.length; x++) {
159
				if (x == lineNum) {
160
					break;
161
				}
162
				startPos += (lines[x].length+1);
163

    
164
			}
165

    
166
			var endPos = lines[lineNum].length+startPos;
167

    
168
			// do selection
169
			// Chrome / Firefox
170

    
171
			if (typeof(tarea.selectionStart) != "undefined") {
172
				tarea.focus();
173
				tarea.selectionStart = startPos;
174
				tarea.selectionEnd = endPos;
175
				return true;
176
			}
177

    
178
			// IE
179
			if (document.selection && document.selection.createRange) {
180
				tarea.focus();
181
				tarea.select();
182
				var range = document.selection.createRange();
183
				range.collapse(true);
184
				range.moveEnd("character", endPos);
185
				range.moveStart("character", startPos);
186
				range.select();
187
				return true;
188
			}
189

    
190
			return false;
191
		}
192

    
193
		$("#btngoto").prop('type','button');
194

    
195
		//On clicking the GoTo button, validate the entered value
196
		// and highlight the required line
197
		$('#btngoto').click(function() {
198
			var tarea = document.getElementById("fileContent");
199
			var gtl = $('#gotoline').val();
200
			var lines = $("#fileContent").val().split(/\r|\r\n|\n/).length;
201

    
202
			if (gtl < 1) {
203
				gtl = 1;
204
			}
205

    
206
			if (gtl > lines) {
207
				gtl = lines;
208
			}
209

    
210
			showLine(tarea, gtl);
211
		});
212

    
213
		// Goto the specified line on pressing the Enter key within the "Goto line" input element
214
		$('#gotoline').keyup(function(e) {
215
			if(e.keyCode == 13) {
216
				$('#btngoto').click();
217
			}
218
		});
219

    
220
	}); // e-o-events.push()
221

    
222
	function loadFile() {
223
		$("#fileStatus").html("");
224
		$("#fileStatusBox").show(500);
225
		$.ajax(
226
			"<?=$_SERVER['SCRIPT_NAME']?>", {
227
				type: "post",
228
				data: "action=load&file=" + $("#fbTarget").val(),
229
				complete: loadComplete
230
			}
231
		);
232
	}
233

    
234
	function loadComplete(req) {
235
		$("#fileContent").show(1000);
236
		var values = req.responseText.split("|");
237
		values.shift(); values.pop();
238

    
239
		if (values.shift() == "0") {
240
			var file = values.shift();
241
			var fileContent = window.Base64.decode(values.join("|"));
242

    
243
			$("#fileContent").val(fileContent);
244
		} else {
245
			$("#fileStatus").html(values[0]);
246
			$("#fileContent").val("");
247
		}
248

    
249
		$("#fileContent").show(1000);
250
	}
251

    
252
	function saveFile(file) {
253
		$("#fileStatus").html("");
254
		$("#fileStatusBox").show(500);
255

    
256
		var fileContent = Base64.encode($("#fileContent").val());
257
		fileContent = fileContent.replace(/\+/g, "%2B");
258

    
259
		$.ajax(
260
			"<?=$_SERVER['SCRIPT_NAME']?>", {
261
				type: "post",
262
				data: "action=save&file=" + $("#fbTarget").val() +
263
							"&data=" + fileContent,
264
				complete: function(req) {
265
					var values = req.responseText.split("|");
266
					$("#fileStatus").html(values[1]);
267
				}
268
			}
269
		);
270
	}
271

    
272
/**
273
 *
274
 *	Base64 encode / decode
275
 *	http://www.webtoolkit.info/
276
 *	http://www.webtoolkit.info/licence
277
 **/
278

    
279
var Base64 = {
280

    
281
	// private property
282
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
283

    
284
	// public method for encoding
285
	encode : function (input) {
286
		var output = "";
287
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
288
		var i = 0;
289

    
290
		input = Base64._utf8_encode(input);
291

    
292
		while (i < input.length) {
293

    
294
			chr1 = input.charCodeAt(i++);
295
			chr2 = input.charCodeAt(i++);
296
			chr3 = input.charCodeAt(i++);
297

    
298
			enc1 = chr1 >> 2;
299
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
300
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
301
			enc4 = chr3 & 63;
302

    
303
			if (isNaN(chr2)) {
304
				enc3 = enc4 = 64;
305
			} else if (isNaN(chr3)) {
306
				enc4 = 64;
307
			}
308

    
309
			output = output +
310
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
311
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
312

    
313
		}
314

    
315
		return output;
316
	},
317

    
318
	// public method for decoding
319
	decode : function (input) {
320
		var output = "";
321
		var chr1, chr2, chr3;
322
		var enc1, enc2, enc3, enc4;
323
		var i = 0;
324

    
325
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
326

    
327
		while (i < input.length) {
328

    
329
			enc1 = this._keyStr.indexOf(input.charAt(i++));
330
			enc2 = this._keyStr.indexOf(input.charAt(i++));
331
			enc3 = this._keyStr.indexOf(input.charAt(i++));
332
			enc4 = this._keyStr.indexOf(input.charAt(i++));
333

    
334
			chr1 = (enc1 << 2) | (enc2 >> 4);
335
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
336
			chr3 = ((enc3 & 3) << 6) | enc4;
337

    
338
			output = output + String.fromCharCode(chr1);
339

    
340
			if (enc3 != 64) {
341
				output = output + String.fromCharCode(chr2);
342
			}
343
			if (enc4 != 64) {
344
				output = output + String.fromCharCode(chr3);
345
			}
346

    
347
		}
348

    
349
		output = Base64._utf8_decode(output);
350

    
351
		return output;
352

    
353
	},
354

    
355
	// private method for UTF-8 encoding
356
	_utf8_encode : function (string) {
357
		string = string.replace(/\r\n/g,"\n");
358
		var utftext = "";
359

    
360
		for (var n = 0; n < string.length; n++) {
361

    
362
			var c = string.charCodeAt(n);
363

    
364
			if (c < 128) {
365
				utftext += String.fromCharCode(c);
366
			} else if ((c > 127) && (c < 2048)) {
367
				utftext += String.fromCharCode((c >> 6) | 192);
368
				utftext += String.fromCharCode((c & 63) | 128);
369
			} else {
370
				utftext += String.fromCharCode((c >> 12) | 224);
371
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
372
				utftext += String.fromCharCode((c & 63) | 128);
373
			}
374

    
375
		}
376

    
377
		return utftext;
378
	},
379

    
380
	// private method for UTF-8 decoding
381
	_utf8_decode : function (utftext) {
382
		var string = "";
383
		var i = 0;
384
		var c = c1 = c2 = 0;
385

    
386
		while (i < utftext.length) {
387

    
388
			c = utftext.charCodeAt(i);
389

    
390
			if (c < 128) {
391
				string += String.fromCharCode(c);
392
				i++;
393
			} else if ((c > 191) && (c < 224)) {
394
				c2 = utftext.charCodeAt(i+1);
395
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
396
				i += 2;
397
			} else {
398
				c2 = utftext.charCodeAt(i+1);
399
				c3 = utftext.charCodeAt(i+2);
400
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
401
				i += 3;
402
			}
403

    
404
		}
405

    
406
		return string;
407
	}
408

    
409
};
410

    
411
	<?php if ($_POST['action'] == "load"): ?>
412
		events.push(function() {
413
			$("#fbTarget").val("<?=htmlspecialchars($_POST['path'])?>");
414
			loadFile();
415
		});
416
	<?php endif; ?>
417

    
418
//]]>
419
</script>
420

    
421
<?php include("foot.inc");
422

    
423
outputJavaScriptFileInline("vendor/filebrowser/browser.js");
(16-16/234)