Serveur ftp

Contenu du snippet

ceci est un serveur FTP en mirc script
tout se passe avec une seulle et unique commande: /wbs.ftpserver

notation: je notre entre () les parametres optionels et entre [] les obligatoires
partager un répertoire: /wbs.ftpserver add [login] [pass] (folder)
si (folder) n'est pas spécifié alors une fenetre de selection de répertoire ($sdir) s'ouvrira.

demarer le serveur: /wbs.ftpserver start
stoper le serveur: /wbs.ftpserver stop
status du serveur: /wbs.ftpserver status
lister les partages: /Wbs.ftpserver list
avoir uen aide sommaire: /wbs.ftpserver (help)

Source / Exemple :


;Socknames:
;listen: wbs.ftpserver
;com: wbs.ftpserver.[client-ip]
;data: wbs.ftpserver@[client-ip]

on *:load:{
  if ($version < 6.35) {
    wecho $sname error: Woops ! your version of mirc is $version but 6.35 or newer is needed !!! sorry but i cant work
    aptitude remove $sname
  }
  else {
    writeini $wcfg $sname enable 0
    writeini $wcfg $sname maxco 2
    writeini $wcfg $sname port 21
    writeini $wcfg $sname nopasv 0
    writeini $wcfg $sname quiet 1
    writeini $wcfg $sname pasv-range 1000 1010
    wecho $sname info: to specify manualy the ip of the server you can type:
    wecho $sname info: //writeini $wcfg $sname serverip [your IP]
    wecho $sname info: dont forget to redirect/open ports on you're router/firewall
  }
}

on *:unload:{
  if ($sock($sname)) wbs.ftpserver stop
remove $wcfg
}

alias -l sname return wbs.ftpserver

on *:start:{
  if ($readini($wcfg,$sname,enable)) socklisten $sname $iif($readini($wcfg,$sname,port),$v1,21)
}

alias wbs.ftpserver {
  wecho $sname $iif($1-,$v1,help)
  if ($1 == start) {
    if ($sock($sname)) wecho $sname error: server is already started
    else {
      writeini $wcfg $sname enable 1
      socklisten $sname $iif($readini($wcfg,$sname,port),$v1,21)
      wecho $sname server started
    }
  }
  elseif ($1 == stop) {
    if (!$sock($sname)) wecho $sname error: server is not started
    else {
      writeini $wcfg $sname enable 0
      sockclose $+($sname,*)
      wecho $sname server stoped
    }
  }
  elseif ($1 == status) wecho $sname Server is curently $iif($sock($sname),started,stoped)
  elseif ($1 == close) {
    if (!$2) wecho $sname error: this function need the ip as argument.
    elseif ($sock($+($sname,.,$2))) sockclose $v1
    else wecho $sname error: stop $qt($2) : invalid ip
  }
  elseif ($1 == add) {
    if ((!$4) && ($3)) tokenize 32 $1- $$sfile($mircdir)
    if (!$4) wecho $sname error: syntax: /wbs.ftpserver add [login] [pass] [folder]
    elseif (!$exists($4-)) wecho $sname error: directory dosent exists
    else {
      writeini $wcfg wbs.ftpserver.shares $+($2,@,$3) 0 0 $noqt($4-)
      wecho $sname Successfuly added with permision: read only, to edit: /wbs.ftpserver chmod $+($2,@,$3) rw.
    }
  }
  elseif ($1 == chmod) wecho $sname info: todo
  elseif ($1 == list) {
    var %n = $sock($sname $+ .*,0)
    if (!%n) wecho $sname No open socket.
    else {
      wecho $sname open connection(s): %n
      while (%n) {
        wecho $sname ip: $sock($sname $+ .*,%n).ip $+ : $+ $sock($sname $+ .*,%n).port
        dec %n
      }
    }
  }
  elseif ((!$1) || ($1 == help)) {
    wecho $sname help for $sname
    wecho $sname availables commands are:
    wecho $sname start - start the ftp server
    wecho $sname stop - stop the ftp server
    wecho $sname add [login] [pass] (folder) - add the folder in sharinf for user [login]
    wecho $sname list - list all open connection for the ftp server
    wecho $sname close [ip] - close the specified [IP]
  }
  else wecho $sname error: unknow command : $qt($1)
}

