Skip to content

Commit 8f06645

Browse files
committed
Initial commit of extracted django webshell
This is a webshell I wrote, and committed as part of an overarching django local-only git project. Rather than conflate all my django projects, I am electing to copy the files for this project as a new git project, abandoning the history in favor of project clarity.
1 parent 69fedc9 commit 8f06645

13 files changed

+846
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.pyc
2+
*.sqlite

templates/webshell/editor.html

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<html>
2+
3+
<link rel="stylesheet" href="/static/codemirror.css">
4+
5+
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
6+
<script src="/static/codemirror.js"></script>
7+
8+
<style type="text/css">
9+
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
10+
</style>
11+
12+
<body>
13+
14+
<form id="save" method="POST" action="/webshell/editor/save/{{fileName}}">
15+
{% csrf_token %}
16+
17+
<textarea name="fileContents" id="fileContents">{{fileContents}}</textarea>
18+
</form>
19+
20+
</body>
21+
22+
</html>
23+
24+
<script>
25+
26+
$("#fileContents").focus();
27+
CodeMirror.commands.save = function(){
28+
$("#save").submit();
29+
};
30+
var e = CodeMirror.fromTextArea(document.getElementById("fileContents"), {
31+
lineNumbers: true,
32+
mode: "text/x-csrc",
33+
vimMode: true,
34+
showCursorWhenSelecting: true
35+
});
36+
</script>

templates/webshell/execute.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
2+
3+
{% include "webshell/includeme_execute.html" %}

templates/webshell/file_manager.html

