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-2016 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
##|*MATCH=diag_edit.php*
27
##|*MATCH=browser.php*
28
##|*MATCH=vendor/filebrowser/browser.php*
29
##|-PRIV
30

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

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

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

    
95
require_once("head.inc");
96

    
97
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'));
98

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

    
105
<div class="panel panel-default">
106
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Save / Load a File from the Filesystem")?></h2></div>
107
	<div class="panel-body">
108
		<div class="content">
109
			<form>
110
				<p><input type="text" class="form-control" id="fbTarget" placeholder="<?=gettext('Path to file to be edited')?>"/></p>
111
				<div class="btn-group">
112
					<p>
113
						<button type="button" class="btn btn-default btn-sm" onclick="loadFile();"	value="<?=gettext('Load')?>">
114
							<i class="fa fa-file-text-o"></i>
115
							<?=gettext('Load')?>
116
						</button>
117
						<button type="button" class="btn btn-default btn-sm" id="fbOpen"		value="<?=gettext('Browse')?>">
118
							<i class="fa fa-list"></i>
119
							<?=gettext('Browse')?>
120
						</button>
121
						<button type="button" class="btn btn-default btn-sm" onclick="saveFile();"	value="<?=gettext('Save')?>">
122
							<i class="fa fa-save"></i>
123
							<?=gettext('Save')?>
124
						</button>
125
					</p>
126
				</div>
127
				<p class="pull-right">
128
					<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;"/>
129
				</p>
130
			</form>
131

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

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

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

    
150
		function showLine(tarea, lineNum) {
151

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

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

    
163
			}
164

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

    
167
			// do selection
168
			// Chrome / Firefox
169

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

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

    
189
			return false;
190
		}
191

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
278
var Base64 = {
279

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

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

    
289
		input = Base64._utf8_encode(input);
290

    
291
		while (i < input.length) {
292

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

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

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

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

    
312
		}
313

    
314
		return output;
315
	},
316

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

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

    
326
		while (i < input.length) {
327

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

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

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

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

    
346
		}
347

    
348
		output = Base64._utf8_decode(output);
349

    
350
		return output;
351

    
352
	},
353

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

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

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

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

    
374
		}
375

    
376
		return utftext;
377
	},
378

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

    
385
		while (i < utftext.length) {
386

    
387
			c = utftext.charCodeAt(i);
388

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

    
403
		}
404

    
405
		return string;
406
	}
407

    
408
};
409

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

    
417
//]]>
418
</script>
419

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

    
422
outputJavaScriptFileInline("vendor/filebrowser/browser.js");
(13-13/225)