on *:socklisten:wbs.ftpserver:{
  var %ip = $iif($sock($sockname).ip,$v1,127.0.0.1) , %sockname = $+(wbs.ftpserver.,%ip)
  if ($sock(%sockname)) {
    sockwrite -n %sockname 500 You are trying to reconnect on the server but just one connection is allowed per ip : closing this one: now !
    sockclose %sockname
  }
  sockaccept %sockname
  if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,new connection from $sock($sockname).ip on port $sock($sockname).port)
  sockwrite -n %sockname 220 $sname FTP server ready
}

on *:sockopen:wbs.ftpserver.*:{
  if ($hget($sockname)) hfree $sockname
}
on *:sockread:wbs.ftpserver.*:{
  var %buffer
  sockread -f %buffer
  wbs.ftpserver.events %buffer
}

on *:sockclose:wbs.ftpserver.*:{
  if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,connection closed for $sock($sockname).ip)
  if ($hget($sockname)) hfree $sockname
}

alias wbs.ftpserver.events {
  if (!$1) return
  elseif ($1 == USER) {
    hadd -m $sockname login $2
    sw 331 Password required for $sname
  }
  elseif ($1 == PASS) {
    var %data = $readini($wcfg,wbs.ftpserver.shares,$+($hget($sockname,login),@,$2))
    if (!%data) { 
      noop $tip($sname,$sname,Bad login form $sock($sockname).ip : $2) 
      sockloose
    }
    else {
      hadd -m $sockname auth 1
      hadd $sockname root $noqt($gettok(%data,3-,32))
      hadd $sockname pwd /
      hadd $sockname serverip $iif($sock($sockname).ip == $ip,127.0.0.1,$sock($sockname).ip)
      hadd $sockname writeperm $gettok(%data,2,32)
      if ($readini($wcfg,$sname,serverip)) hadd $sockname serverip $v1
      writeini $wcfg wbs.ftpserver.shares $+($hget($sockname,login),@,$2) $calc($gettok(%data,1,32) +1) $gettok(%data,2-,32)
      sw 230 Ok
    }
  }
  elseif ($1 == QUIT) {
    if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,$sock($sockname).ip has quit.)
    sockloose
  }
  elseif ($1 == FEAT) sw 211 SIZE REST
  else {
    if (!$hget($sockname,auth)) sockloose
    elseif (.. isin $hget($sockname,pwd)) sockloose
    elseif ($1 == NOOP) sw 200 NOOP command successful
    elseif ($1 == SYST) sw 215 UNIX Type: L8
    elseif ($1 == PWD) sw 257 $+(",$hget($sockname,pwd),") is current directory.
    elseif ($1 == CDUP) {
      var %pwd = $hget($sockname,pwd)
      if (%pwd == /) sw 500 You are already at the root.
      elseif ($2) sw 500 Too many argument.
      else {
        hadd $sockname pwd $deltok(%pwd,-1,47)
        sw 250 CWD command successful.
      }
    }
    elseif ($1 == DELE) {
      var %file = $qt($+($hget($sockname,root),$hget($sockname,pwd),$2-))
      echo -a %file
      if (!$hget($sockname,writeperm)) sw 500 You dont have the permission to do that !
      elseif (!$2) sw 500 This function need a argument (the filename).
      elseif (!$exists(%file)) sw 500 The target dosent exists.
      elseif ((/../ isin $2-) || (\..\ isin $2-)) sw 500 Hacking attemp detected: abord
      else {
        .remove %file
        sw 250 Ok
      }
    }
    elseif ($1 == REST) {
      if (!$2) sw 500 Missing argument
      elseif ($2 !isnum) sw 500 Invalid argument: must be a int
      else {
        hadd $sockname filepos $2
        sw 226 ready to resume transfer at position $2
      }
    }
    elseif ($1 == TYPE) {
      if (!$istok(A;I,$2,59)) sw 500 Invalid type: must be A or I
      else {
        hadd $sockname type $2
        sw 200 Type set to $2
      }
    }
    elseif ($1 == CWD) {
      var %target = $strip($2-) , %cdir = $hget($sockname,pwd) , %path = $+($hget($sockname,root),%cdir,$iif($right(%cdir,1) != /,/),%target))
      if ($left(%target,1) == /) var %path = $+($hget($sockname,root),%target)
      if (%target == /) {
        hadd $sockname pwd /
        sw 250 command successful.
        return
      }
      if (!%target) sw 500 Missing argument
      elseif (!$exists(%path)) sw 500 Invalid argument: directory dosent exists.
      elseif ((/../ isin %target) || (\..\ isin %target)) sw 500 Hacking attemp detected: abord
      else {
        if ($left($2,1) != /) hadd $sockname pwd $replace(/ $+ %cdir $+ $nopath($2-) $+ /,//,/)
        else hadd $sockname pwd $2-
        sw 250 CWD command successful.
      }
    }
    elseif ($1 == PASV) {
      if ($readini($wcfg,$sname,nopasv)) sw 550 Command disabled in server config file.
      else {
        var %sockname = $+($sname,@,$sock($sockname).ip) , %secure = 100
        if ($readini($wcfg,$sname,pasv-range)) {
          tokenize 32 $v1
          if (!$2) %port = $1
          else {
            var %port = $r($1,$2)
            while ((!$portfree(%port)) && (%secure)) {
              var %port = $r($1,$2)
              dec %secure
            }
            if (!%secure) {
              wecho $sname error: unable to get a port in range $1- : set a larger plage of port in portrange.
              sw 500 Internal server error: cannot found a port free on the server side.
              return
            }
          }
          var %p1 = $int($calc(%port / 256)) , %p2 = %port % 256
          if ($sock(%sockname)) sockclose %sockname
          hadd -m $sockname pasv %sockname $sock($sockname).ip %port
          socklisten wbs.ftpserver-data %port
          sw 227 Entering Passive Mode $+($chr(40),$replace($hget($sockname,serverip),.,$chr(44)),$chr(44),%p1,$chr(44),%p2,$chr(41)) .
        }
        else sw 500 Bad configuration.
      }
    }
    elseif ($1 == PORT) {
      var %port = $calc($gettok($2,5,44) * 256 + $calc($gettok($2,6,44))) , %sockname = $+($sname,@,$sock($sockname).ip)
      if (!%port) sockclose $sockname
      else {
        if ($sock(%sockname)) sockclose %sockname
        hadd -m $sockname pasv %sockname $sock($sockname).ip %port
        sockopen %sockname $replace($gettok($2,1-4,44),$chr(44),.) %port
      }
    }
    elseif ($1 == MKD) {
      var %target = $replace($+($hget($sockname,root),$hget($sockname,pwd),/,$2-),//,/)
      if (!$2) sw 500 Missing argument.
      elseif ($istok(.;..;/;../;\;~;#; $+ $chr(35),$2-,59)) sw 500 Invalid argument.
      elseif ($regex($2,/(\/|\\)\.\.\1/)) sw 500 Invalid argument
      elseif ($exists(%target)) sw 500 Unable to create: already exists
      else {
        mkdir $qt(%target)
        sw 257 $qt($nopath($2-)) Directory created.
      }
    }
    elseif ($1 == ABOR) {
      var %sockdata = $gettok($hget($sockname,pasv),1,32)
      if ($sock(%sockdata)) sockclose %sockdata
      sw 200 Abord: ok
    }
    elseif ($1 == RETR) {
      var %sockdata = $gettok($hget($sockname,pasv),1,32) , %file = $qt($+($hget($sockname,root),$hget($sockname,pwd),$2-))
      if (!$sock(%sockdata)) sw 500 Unable to transfer: data socket not opened
      ;elseif ($hget($sockname,type) != I) sw 500 Unable to transfer: invalid type $qt($v1) > I is needed for trasnfers
      elseif (!$2) sw 500 Missing argument
      elseif (.. isin $2-) sw 500 Unallowed charaters in file name
      elseif (!$exists(%file)) sw 500 Unable to find $qt($2-)
      else {
        if ($fopen(%sockdata)) .fclose %sockdata
        if ($hget(%sockdata)) hfree %sockdata
        if ($hget($sockname,filepos)) {
          var %pos = $v1
          if ($file(%file).size < %pos) sw 500 Error: you requested to resume at %pos but the file size is $v1
          else hadd -m %sockdata filepos %pos
          hdel $sockname filepos
        }
        else hadd -m %sockdata filepos 0
        hadd %sockdata parent $sockname
        hadd %sockdata file %file
        sockmark %sockdata $1
        if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,Transfering $nopath(%file) to $sock($sockname).ip on %sockdata)
        sw 150 Opening Binary mode data connection for file list
        .fopen %sockdata %file
        .fseek %sockdata $hget(%sockdata,filepos)
        noop $fread(%sockdata,4000,&data)
        if ($hget($sockname,type) == A) sockwrite -n %sockdata $bvar(&data,1,4000).text
        else sockwrite %sockdata &data
      }
    }
    elseif ($1 == STOR) {
      var %sockdata = $gettok($hget($sockname,pasv),1,32) , %filepos = $iif($hget(%sockdata,filepos),$v1,0) , %file = $qt($+($hget($sockname,root),$hget($sockname,pwd),$2-))
      if (!$hget($sockname,writeperm)) sw 500 You dont have the permission to do that !
      elseif (!$sock(%sockdata)) sw 500 Unable to transfer: data socket not opened
      elseif (!$2) sw 500 Missing argument.
      elseif (.. isin $2-) sw 500 Unallowed charaters in file name
      else {
        if ($hget(%sockdata)) hfree %sockdata
        hadd -m %sockdata parent $sockname
        hadd %sockdata file %file
        sockmark %sockdata $1
        if ($fopen(%sockdata)) .fclose %sockdata
        .fopen -o %sockdata %file
        sw 150 Opening Binary mode data connection for file list
      }
    }
    elseif ($1 == LIST) {
      var %sockdata = $gettok($hget($sockname,pasv),1,32)
      if (!$sock(%sockdata)) sw 500 No data socket opened
      elseif ($hget($sockname,type) != A) sw 500 Unsuported TYPE mode for listing: please use TYPE A
      else {
        var %dir = $+($hget($sockname,root),$hget($sockname,pwd))
        sockwrite -n %sockdata DIR drwxr-sr-t  14 web      site         4096 Feb 13 23:39 .
        if ($hget($sockname,pwd) != /) sockwrite -n %sockdata DIR drwxr-sr-t  14 web      site         4096 $asctime($ctime,mmm dd) ..
        noop $finddir(%dir,*.*,0,0,sockwrite -n %sockdata DIR drwxr-sr-t  14 web      site         4096 Feb 13 23:39  $nopath($1-))
        noop $findfile(%dir,*.*,0,0,sockwrite -n %sockdata -rw-r--r--   1 web      site           $file($1-).size $asctime($file($1-).ctime,mmm dd) $time $nopath($1-))
        sockclose %sockdata
        sw 226 Transfer complete.
      }
    }
    else sw 500 Unknow command
  }
  ;wecho $sname < $1-
}
on *:socklisten:wbs.ftpserver-data*:{
  var %table = $+($sname,.,$sock($sockname).ip) , %data = $hget(%table,pasv) , %sock = $$gettok(%data,1,32)
  if (%data) sockaccept %sock
  sockmark %sock $hget(%table,type)
  sockclose $sockname
}
on *:sockopen:wbs.ftpserver@*:{
  if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,opened active connection for $sock($sockname).ip)
}
on *:sockwrite:wbs.ftpserver@*:{
  if ((!$hget($sockname)) && (!$fopen($sockname)) && (!$sock($sockname).mark) && ($sock($sockname).sq > 4000)) { sockloose | return }
  hinc $sockname filepos 4000
  noop $fread($sockname,4000,&data)
  if ($hget($hget($sockname,parent),type) == A) sockwrite -n $sockname $bvar(&data,1,4000).text
  sockwrite $sockname &data
  if (!$bvar(&data,0)) {
    if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,File $nopath($hget($sockname,file)) was successfully transfered to $sock($sockname).ip on port $sock($sockname).port in $duration($sock($sockname).to))
    sockwrite -n $hget($sockname,parent) 226 Transfer complete.
    sockloose
  }
}
alias -l sockloose {
  if ($hget($sockname)) hfree $sockname
  if ($fopen($sockname)) .fclose $sockname
  sockclose $sockname
}
on *:sockclose:wbs.ftpserver@*:{
  if (!$readini($wcfg,$sname,quiet)) noop $tip($sname,$sname,Client $sock($sockname).ip closed the data socket)
  sockwrite -n $hget($sockname,parent) 226 Transfer complete.
  if ($hget($sockname)) hfree $sockname
  if ($fopen($sockname)) .fclose $sockname
}
on *:sockread:wbs.ftpserver@*:{
  sockread &buffer
  if (!$hget($sockname)) sockloose
  else {
    ;bwrite $hget($sockname,file) -1 -1 &buffer
    .fwrite -b $sockname &buffer
  }
}
alias -l sw {
  ;wecho $sname > $1-
  sockwrite -n $sockname $1-
}

alias -l wecho echo -a $+($chr(91),$sname,$chr(93)) $$1-
alias wcfg return $qt($mircdirFtpServer-Config.ini)

Conclusion :


il es encore en phase de developement mais il es deja fonctionel

pour le moment les listing de répertoires DOIVENT se faire en mode ascii (TYPE A) et les transfers en binaire (TYPE I)
j'effectue mes tests avec FlashFxp et tout marche bien, pour le moment je ne sais pas encore comment faire mon listing en binaire

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.