#!/usr/bin/env python
# SuperSMS 1.1
# By Juanjo Álvarez <juanjux@yahoo.es> Programador principal
#    Fermín Martínez <ferkys@softhome.net> A veces programa cositas wapas
# Gracias a:
#    Azrael: La idea surgió viendo el WinSMS y los drivers los suelo
#            hacer basándome en capturas de red de su programa
#    Gerald Combs  <gerald@ethereal.com> Por su fantástico Ethereal que me
#                   permite ver todo lo que entra y sale por los chips
#                   de mi ethernet.

""" 
Agenda: Archivo .esmsalias en el directorio de usuario (si, se cambiará 
más adelante para hacerlo portable con el formato:

nombre     numero
otronombre otronumero

En sistemas no Unix (sí, se escribe así) la agenda es el archivo "AgendaSMS" 
en el mismo directorio que el script, sin embargo esto aún no lo he probado 
en ningún sistema que no sea Linux.
"""

"""
Posibles mejoras:

* Que acepte el mensaje por la entrada estándar: fortunes|supersms.py
* Meter los drivers en otro archivo. En este caso ya hay que asegurarse
  de meter el archivo de drivers en el path de Python y no es tán cómodo 
  como "bajar y ejecutar".
* Un histórico de mensajes enviados, para poder reenviarlos. Esto 
  podría implementarse con un parámetro que muestre una lista de los x
  últimos mensajes enviados con un numerito por cada uno y las primeras
  palabras, y de la opción de reenviar al mismo telefono o enviar a otro
  teléfono
* Más drivers 
* Un archivo de configuración donde se pueda especificar el driver por
  defecto, si numeramos o no los mensajes, y alguna chorradilla más.
"""

""" 
Cambios:

1.2.1  Añado el servidor de Navegalia y arreglo el de Movistar, Mensajedirecto 
       deja de funcionar :(
1.2    Admite el número o el nombre como parámetro (en ese caso no pregunta)

"""
REINTENTOS = 5

import os
import string, time, sys, pwd, socket, getopt, httplib,urllib
if os.name == 'posix':
	import pwd

# Sección de Drivers (algún dia iran en otro archivo)

def interact(h, refererurl, posturl, host, postdata, cook=None, success_str=''):
	h.putrequest("POST", posturl)
	h.putheader('Referer', refererurl)
	h.putheader('Host', host)
	h.putheader("Content-length", '%d' % len(postdata))
	h.putheader('Accept', 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*')
	h.putheader('Accept-Language', 'es')
	h.putheader('Content-Type', 'application/x-www-form-urlencoded')
	h.putheader('Accept-Encoding', 'gzip, deflate')
	h.putheader('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)')
	h.putheader('Connection', 'Keep-Alive')
	h.putheader('Pragma', 'no-cache')
	if cook != None:
		h.putheader('Cookie', '%s' % cook) #Ojo que tiene q venir digerida
	h.endheaders()
	h.send(postdata)
	reply, msg, headers = h.getreply()
	data = h.getfile().read()
	if data.rfind(success_str) != -1:
		print 'El mensaje se envio correctamente'
		return 1
	else:
		print 'Se produjo un error al enviar el mensaje'
		print 'Respuesta:'
		print data
		return 0

class navegalia:
	def __init__(self):
		self.tamanio = 125

	def envia(self, cadena, telefono, longitud):
		g = httplib.HTTP('212.73.32.207:80')
		g.putrequest('GET', 'http://212.73.32.207/html/texto.htm')
		g.endheaders()
		g.getreply()
		dat = g.getfile().read()

		pos = string.find(dat, '<form name="envio_sms"')
		action = dat[pos+31:pos+77]
		
		pos = string.find(dat, 'name="estado1"')
		estado1 = dat[pos+36:pos+46]
		
		pos = string.find(dat, 'name="estado2"')
		estado2 = dat[pos+36:pos+46]

		cadparams = urllib.urlencode({'estado1':estado1, 'estado2': estado2, 'telefonoDestino1': telefono, 'codigoLookFeel': '1', 'tNumber': '', 'nAddress': '', 'texto': cadena})
		
		print 'Esperando 4.5 segundos para que el servidor no se mosquee...'
		time.sleep(4.5)
		
		ip = action[7:20] + ':80'
		purl = action[20:46]
		h = httplib.HTTP(ip)
		
		return interact(h, refererurl='http://212.73.32.207/html/texto.htm?'+telefono, posturl=purl, host='212.73.32.207', postdata=cadparams, cook=None, success_str='" se está procesando correctamente')
									
class mensajedirecto: # No pirula
	def __init__(self):
		self.tamanio = 120

	def envia(self, cadena, telefono, longitud):
		g = httplib.HTTP('209.25.191.127:80')
		g.putrequest('GET', 'http://www.mensajedirecto.com/index.php?ver=sms' )
		g.endheaders()
		g.getreply()
		del g

		cadparams = urllib.urlencode({'ver': 'sms', 'caracteres': '130', 'num':  telefono, 'men': cadena})
		h = httplib.HTTP("213.96.106.133:80")
		return interact(h, refererurl='http://www.mensajedirecto.com/index.php?ver=sms', posturl='/smse.php', host='www2.mensajedirecto.com', postdata=cadparams, cook=None, success_str='enviado correctamente')
		
class movistar:
	def __init__(self):
		self.tamanio = 154

	def envia(self, cadena, telefono, longitud):
		g = httplib.HTTP('194.224.100.123:80')
		g.putrequest('GET', 'http://www.activajoven.tsm.es/enviar_mensajes.asp')
		g.endheaders()
		cabs = g.getreply()[2]
		dat = g.getfile().read()		
		try:
			cookie = cabs.getrawheader('Set-Cookie').split(';')[0]
		except AttributeError: 
			print 'No se pudo envíar mensaje:\n',dat
			time.sleep(2)
			return 0

		cadparams = 'nocache='+'12%2F31%2F25+11%3A59%3A59+PM&'+urllib.urlencode({'confirmacion': '1', 'telefono': telefono, 'email': '', 'mensaje_texto': cadena})

		h = httplib.HTTP("194.224.100.123:80")
		print 'Esperando un poquito para que el servidor no se mosquee...'
		time.sleep(4.5)
		return interact(h, refererurl='http://www.activajoven.tsm.es/enviar_mensajes.asp', posturl='/confirmacion_envio.asp', host='www.activajoven.tsm.es', postdata=cadparams, cook='%s;r' % cookie, success_str='con éxito')

#----------------------------------------------------------		
class Main:
	VERSION='1.2'
	
	def __init__(self):
		self.driver = None
		self.numero_nombre = ''
		self.repetir = 1
		self.mensaje = ''
		
	def pideNumero(self,dado):
		if dado == '':
			numero = raw_input('Número de teléfono o nombre: ')
		else: numero = dado
		
		try:
			int(numero)
			return (numero.strip(), 0)
		except ValueError:
			try: 
				if os.name != 'posix':
					aliaspath = 'AgendaSMS'
				else:
					(foo, foo, foo, foo, foo, homedir, foo) = pwd.getpwuid(os.getuid() )
					del foo
					aliaspath = os.path.join(homedir, '.esmsalias')
				aliasfile = open(aliaspath) 
				datos = aliasfile.readlines()
			except IOError: print 'Error abriendo agenda'
			for i in datos:
				tokens = string.split(i)
				if tokens[0] == numero:
					return (tokens[1],1)
			print 'Error: Nombre no encontrado'
			sys.exit(1)

	def lineaComandos(self):
		optlist, args = [], []
		short_opts = 'njhrmd'
		long_opts = ['navegalia',
					 'movistar',
					 'mensajedirecto',
					 'help',					 
					 'repetir=']
		try:
			optslist, args = getopt.getopt(sys.argv[1:], short_opts, long_opts)
			
			for cmdline, value in optslist:
				if cmdline in ['-n', '--navegalia']:
					self.driver = navegalia()
				elif cmdline in ['-d', '--mensajedirecto']:
					self.driver = mensajedirecto()
				elif cmdline in ['-m', '--movistar']:
					self.driver = movistar()
				elif cmdline in ['-h', '--help']:
					self.usage()
				elif cmdline in ['-r', '--repetir']:
					self.repetir = int(value)
			try:
				self.numero_nombre = args[0]
				self.mensaje = args[1]
			except IndexError: pass

					
		except getopt.error, x:
			print "Error: " + str(x)
			self.usage()
			sys.exit(1)
		if self.driver == None:
			self.driver = movistar()
			#self.driver = enviasms()
			#self.driver = navegalia()



	def usage(self):
		print "SuperSMS.py Versión " + self.VERSION
		print "Uso:"
		print "-j o --jumpy: Envía el mensaje utilizando Jumpy.es (por defecto)"
		print "-m o --mensajedirecto: Envía el mensaje utilizando MensajeDirecto.com"
		print "-t o --terra: Envía el mensaje utilizando Terra.es"
		print "-h o --help: Muestra esta ayuda"
		sys.exit(0)
	

	def main(self):
		self.lineaComandos() #Selecciona el driver
		(numero, agenda) = self.pideNumero(self.numero_nombre)

		texto = ''
		
		if agenda: print 'Número encontrado en la agenda: ', numero
		else:      print 'Mensaje para el número: ', numero
		
		if self.mensaje:
			texto = self.mensaje
		else:
			print 'Introduzca el mensaje, termine con Control+D:'
			try:
				while 1:
					texto_tmp = raw_input()
					texto += texto_tmp + ' '
			except EOFError: pass
		
		list_msg = []
		len_msg = len(texto)
		num_tokens = (len_msg/self.driver.tamanio)+1
		
		for i in range(num_tokens):
			list_msg.append(texto[self.driver.tamanio*i:self.driver.tamanio*(i+1)])
			
		list_msg.reverse()
		count = 0
		#while self.repetir:	
		for j in list_msg:
			count += 1
			cadena_num = '(' + str(len(list_msg) - count + 1) + '/' + str(len(list_msg)) + ')' 
			fragmento = cadena_num + j
			print '\n*****MENSAJE****: ',fragmento,'\n'
			longitud = len(fragmento)
			
			insistir = REINTENTOS
			
			while (not self.driver.envia(fragmento, numero, longitud)) and insistir:
				print 'Reintentando... (quedan',insistir,'intentos)'
				insistir-=1
			
			#self.repetir -= 1

M = Main()			
M.main()
