#!/usr/bin/env python
#-*-coding: utf-8-*-
import pygtk, gtk
pygtk.require('2.0')
import sys
import os
import time
import subprocess
import thread
from threading import Thread

class JanelaCompartilhar:
    def __init__(self):
        self.janela = gtk.Window()
        self.janela.set_position(gtk.WIN_POS_CENTER)
        self.janela.set_size_request(480, 480)
        self.janela.set_title("share - Compartilhar um arquivo")
        self.janela.set_resizable(False)
        try:
            self.janela.set_icon_from_file("icone.png")
        except Exception:
            self.icone = self.janela.render_icon(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_MENU)
            self.janela.set_icon(self.icone)

        self.label_instrucao = gtk.Label("Escolha um arquivo para compartilhar.")
        self.label_arquivo = gtk.Label("Nenhum arquivo escolhido.")
        self.label_instrucao2 = gtk.Label("Escolha uma porta entre 1025 e 65535:")
        self.label_porta =  gtk.Label("Nenhuma porta escolhida.")
        self.label_conexao = gtk.Label("")

        self.botao_cancelar = gtk.Button("Cancelar".center(30))
        self.botao_cancelar.connect("clicked", self.cancelar)
        
        self.botao_voltar = gtk.Button("<Voltar".center(30))
        self.botao_voltar.connect("clicked", self.voltar)
        
        self.botao_arquivo = gtk.Button('Escolher'.center(30))
        self.botao_arquivo.connect("clicked", self.escolher_arquivo)

        self.botao_compartilhar = gtk.Button('Compartilhar'.center(50))
        self.botao_compartilhar.connect('clicked', self.compartilhar)

        self.texto_porta = gtk.Entry(5)
        self.texto_porta.connect("changed", self.escolher_porta)

        self.fixo = gtk.Fixed()
        self.fixo.put(self.label_instrucao, 30, 100)
        self.fixo.put(self.label_instrucao2, 30, 150)
        self.fixo.put(self.label_arquivo, 30, 200)
        self.fixo.put(self.label_porta, 30, 250)
        self.fixo.put(self.label_conexao, 30, 350)

        self.fixo.put(self.botao_arquivo, 300, 95)
        self.fixo.put(self.texto_porta, 300, 150)
        self.fixo.put(self.botao_compartilhar, 120, 300)
        self.fixo.put(self.botao_cancelar, 30, 420)
        self.fixo.put(self.botao_voltar, 300, 420)

        self.janela.add(self.fixo)
        self.janela.show_all()

        self.caminho = ""
        self.porta = ""
        self.nome_arquivo = ""
        self.lista_portas = []

    def passe(self, widget, data=None):
        resposta = 42

    def escolher_arquivo(self, widget):
        "Valida a escolha do arquivo."
        # Cria um File Chooser
        self.fc = gtk.FileChooserDialog("Escolher...", None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        self.fc.set_default_response(gtk.RESPONSE_OK)
        resposta = self.fc.run()
        if resposta == gtk.RESPONSE_OK:
            self.caminho =  self.fc.get_filename()
            # Nome do arquivo é o último índice do caminho quando dividido pelas barras presentes
            nome = self.caminho.split('/')[len(self.caminho.split('/'))-1]
            self.nome_arquivo = nome
            if len(nome) > 40:
                nome_curto = nome[:10]+ ' [...] ' + nome[len(nome)-20:]
                self.nome_arquivo = nome_curto
                self.label_arquivo.set_text('Arquivo "' + nome_curto +'" escolhido')
            else:
                self.label_arquivo.set_text('Arquivo "'+ nome + '" escolhido.')
            # Se caminho contiver espaços, é preciso fazer com que o shell o reconheça
            # Solução 1: adicionando barra invertida antes dos espaços
            '''
            if " " in self.caminho:
                caminho_espacos = self.caminho.split(" ")
                caminho = ''
                i = 0
                while i < len(caminho_espacos):
                    # Para terminar no penultimo, não adicionando depois do último indice.
                    if i == len(caminho_espacos)-1:
                        self.caminho += caminho_espacos[i]
                    else:
                        self.caminho += caminho_espacos[i] + "\ "
                    i+=1
            '''
            # Solução 2: adicionando aspas no início e fim do caminho
            if " " in self.caminho:
                aspas='"'
                self.caminho = aspas + self.caminho + aspas
        elif resposta == gtk.RESPONSE_CANCEL:
            self.caminho = ""
            self.label_arquivo.set_text('Nenhum arquivo escolhido.')
        # Destrói o File Chooser
        self.fc.destroy()

    def escolher_porta(self, widget):
        "Valida a porta a ser escolhida."
        self.porta = str(self.texto_porta.get_text())
        if (self.porta== ""):
            self.label_porta.set_text("Nenhuma porta escolhida.")
        elif (not self.porta.isdigit()):
            self.label_porta.set_text("A porta deve conter somente números.")
        elif (self.porta.isdigit()):
            if (int(self.porta) <= 1024):
                self.label_porta.set_text("Número da porta muito baixo.")
            elif (int(self.porta) > 65535):
                self.label_porta.set_text("Número da porta muito alto.")
            else:
                self.label_porta.set_text("Porta "+ str(self.porta) +" escolhida. Clique em 'Compartilhar' para iniciar.")

    def cancelar(self, widget, data=None):
        if len(self.lista_portas) == 0:
            self.label_conexao.set_text("Não há compartilhamentos a serem cancelados.")
        else:
            for i in self.lista_portas:
                cmd = "fuser -k %s/tcp" % i
                os.system(cmd)
            self.lista_portas = []
            self.label_conexao.set_text("Compartilhamento cancelado.")

    def voltar(self, widget, data=None):
        self.janela.hide()
	j.janela.show()

    def sair(self, widget, data=None):
        gtk.main_quit()

    def erro(self, mensagem):
        e = gtk.MessageDialog(None,  gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, mensagem)
        e.run()
        e.destroy()

    def compartilhar(self, widget, data=None):
        "Valida o arquivo e porta selecionados e fica escutando para enviar."
        if (self.caminho == ""):
            self.erro("Nenhum arquivo escolhido.")
        elif (self.porta == ""):
            self.erro("Nenhuma porta escolhida.")
        elif (not self.porta.isdigit()):
            self.erro("A porta deve conter somente números.")
        elif (self.porta.isdigit()):
            if (int(self.porta) <= 1024):
                self.erro("Número da porta muito baixo.")
            elif (int(self.porta) > 65535):
                self.erro("Número da porta muito alto.")
            else:
                # Libera a porta escolhida pelo usuário
                cmd = "fuser -k %s/tcp 2> /dev/null > /dev/null" % self.porta
                os.system(cmd)

                self.lista_portas.append(self.porta)

                # Mostra pro usuário que a conexão foi iniciada.
                texto = "Compartilhando arquivo '%s'\nna porta %s." % (self.nome_arquivo, self.porta)
                self.label_conexao.set_text(texto)
                
                
                cmd = "nc -q 1 -l -p %s < %s" % (self.porta, self.caminho)
                def nc():
                    netcat =  subprocess.Popen([cmd], stderr=subprocess.PIPE, shell=True)
                    print "aaa"
                    saida, erro = netcat.communicate()
                    print erro
                    if "Address already in use" in erro or "" == erro:
                        nc()
                t=Thread(target=nc)
                t.start()
                #thread.start_new_thread(nc, ())
                print "oi"

################################################################################################################################

class JanelaReceber:
    def __init__(self):
        self.janela = gtk.Window()
        self.janela.set_position(gtk.WIN_POS_CENTER)
        self.janela.set_size_request(480, 480)
        self.janela.set_title("share - Receber um arquivo")
        self.janela.set_resizable(False)
        try:
            self.janela.set_icon_from_file("icone.png")
        except Exception:
            self.icone = self.janela.render_icon(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_MENU)
            self.janela.set_icon(self.icone)
       

        self.label_instrucao = gtk.Label("Digite o IP de quem está compartilhando:")
        self.label_ip = gtk.Label("Nenhum IP escolhido.")
        self.label_instrucao2 = gtk.Label("Escolha uma porta entre 1025 e 65535:")
        self.label_porta =  gtk.Label("Nenhuma porta escolhida.")
        self.label_conexao = gtk.Label("")
        
        self.botao_voltar = gtk.Button("<Voltar".center(30))
        self.botao_voltar.connect("clicked", self.voltar)
        
        self.texto_ip = gtk.Entry(15)
        self.texto_ip.connect("changed", self.escolher_ip)

        self.botao_receber = gtk.Button('Receber'.center(50))
        self.botao_receber.connect('clicked', self.receber_arquivo)

        self.texto_porta = gtk.Entry(5)
        self.texto_porta.connect("changed", self.escolher_porta)

        self.fixo = gtk.Fixed()
        self.fixo.put(self.label_instrucao, 30, 100)
        self.fixo.put(self.label_instrucao2, 30, 150)
        self.fixo.put(self.label_ip, 30, 200)
        self.fixo.put(self.label_porta, 30, 250)
        self.fixo.put(self.label_conexao, 30, 350)

        self.fixo.put(self.texto_ip, 300, 100)
        self.fixo.put(self.texto_porta, 300, 150)
        self.fixo.put(self.botao_receber, 120, 300)
        self.fixo.put(self.botao_voltar, 300, 420)

        self.janela.add(self.fixo)
        self.janela.show_all()

        self.nome_arquivo = ""
        self.ip = ""
        self.porta = ""

        self.IP_OK =  False
        

    def voltar(self, widget, data = None):
	self.janela.hide()
	j.janela.show()
	
    def receber(self):
        print "implementar receber"


    def escolher_ip(self, widget, data=None):
        self.ip = self.texto_ip.get_text()        
        if self.ip == "":
            self.IP_OK = False
            self.label_ip.set_text("Nenhum IP escolhido.")
        elif self.ip == "localhost":
            self.IP_OK = True
            self.label_ip.set_text("Localhost escolhido.")
        elif '.' not in self.ip:
            self.IP_OK = False
            self.label_ip.set_text("Endereço IP inválido.") # Porque não tem pontos.
        elif '.' in self.ip:
            octetos = self.ip.split('.')
            if  len(octetos) < 4:
                self.IP_OK = False
                self.label_ip.set_text("Endereço IP inválido.") # Não tem 4 octetos
            else:
                for byte in octetos:
                    if not byte.isdigit():
                        self.IP_OK = False
                        self.label_ip.set_text("Endereço IP inválido.") # Algum octeto não é numero
                        break
                    elif byte.isdigit():
                        if int(byte) > 255 or '' in octetos:
                            self.IP_OK = False
                            self.label_ip.set_text("Endereço IP inválido.")
                            break
                        else:
                            self.IP_OK = True
                            self.label_ip.set_text("Endereço " + self.ip + " escolhido.")
    
    def escolher_porta(self, widget):
        "Valida a porta a ser escolhida."
        self.porta = str(self.texto_porta.get_text())
        if (self.porta== ""):
            self.label_porta.set_text("Nenhuma porta escolhida.")
        elif (not self.porta.isdigit()):
            self.label_porta.set_text("A porta deve conter somente números.")
        elif (self.porta.isdigit()):
            if (int(self.porta) <= 1024):
                self.label_porta.set_text("Número da porta muito baixo.")
            elif (int(self.porta) > 65535):
                self.label_porta.set_text("Número da porta muito alto.")
            else:
                self.label_porta.set_text("Porta "+ str(self.porta) +" escolhida.")


    def sair(self, widget, data=None):
	gtk.main_quit()

    def erro(self, mensagem):
        e = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, mensagem)
        e.run()
        e.destroy()

    def receber_arquivo(self, widget, data=None):
        if not self.IP_OK:
            self.erro("Endereço IP inválido.")
        else:
            self.porta = str(self.texto_porta.get_text())
            if (self.porta== ""):
                self.erro("Nenhuma porta escolhida.")
            elif (not self.porta.isdigit()):
                self.erro("A porta deve conter somente números.")
            elif (self.porta.isdigit()):
                if (int(self.porta) <= 1024):
                    self.erro("Número da porta muito baixo.")
                elif (int(self.porta) > 65535):
                    self.erro("Número da porta muito alto.")
                else:  
                    # Cria um File Chooser
                    self.fc = gtk.FileChooserDialog("Salvar...", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK))
                    self.fc.set_default_response(gtk.RESPONSE_OK)
                    resposta = self.fc.run()
                    if resposta == gtk.RESPONSE_OK:
                        self.nome_arquivo = self.fc.get_filename()
                        self.fc.destroy()
                        aspas = '"'
                        self.nome_arquivo = aspas + self.nome_arquivo + aspas

                        cmd = "nc -q 1 %s %s > %s" %(self.ip, self.porta, self.nome_arquivo)
                        netcat = subprocess.Popen([cmd], stderr=subprocess.PIPE, shell=True)
                        saida, erro = netcat.communicate()
                        
                        erros = ["Connection refused", "Conexão recusada", "Rede Inalcançável", "Network is unreachable", "No route to host", "Connection timed out"]
                        indice = 0
                        
                        while indice < len(erros):
                            if erros[indice] in erro:
                                self.erro(erros[indice])
                            else:
                                self.label_conexao.set_text("Arquivo " + self.nome_arquivo + "salvo!")
                            indice += 1

                    elif resposta == gtk.RESPONSE_CANCEL:
                        print "nao escolheu"
                    # Destrói o File Chooser
                        self.fc.destroy()

class JanelaPrincipal:
    def __init__(self):
        self.janela = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.janela.set_position(gtk.WIN_POS_CENTER)
        self.janela.set_size_request(480, 480)
        self.janela.set_title("share")
        self.janela.set_resizable(False)
        try:
            self.janela.set_icon_from_file("icone.png")
        except Exception:
            self.icone = self.janela.render_icon(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_MENU)
            self.janela.set_icon(self.icone)


        self.botao_servir = gtk.Button("COMPARTILHAR UM ARQUIVO")
        self.botao_servir.connect("clicked", self.compartilhar)

        self.botao_receber = gtk.Button("RECEBER UM ARQUIVO")
        self.botao_receber.connect("clicked", self.receber)
        
        self.button3 = gtk.Button("AJUDA")
        self.button3.connect("clicked", self.ajuda )

        self.button4 = gtk.Button("SOBRE")
        self.button4.connect("clicked", self.sobre)

        self.button5 = gtk.Button("SAIR")
        self.button5.connect("clicked", self.sair)

        self.caixa = gtk.VBox()

        self.caixa.pack_start(self.botao_servir)
        self.caixa.pack_start(self.botao_receber)
        self.caixa.pack_start(self.button3)
        self.caixa.pack_start(self.button4)
        self.caixa.pack_start(self.button5)

        self.janela.add(self.caixa)
        self.janela.show_all()
        self.janela.connect("destroy", self.sair)

    def main(self):
        gtk.main()

    def sair(self, widget, data=None):
        gtk.main_quit()

    def compartilhar(self, widget, data=None):
	self.janela.hide()
	jc = JanelaCompartilhar()
	jc.janela.show()

    def receber(self, widget, data=None):
	self.janela.hide()        
	jr = JanelaReceber()
	jr.janela.show()

    def ajuda(self, widget, data=None):
        a = gtk.Dialog("share - Ajuda", None, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        label = gtk.Label("\n\n\n" + "Nós quem precisamos de ajuda.".center(70) + "\n\n\n")
        a.vbox.pack_start(label)
        label.show()
        a.run()
        a.destroy()

    def sobre(self, widget):
        s = gtk.AboutDialog()
        s.set_program_name = str(sys.argv[0])
        s.set_version("v0.1")
        s.set_copyright("GPL v3 ou superior")
        s.set_comments("\nPrograma que usa a ferramenta netcat para o compartilhamento simples de arquivos em rede local.\n\nTrabalho para a disciplina de Programação de Scripts\n\n Universidade Federal do Ceará\nCurso: Redes de Computadores\n 4º Semestre\n\nAutores:\nIsac Cavalcante, Maria Micaele, Tiago Nascimento")
        s.set_website("www.algumsite.com")
        s.run()
        s.destroy()

if __name__== "__main__":
    try:
        j = JanelaPrincipal()
        j.main()
    except KeyboardInterrupt:
        print "\nCancelado pelo usuário."