+237
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
2+
3+
<div id='viewImgDiv' style='display: none; position: fixed; left: 1%; top:1%;' onclick='$("#viewImgDiv").hide();'/>
4+
<img style='position: fixed; left: 1%; top: 1%; max-height:98%; max-width:98%; border: solid black 1px; padding: 2px; background-color: rgb(200,100,100);' id='viewImg' />
5+
<span style='position: fixed; left:2%; top: 2%; font-size: 300%; cursor: pointer; box-shadow:0px 0px 5px 1px white inset; ' onclick='delete_file(new ImageRow(curFname, curRowNum));'> &times; </span>
6+
<span style='position: fixed; left:2%; top: 25%; font-size: 200%; cursor: pointer; box-shadow:0px 0px 5px 1px white inset; ' onclick='delete_file_next(new ImageRow(curFname, curRowNum));'> dn </span>
7+
<span style='position: fixed; left:2%; top: 50%; font-size: 200%; cursor: pointer; box-shadow:0px 0px 5px 1px white inset; ' onclick='file_next(new ImageRow(curFname, curRowNum));'> n </span>
8+
</div>
9+
10+
{% include "webshell/execute.html" %}
11+
12+
<h2> here's files for <span id="cwd_span"> {{ cwdin }} </span>: </h2>
13+
14+
<table id='files_table' border='1'>
15+
<tr/>
16+
</table>
17+
18+
<script type="text/javascript">
19+
var curFname = "";
20+
var curRowNum = -1;
21+
22+
function urlDecode(inString) {
23+
return decodeURIComponent(inString).replace('+', ' ');
24+
}
25+
26+
function urlEncode(inString) {
27+
return encodeURIComponent(inString);
28+
}
29+
30+
function delete_file(image_row) {
31+
image_row.highlight("red");
32+
var image_name = urlEncode(image_row.image_name);
33+
$.getJSON("/webshell/ajax/delete/"+image_row.image_name, function(data){
34+
if (data["HTTPRESPONSE"] == 1) {
35+
$("#row_"+image_row.row_number).remove();
36+
} else {
37+
//alert("failure");
38+
}
39+
});
40+
curFname = "";
41+
curRowNum = -1;
42+
}
43+
44+
function file_next(image_row) {
45+
show_image(image_row.next());
46+
}
47+
48+
function delete_file_next(image_row) {
49+
delete_file(image_row);
50+
show_image(image_row.next());
51+
}
52+
53+
function set_cwd(dir_name) {
54+
dir_name = urlEncode(dir_name).replace('..', '++');
55+
$.getJSON("/webshell/ajax/set_cwd/"+dir_name, function(data){
56+
if (data["HTTPRESPONSE"] == 1) {
57+
$("#cwd_span").text(data["cwd"]);
58+
dump_files();
59+
get_files();
60+
} else {
61+
//alert("failure");
62+
}
63+
});
64+
}
65+
66+
function show_image(image_row) {
67+
if(image_row != null) {
68+
var image_name = image_row.image_name;
69+
var row_number = image_row.row_number;
70+
71+
curFname = image_row.image_name;
72+
curRowNum = image_row.row_number;
73+
image_row.highlight("green");
74+
75+
image_name = urlEncode(image_name);
76+
77+
var v = $('#viewImg').attr('src', '/webshell/file_manager/get/'+image_name)
78+
.unbind()
79+
.load( function(){
80+
$("#viewImgDiv").show();
81+
preloader.preload(image_row.next());
82+
} )
83+
.error( function(){
84+
alert("had an error");
85+
preloader.preload(image_row.next());
86+
} )
87+
//.attr('onprogress', function(e) {
88+
// alert('progressing!' + ':' + e);
89+
//} )
90+
;
91+
}
92+
}
93+
94+
95+
96+
97+
function ImageRow() {
98+
this.image_name = "";
99+
this.row_number = -1;
100+
}
101+
102+
function ImageRow(image_name, row_number) {
103+
this.image_name = image_name;
104+
this.row_number = row_number;
105+
this.nr = null;
106+
}
107+
108+
ImageRow.prototype.highlight = function(color) {
109+
$("#row_"+this.row_number+" td").css("background-color", color);
110+
}
111+
112+
ImageRow.prototype.next = function () {
113+
this.nr = null;
114+
115+
for(var i = this.row_number+1; $("#row_"+i).length > 0; i++) {
116+
var row = $("#row_" + i + " input[name='image_name']")[0];
117+
if ( row ) {
118+
this.nr = new ImageRow($(row).attr('value'), i);
119+
return(this.nr);
120+
}
121+
}
122+
return this.nr;
123+
}
124+
125+
126+
127+
function Preloader() {
128+
this.queue = [];
129+
this.active = false;
130+
this.preloaded = {};
131+
}
132+
133+
Preloader.prototype.preload = function(image_row) {
134+
if(image_row != null) {
135+
if(this.preloaded[image_row.image_name] != true){
136+
this.queue.push(image_row);
137+
this.next();
138+
}
139+
}
140+
}
141+
142+
Preloader.prototype.next = function() {
143+
if(this.queue.length > 0) {
144+
image_row = this.queue.shift();
145+
146+
this.preloaded[image_row.image_name] = true;
147+
148+
image_row.highlight("orange");
149+
$("#row_" + image_row.row_number + " input[name='image_name']").each( function() {
150+
$('<img/>').attr('src', '/webshell/file_manager/get/' + $(this).attr('value'))
151+
.unbind()
152+
.load( function() {
153+
image_row.highlight("yellow");
154+
preloader.preload(image_row.next());
155+
})
156+
.error( function(){
157+
alert("had an error.2");
158+
} )
159+
;
160+
});
161+
}
162+
}
163+
164+
165+
var preloader = new Preloader();
166+
167+
function update_row(f) {
168+
fname = urlDecode(f.name);
169+
var row_to_update = $('tr[name="' + fname + '"]').get(0);
170+
if(row_to_update != null) {
171+
var row_children = $(row_to_update).children("td");
172+
if($(row_children[2]).text() != f.fileType) {
173+
$(row_children[2]).html("<pre>" + f.fileType + "</pre>");
174+
}
175+
if($(row_children[3]).text() != f.size) {
176+
$(row_children[3]).html("<pre>" + f.size + "</pre>");
177+
}
178+
if($(row_children[4]).text() != f.dateModified) {
179+
$(row_children[4]).html("<pre>" + f.dateModified + "</pre>");
180+
}
181+
}
182+
}
183+
184+
var rowNum = 0;
185+
function add_row(f) {
186+
fname = urlDecode(f.name);
187+
var rowHtml = '<tr id="row_' + rowNum + '" name="' + fname + '">' +
188+
'<td>' + '<input type="button" value="Delete" onclick=' +
189+
"'delete_file(new ImageRow(" + '"' + fname + '"' + ", " + rowNum + "));' />" +
190+
"</td><td>";
191+
if (f.fileType == "dir") {
192+
rowHtml += "<a onclick='set_cwd(" + '"' + fname + '"' + ");'> " + fname + " / </a>";
193+
} else {
194+
if (f.fileType == "image") {
195+
rowHtml += "<span style='cursor:pointer;' onclick='show_image(new ImageRow(" + '"' + fname +
196+
'", ' + rowNum + "));'> " + fname + "</span>" +
197+
'<input type="hidden" name="image_name" value="' + fname + '"/>';
198+
} else {
199+
rowHtml += "<a href='/webshell/file_manager/get/" + fname + "' target='_blank'>" + fname + "</a>";
200+
}
201+
rowHtml += "<a href='/webshell/editor/view/" + fname + "' target='_blank'> &#9998; </a>";
202+
}
203+
rowHtml += "</td>" +
204+
"<td><pre>" + f.fileType + "</pre></td>" +
205+
"<td><pre>" + f.size + "</pre></td>" +
206+
"<td><pre>" + f.dateModified + "</pre></td>" +
207+
"</tr>";
208+
209+
$('#files_table tr:last').after( rowHtml );
210+
rowNum++;
211+
}
212+
213+
function dump_files() {
214+
$('#files_table').empty();
215+
$('#files_table').append( "<tr> </tr>" );
216+
217+
}
218+
219+
function get_files() {
220+
$.getJSON( "/webshell/ajax/get_files/", function( data ) {
221+
$.each( data, function( index, f ) {
222+
fname = urlDecode(f.name);
223+
if($('tr[name="' + fname + '"]').length <= 0) {
224+
add_row(f);
225+
} else {
226+
update_row(f);
227+
}
228+
});
229+
});
230+
}
231+
232+
// Do initial files load
233+
234+
get_files();
235+
var tid = setInterval(get_files, 10000);
236+
237+
</script>

templates/webshell/history.html

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
2+
3+
<h1> You are username={{ username }} </h1>
4+
<h2> here's your history: </h2>
5+
6+
<table border='1'>
7+
{% for h in history_list %}
8+
<tr>
9+
<td> <a href='/webshell/history/delete/{{h.id}}'> x </a> </td>
10+
<td><pre> {{ h.time_stamp }} </pre></td>
11+
<td><pre> {{ h.cmd_pwd }} </pre></td>
12+
<td><pre> {{ h.cmd_text }} </pre></td>
13+
</tr>
14+
{% endfor %}
15+
</table>

0 commit comments

Comments
 (0)