Advertisement
Guest User

Golang Ftp downloader

a guest
Nov 4th, 2010
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.10 KB | None | 0 0
  1. /* Written by kenkeiras
  2.  * This program is free software. It comes without any warranty, to
  3.  * the extent permitted by applicable law. You can redistribute it
  4.  * and/or modify it under the terms of the Do What The Fuck You Want
  5.  * To Public License, Version 2, as published by Sam Hocevar. See
  6.  * http://sam.zoy.org/wtfpl/COPYING for more details.
  7.  */
  8. package main
  9.  
  10. import(
  11.     "fmt"     /* Entrada / Salida        */
  12.     "net"     /* Sockets                 */
  13.     "os"      /* Archivos, errores ...   */
  14.     "strings" /* Manejo de strings       */
  15.     "strconv" /* Conversiones de strings */
  16. )
  17.  
  18. const BUFF_LEN = 1024
  19.  
  20. /* Lee una linea de un socket */
  21. func readline (sock *net.TCPConn) (s string){
  22.     s = ""
  23.     readData := make([]byte, 1) /* Un buffer de un byte */
  24.     for {
  25.         _, e := sock.Read(readData) /* Se lee un byte */
  26.  
  27.         /* Si algo falla... */
  28.         if (e != nil){
  29.             fmt.Fprintf(os.Stderr, "Error: %v\n", e)
  30.             os.Exit(2)
  31.         }
  32.  
  33.         /* Si no se acabo una línea, añadir el byte */
  34.         if (readData[0] != '\n'){
  35.             s = s + string(readData)
  36.         } else {
  37.         /* Sino, salir */
  38.             break
  39.         }
  40.     }
  41.     /* Se devuelve el string */
  42.     return
  43. }
  44.  
  45. /* Lee el banner del Servidor y devuelve el primer comando */
  46. func show_banner(sock *net.TCPConn) string{
  47.     line := ""
  48.     for{
  49.         line = readline(sock) /* Se lee una línea de socket */
  50.         if (line[ : 3 ] == "220"){ /* Si no dice nada importante */
  51.             fmt.Println(line)    /* Se muestra y se sigue esperando */
  52.         } else {    /* Sino se sale */
  53.             break
  54.         }
  55.     }
  56.     return line /* Es necesario devolver la última línea, porque
  57.                    no se sabe cuanto va a durar la "charla" */
  58. }
  59.  
  60. func getaddr(line string) *net.TCPAddr{
  61.  
  62.     /* Se elimina el texto que no importa */
  63.     base := line [ strings.Index(line, "(") + 1 :
  64.                    strings.Index(line, ")")]
  65.    
  66.     /* Se divide el texto con las ',' */
  67.     s := strings.Split(base, ",", 10)
  68.  
  69.     /* Se ensambla la IP */
  70.     ip := s[0] + "." + s[1] + "." + s[2] + "." + s[3]
  71.  
  72.     /* Y los puertos */
  73.     p1, _ := strconv.Atoi(s[4])
  74.     p2, _ := strconv.Atoi(s[5])
  75.     port := strconv.Itoa((p1 * 256) + p2)
  76.  
  77.     /* Por último se crea la variable de dirección */
  78.     addr, e := net.ResolveTCPAddr(ip + ":" + string(port) )
  79.     if (e != nil){
  80.         fmt.Fprintf(os.Stderr, "Error: %v\n", e)
  81.         os.Exit(1)
  82.     }
  83.  
  84.     /* Y se devuelve esa variable */
  85.     return addr
  86. }
  87.  
  88. /* Se pide una conexión en pasivo */
  89. func get_passive(sock *net.TCPConn){
  90.     sock.Write([]byte("PASV\r\n"))
  91. }
  92.  
  93. /* Se setea la conexíon a binario */
  94. func set_binary(sock *net.TCPConn){
  95.     sock.Write([]byte("TYPE I\r\n"))
  96. }
  97.  
  98. /* Descarga el archivo */
  99. func download_file(sock *net.TCPConn,
  100.                    file string ,
  101.                    addr *net.TCPAddr,
  102.                    quit chan int){
  103.  
  104.     /* Obtiene el nombre del archivo */
  105.     fname := file[ strings.LastIndex(file, "/") + 1 : ]
  106.  
  107.     /* Lo pide al servidor */
  108.     sock.Write([]byte("RETR " + file + "\r\n"))
  109.  
  110.     /* Se conecta a el */
  111.     nsock, e := net.DialTCP("tcp", nil, addr)
  112.     if (e != nil){
  113.         fmt.Fprintf(os.Stderr, "Error conectando: %v\n", e)
  114.         os.Exit(1)
  115.     }
  116.  
  117.     /* Crea el archivo nuevo */
  118.     f, e := os.Open(fname, os.O_WRONLY| os.O_RDONLY | os.O_CREAT,
  119.              0666)
  120.     if (e != nil){
  121.         fmt.Fprintf(os.Stderr, "Error creando archivo: %v\n", e)
  122.         os.Exit(1)
  123.     }
  124.  
  125.     /* Y lo descarga */
  126.     buff := make([]byte, BUFF_LEN)
  127.     fmt.Print("Descargando... ")
  128.     for {
  129.         /* Lee unos cuantos bytes */
  130.         len, e := nsock.Read(buff)
  131.  
  132.         /* Si se acabó el archivo */
  133.         if (e == os.EOF){
  134.             break
  135.         }
  136.         if (e != nil){
  137.             fmt.Fprintf(os.Stderr, "Error: %v\n", e)
  138.             break
  139.         }
  140.         if (len < 1){
  141.             break
  142.         }
  143.         f.Write(buff[ : len ])
  144.     }
  145.     fmt.Println("completado!")
  146.     /* Solo queda cerrar el archivo y el socket de  la descarga */
  147.     f.Close()
  148.     nsock.Close()
  149.  
  150.     /* Y avisar del final del subproceso */
  151.     quit <- 1
  152. }
  153.  
  154. func main(){
  155.     user := "anonymous"    /* Usuario */
  156.     passwd := ""           /* Contraseña */
  157.     filepath := ""         /* Archivo a descargar */
  158.     host := "localhost"    /* Servidor */
  159.     port := "21"           /* Puerto */
  160.     quit := make(chan int) /* Canal para avisar de fin de subproceso */
  161.  
  162.     /* Si no se especifico el archivo*/
  163.     if (len(os.Args[:]) != 2){
  164.         fmt.Println("Uso:", os.Args[0],
  165.             "[<usuario>[:<contraseña>]@]<host>[:<puerto>]/archivo")
  166.         os.Exit(0)
  167.     }
  168.  
  169.     /* Se interpreta el argumento */
  170.     comp := strings.Split(os.Args[1], "@", 2)
  171.     uri := ""
  172.     if (len(comp) == 2){ /* Si se especifica user:pass */
  173.         up := strings.Split(comp[0], ":", 2)
  174.         user = up[0]
  175.         if (len(up) > 1){
  176.             passwd = up[1]
  177.         }
  178.         uri = comp[1]
  179.     } else {
  180.         uri = comp[0]
  181.     }
  182.     comp = strings.Split(uri, "/", 2)
  183.     if (len(comp) == 2){
  184.         hp := strings.Split(comp[0], ":", 3)
  185.         host = hp[0]
  186.         if (len(hp) > 1){
  187.             port = hp[1]
  188.         }
  189.         filepath = comp[1]
  190.     } else {
  191.         fmt.Fprintf(os.Stderr, "No se ha especificado el archivo\n")
  192.         os.Exit(4)
  193.     }
  194.    
  195.    
  196.     /* Se resuelve la dirección */
  197.     addr, e := net.ResolveTCPAddr(host + ":" + port)
  198.  
  199.     if (e != nil){
  200.         fmt.Fprintf(os.Stderr, "Error: %v\n", e)
  201.         os.Exit(1)
  202.     }
  203.  
  204.     fmt.Printf("Conectando a %s... ", addr)
  205.  
  206.     /* Se establece la conexión */
  207.     sock, e := net.DialTCP("tcp", nil, addr)
  208.     if (e != nil){
  209.         fmt.Fprintf(os.Stderr, "Error conectando: %v\n", e)
  210.         os.Exit(1)
  211.     }
  212.     fmt.Println("Hecho")
  213.  
  214.     /* Envía el user y el pass */
  215.     sock.Write([]byte("USER " + user + "\r\n"))
  216.     sock.Write([]byte("PASS " + passwd + "\r\n"))
  217.  
  218.     /* Muestra el banner */
  219.     line := show_banner(sock)
  220.     for{
  221.         /* ¿EOF? */
  222.         if (line == ""){
  223.             break
  224.         }
  225.         /* Login correcto, se pasa a binario y se pide
  226.             un canal pasivo */
  227.         if (line[ 0 : 3 ] == "230"){
  228.             set_binary(sock)
  229.             get_passive(sock)
  230.  
  231.         /* Cuando hay un canal pasivo abierto, se obtiene su
  232.             dirección y se descarga el archivo */
  233.         } else if (line [ : 3 ] == "227"){
  234.             naddr := getaddr(line)
  235.             go download_file(sock, filepath, naddr, quit)
  236.  
  237.         /* Error al descargar :( */
  238.         } else if (line [ : 3] == "550") {
  239.             fmt.Fprintf(os.Stderr, "Error al descargar el archivo\n")
  240.             os.Exit(5)
  241.  
  242.         /* Cerrando conexión */
  243.         } else if (line [ : 3] == "226") {
  244.             break
  245.         }
  246.         /* Se muestra lo que dice el servidor */
  247.         fmt.Println(line)
  248.  
  249.         /* Y se obtiene la próxima línea */
  250.         line = readline(sock)
  251.     }
  252.     /* Se espera por el subproceso */
  253.     <-quit
  254.     /* Se cierra el socket */
  255.     sock.Close()
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement