?? ftps.csp
字號:
package ftps;
import utils;
var users = null; // map of xml::element
var all; // map of conection objects
var all_mutex; // all guard
class connection
{
var _user_name;
var _path;
var _quota;
var _approved;
var _dialog_stream; // dialog stream
var _alive;
var _remote_addr;
var _client_addr;
var _passive_socket;
var _addr; // server addr/name (see PASV)
//|
//| constructor
//|
function connection(conn_socket)
{
_dialog_stream = conn_socket.stream();
_client_addr = conn_socket.remote_addr;
_alive = true;
_passive_socket = null;
_path = new utils::path();
_quota = 0;
_addr = conn_socket.addr;
if(!_addr.like("[0-9]*.[0-9]*.[0-9]*.[0-9]*")) _addr = socket::addr_by_name(_addr);
}
function answer(number,msg)
{
//DEBUG out.printf("%d %s\r\n",number,msg);
_dialog_stream.printf("%d %s\r\n",number,msg);
}
function get_data_stream()
{
var rsock = _passive_socket ?
_passive_socket.accept(60000):
socket::connect(_remote_addr,60000);
return rsock? rsock.stream(): null;
}
function write_acc_denied() {
if (_quota == 0) { answer(550,"Access denied"); return true; }
return false;
}
//|
//| TYPE cmd handler
//|
function do_TYPE(prm) { answer(200,"type set"); }
function print_list_line(data_stream,n)
{
data_stream.printf("%10s 1 owner group %10d %10s %s\r\n",
utils::format_node_atts(n),
n.size,
utils::format_date(n.mtime),
n.name_extension);
}
//|
//| LIST cmd handler, list directory content
//|
function do_LIST(prm)
{
answer(150,"ASCII data");
var _data_stream = get_data_stream();
if (_data_stream)
{
var n = new node(_path.map(prm));
if(n.is_folder)
{
var i,nodes = n.nodes("*.*");
for( i=0; i < nodes.length; i++)
{
print_list_line(_data_stream,nodes[i]);
}
}
else if(n.is_file)
print_list_line(_data_stream,n);
answer(226,"transfer complete");
//close stream
_data_stream.close();
}
else {
answer(226,"transfer complete");
}
}
//|
//| RETR cmd handler
//|
function do_RETR(prm)
{
try {
var n = new node(_path.map(prm));
if (!n.is_file) { answer(500,"command not supported"); return null; }
var in_stream = n.stream("rb");
answer(150, "Binary data connection");
var data_stream = get_data_stream();
if (!data_stream) { answer(500,"command not supported"); return null; }
var buffer = new blob();
while(_alive) {
if(!in_stream.read(buffer,8192)) break;
data_stream.write(buffer);
}
in_stream.close();
data_stream.close();
}
catch(e) {
answer(450,"Requested file action not taken. " + e);
return null;
}
answer(252,"FTP transfer completed correctly");
//answer(500,"command not supported");
}
function do_STOR(prm)
{
if(write_acc_denied()) return;
try {
var n = new node(_path.map(prm));
if (n.is_folder) //TODO: proper response please
{ answer(500,"command not supported"); return null; }
var out_stream = n.stream("wb");
answer(150, "Binary data connection");
var data_stream = get_data_stream();
if (!data_stream) { answer(500,"command not supported"); return null; }
var buffer = new blob();
while(_alive) {
if(!data_stream.read(buffer,8192)) break;
out_stream.write(buffer);
}
out_stream.close();
data_stream.close();
}
catch(e) {
answer(450,"Requested file action not taken. " + e);
return null;
}
answer(252,"FTP transfer completed correctly");
}
//|
//| PORT cmd handler
//|
function do_PORT(prm)
{
if(_passive_socket) { _passive_socket.close(); _passive_socket = null; }
var i,n = prm.split(',');
var port = 0;
if(n.length == 6)
{
for(i=0;i<6;++i) n[i] = int(n[i]);
port = (n[4] << 8) + n[5];
_remote_addr = string::printf("%d.%d.%d.%d:%d",n[0],n[1],n[2],n[3], port );
}
if (port == 0)
answer(501,"bad parameters:" + prm);
else
answer(200,"PORT command successful");
}
//|
//| PASV cmd handler
//|
function do_PASV(prm)
{
if(!_passive_socket) _passive_socket = new socket( string::printf("%s:%d",_addr,0) );
var addr = _addr.replace('.',',');
var port = _passive_socket.port;
//out.printf("Passive Mode (%s,%d,%d)\n", addr, port >> 8, port & 0xff);
answer(227,string::printf("Passive Mode (%s,%d,%d)", addr, port >> 8, port & 0xff));
}
function do_DELE(prm)
{
if(write_acc_denied()) return;
var n = new node(_path.map(prm));
try {
n.remove();
answer(200, "file has been deleted.");
}
catch(e) {
answer(553,"Requested action not taken." + e);
}
}
function do_RMD(prm)
{
if(write_acc_denied()) return;
var n = new node(_path.map(prm));
try {
n.remove();
answer(200, "dir has been deleted.");
}
catch(e) {
answer(553,"Requested action not taken." + e);
}
}
function do_CWD(prm)
{
if(_path.change(prm)) answer(200,"dir changed");
else answer(553,string::printf("File name '%s' not allowed. You are using wrong FTP client.",prm));
}
function do_MKD(prm)
{
if(write_acc_denied()) return;
var n = new node(_path.map(prm));
try {
n.make_folder();
answer(200,"dir created");
}
catch(e) {
answer(553,"Requested action not taken." + e);
}
}
function do_CDUP(prm)
{
do_CWD("..");
}
function do_ACCT()
{
answer(500,"command not supported");
}
function do_QUIT()
{
_alive = false;
}
function do_USER(prm)
{
_user_name = prm;
answer(331,"Password:");
}
function do_PASS(prm)
{
var userdef = users[_user_name];
if( userdef )
{
var pwd = userdef["password"];
if(!pwd || pwd == prm) {
_path.base = userdef["path"];
_quota = number(userdef["quota"]);
answer(230, string::printf("User %s logged in.",_user_name));
}
}
else
{
_alive = false;
answer(530, "Not logged in. Wrong credentials.");
}
}
function do_PWD()
{
answer(200, string::printf("\"%s\"", _path.rel_path()));
}
function do_SYS()
{
answer(500,"command not supported");
}
//|
//| map cmd name to handler function
//|
static var cmds =
{
"RETR": do_RETR, "STOR": do_STOR, "TYPE": do_TYPE, "DELE": do_DELE,
"CDUP": do_CDUP, "CWD": do_CWD, "QUIT": do_QUIT, "USER": do_USER,
"PASS": do_PASS, "PWD" : do_PWD, "SYS" : do_SYS, "PORT": do_PORT,
"LIST": do_LIST, "ACCT": do_ACCT, "MKD": do_MKD, "RMD": do_RMD,
"PASV": do_PASV
};
//|
//| thread main function
//|
function run()
{
var cmd,prm;
answer(220,string::printf("TerraInformatica's TIL FTP service on '%s' ready.",socket::hostname()));
out.printf("connection with %s\n",_client_addr);
synchronized(all_mutex) { all[this] = true; }
while(_alive)
{
cmd = _dialog_stream.get(' ',"\r\n"); //get until whitespace or eol
if(!cmd) break; // connection lost or closed
//DEBUG out.printf("got:%s ",cmd);
// if we got " " then read next param, otherwise prm = "";
prm = (_dialog_stream.get_match == 2)? "" : _dialog_stream.get("\r\n");
//DEBUG out.printf("%s\n",prm);
var func = cmds[cmd.to_upper()];
if(func)
{
try {
// make oject method reference and invoke it...
(this @ func)(prm) ;
}
catch( err ) {
out.printf("ERROR:%s\n",err);
answer(506,"Requested action not yet properly implemented by the server.");
}
}
else
answer(506,"Requested action not implemented by the server.");
}
synchronized(all_mutex) {
if(all[this]) all.remove(this);
}
if( _passive_socket ) _passive_socket.close();
_dialog_stream.put("Good bye...\r\n");
_dialog_stream.close();
out.printf("connection with %s(%s) closed\n",_client_addr,socket::name_by_addr(_client_addr));
}
}
var alive = true;
var gate;
//|
//| ftp gatekeeper thread function
//| parameters:
//| ftp_conf - xml::element (ftp)
//| users - map(key - username,value - xml::element(user) )
//| see:
//| config.xml
function gatekeeper(ftp_conf,users_map)
{
var address = ftp_conf["address"] || "localhost:21";
users = users_map;
all = new map();
all_mutex = new mutex();
gate = new socket(address);
while(alive) {
try {
var conn_socket = gate.accept();
if(!conn_socket || !alive) return false;
var conn = new connection(conn_socket);
new thread( conn.run );
}
catch(e) {
// do something here
out.printf("ERROR(gatekeeper): %s\n",e);
break;
}
}
}
function shutdown()
{
alive = false;
gate.shutdown();
synchronized(all_mutex)
{
var i; for(i = 0; i < all.length; i++)
{
var conn = all.key(i);
conn._alive = false;
conn._dialog_stream.close(); //source.shutdown();
}
}
}
function active()
{
return alive || all.length;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -