#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, re, mechanize, cookielib, base64, urllib2, time
from www2sms_gui_dialog_captcha import *
from PyQt4 import QtCore, QtGui

def UpdatePbar(self, MainWindow, app, value, label):
	MainWindow.Stat.ui.label.setText(label)
	MainWindow.Stat.ui.progressBar.setProperty("value", value)
	app.processEvents()
    

class ShowCAPTCHA(QtGui.QDialog, Ui_DialogCaptcha):
	def __init__(self, win_parent = None):
		#Init the base class
		QtGui.QDialog.__init__(self, win_parent)
		self.ui = Ui_DialogCaptcha()
		self.ui.setupUi(self)

# Class which holds the provider methods.
class provider():
	# get the printable name for this provider
	def getName(self):
		raise Exception('provider class is a base class only')
	# eventually we will have to separate the advanced features out, and return these as
	# canSchedule(), canSetSender(), canFlash(), but with the current providers these
	# are all either on or off, so we use a single method to describe them
	def hasAdvancedFeatures(self):
		return False
	# send the sms
	def sendSMS(self, app, NUMBER, SMSTEXT, LOGIN, PASSWORD, SCHEDULE=None, SENDER=None, FLASH=None):
		return False, "SMS sending not implemented"

# o2online.de 1.0
class provider_o2online_de(provider):
	def getName(self):
		return 'o2online (Deutschland)'
	def hasAdvancedFeatures(self):
		return True
	def sendSMS(self, MainWindow, app, NUMBER, SMSTEXT, LOGIN, PASSWORD, SCHEDULE=None, SENDER=None, FLASH=None):
		LOGINURL = 'http://www.o2online.de/'
		execute = True
		MainWindow.Stat.ui.progressBar.setMinimum(0)
		MainWindow.Stat.ui.progressBar.setMaximum(10)

		if execute:
			# RegExp to check if SMS was send successfully:
			re_suc = re.compile('Ihre SMS wurde erfolgreich versendet', re.IGNORECASE)
			# RegEx to check if en error occured
			re_fail = re.compile('(Fehler beim Login)|(Error logging in)', re.IGNORECASE)
			# RegExp to find the link to the communication center:
			com = re.compile('comcenter')
			# RegExp to find the sucking CAPTCHA image
			re_cap = re.compile('jcaptchaReg')

			# Instanziate a Browser
			print "Initiating the browser"
			UpdatePbar(self, MainWindow, app, "1", "Initiating the browser")
			brw = mechanize.Browser()

			# Instanziate Cookie Jar
			CoJa = cookielib.LWPCookieJar()
			brw.set_cookiejar(CoJa)

			# Browser options
			#brw.set_handle_gzip(True)
			brw.set_handle_referer(True)
			brw.set_handle_redirect(True)
			brw.set_handle_equiv(True)
			brw.set_handle_robots(False)
			#brw._factory.encoding = "UTF-8"
			#brw._factory._forms_factory.encoding = "UTF-8"
			#brw._factory._links_factory._encoding = "UTF-8"

			# Follows refresh 0 but not hangs on refresh > 0
			brw.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

			# Debugging stuff
			#brw.set_debug_http(True)
			#brw.set_debug_responses(True)
			#brw.set_debug_redirects(True)


			# User-Agent
			# Mozilla
			#br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.6) Gecko/20100105 Gentoo Firefox/3.5.6')]
			# Opera
			brw.addheaders = [('User-agent', 'Opera/9.80 (Linux x86_64; U; en) Presto/2.5.18 Version/10.50 Gentoo')]

			# Open the O2 website
			print "Open Website"
			UpdatePbar(self, MainWindow, app, "2", "Open Website")
			brw.open(LOGINURL)

			# Select the Login form
			print "Select Login Form"
			UpdatePbar(self, MainWindow, app, "3", "Select Login Form")
			brw.select_form(name='loginForm')

			# Get the URL to the Communication Center
			print "Get the URL to the Communication Center"
			UpdatePbar(self, MainWindow, app, "4", "Get the URL to the Communication Center")
			for item in brw.form.find_control("url", type="select").items:
			    if com.search(str(item)):
				COMMURL = str(item)

			# Check that COMURL is not empty
			print "Check that COMURL is not empty"
			UpdatePbar(self, MainWindow, app, "5", "Check that COMURL is not empty")
			try:
			    COMMURL
			except:
			    raise Exception("Failed to get URL to Communication Center")

			# Fill in User credentials
			print "Fill in User credentials"
			UpdatePbar(self, MainWindow, app, "6", "Fill in User credentials")
			brw.form['loginName'] = LOGIN
			#brw.form['password'] = base64.b64decode(PASSWORD)
			brw.form['password'] = PASSWORD
			brw.form['url'] = [COMMURL]
			#brw.form.set_value([COMMURL], name="url")

			# Login
			print "Loging in"
			UpdatePbar(self, MainWindow, app, "7", "Loging in")
			try:
				brw.submit()
			except:
				STATUS = False
				MSG = "Login fehlgeschlagen"
				return STATUS, MSG
				raise Exception("Login fehlgeschlagen")

			result = brw.response().read()
			#print result
			#log = open("submit.html", "w")
			#log.write(str(result))
			#log.close()

			#check for CAPTCHA
			print "CAPTCHA-Check"
			UpdatePbar(self, MainWindow, app, "8", "CAPTCHA-Check")
			while re_cap.search(str(result)):
				#Instaciate the CAPTCHA dialog
				sc = ShowCAPTCHA()

				## Download the CAPTCHA with urllib2
				#current_url = brw.geturl()
				#base_url = current_url[:current_url.rfind("/")]
				#dl_captcha = urllib2.urlopen("%s/jcaptchaReg" %(base_url))
				#qimg = QtGui.QImage.fromData(dl_captcha.read())
				#pixmap = QtGui.QPixmap.fromImage(qimg)

				## Download the CAPTCHA with urllib2 and save to jpg
				#current_url = brw.geturl()
				#base_url = current_url[:current_url.rfind("/")]
				#dl_captcha = urllib2.urlopen("%s/jcaptchaReg" %(base_url))
				#captcha = open("captcha.jpg", 'wb')
				#captcha.write(dl_captcha.read())
				#captcha.close()
				#pixmap = QtGui.QPixmap('captcha.jpg')

				## Download CAPTCHA with mechanize
				current_url = brw.geturl()
				base_url = current_url[:current_url.rfind("/")]
				dl_captcha = brw.open("%s/jcaptchaReg" %(base_url)).read(4096*10)
				qimg = QtGui.QImage.fromData(dl_captcha)
				pixmap = QtGui.QPixmap.fromImage(qimg)
				brw.back()

				## Download CAPTCHA with mechanize and save to file
				#current_url = brw.geturl()
				#base_url = current_url[:current_url.rfind("/")]
				#dl_captcha = brw.open("%s/jcaptchaReg" %(base_url)).read(4096*10)
				#captcha = open("captcha.jpg", 'wb')
				#captcha.write(dl_captcha)
				#captcha.close()
				#pixmap = QtGui.QPixmap('captcha.jpg')

				#Set captcha.jpg to show up in the CAPTCHA dialog
				sc.ui.label_captcha.setPixmap(pixmap)
				def getcaptcha():
					self.captchatext = unicode(sc.ui.lineEdit_captcha.text())
				QtCore.QObject.connect(sc.ui.buttonBox_Captcha, QtCore.SIGNAL("accepted()"), getcaptcha)
				sc.show()
				sc.exec_()
				brw.select_form(name='riddle')
				print self.captchatext
				brw.form["riddleValue"] = self.captchatext
				try:
					brw.submit()
				except:
					STATUS = False
					MSG = "Kommunikationsfehler"
					return STATUS, MSG
					raise Exception("Kommunikationsfehler")

				result = brw.response().read()
				if re_cap.search(str(result)):
					reply = QtGui.QMessageBox.question(MainWindow, 'CAPTCHA verifikation fehlgeschlagen!', "Nochmal versuchen?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
					if reply == QtGui.QMessageBox.No:
						STATUS = False
						MSG = "CAPTCHA verifikation abgebrochen durch User"
						return STATUS, MSG
						raise Exception("UserQuitCaptchaVerification")


			if re_fail.search(str(result)):
				STATUS = False
				MSG = "Login fehlgeschlagen oder nicht registriert"
				return STATUS, MSG
				raise Exception("Login fehlgeschlagen oder nicht registriert")

			# Open the SMS Center (ISO-8859-1)
			print "Open the SMS Center"
			UpdatePbar(self, MainWindow, app, "9", "Open the SMS Center")
			brw.open('https://email.o2online.de/smscenter_new.osp')
			res = brw.response()
			ENCODING = res.info()["Content-type"].split()[1].split("=")[1]

			try:
				print "Select SMS form"
				brw.select_form(name='frmSMS')
			except:
				STATUS = False
				MSG = "Failed to select form"
				return STATUS, MSG
				raise Exception("Failed to select form")

			brw.form.set_all_readonly(False)
			brw.form['SMSTo'] = NUMBER
			brw.form['SMSText'] = SMSTEXT
			if FLASH :
				print "Sending Flash SMS"
				brw.form['FlagFlash'] = '1'
			if SENDER == "Anonym" :
				print "Sending Anonymous SMS"
				brw.form['FlagDefSender'] = '1'
				brw.form['FlagAnonymous'] = '1'
			if SENDER != "MyNumber" and SENDER != "Anonym" :
				print "Sending SMS with \"%s\" as sender" %(SENDER)
				brw.form['FlagDefSender'] = '1'
				brw.form['SMSFrom'] = str(SENDER)
			if SCHEDULE :
				print "Scheduling SMS"
				StartDate = '%s,%s,%s,%s,%s,%s' %(str(SCHEDULE[1][0]), str(SCHEDULE[2][0]), str(SCHEDULE[3][0]), str(SCHEDULE[4][0]), str(SCHEDULE[5][0]), '00')
				StopDate = '%s,%s,%s,%s,%s,%s' %(str(SCHEDULE[1][1]), str(SCHEDULE[2][1]), str(SCHEDULE[3][1]), str(SCHEDULE[4][1]), str(SCHEDULE[5][1]), '00')
				# See sourcecode of  the webpage for the mapping:
				#<option value="5">einmalig
				#<option value="6">stündlich
				#<option value="1">täglich
				#<option value="2">wöchentlich
				#<option value="3">monatlich
				#<option value="4">jährlich
				Frequency_Dict = {'Daily' : '1', 'Weekly' : '2', 'Monthly': '3', 'Yearly' : '4', 'Once' : '5',  'Hourly' : '6'}
				FQ = str(Frequency_Dict[SCHEDULE[0][0]])
				brw.form['RepeatType'] = FQ
				brw.form['FolderID'] = '3'
				brw.form['RepeatStartDate'] = StartDate
				if SCHEDULE[0][1] :
					print "Setting end date to scheduling"
					brw.form['RepeatEndType'] = '1'
					brw.form['RepeatEndDate'] = StopDate
			try:
				print "Send SMS"
				UpdatePbar(self, MainWindow, app, "10", "Send SMS")
				brw.submit()
				result = brw.response().read()
				if re_suc.search(str(result)):
					STATUS = True
					MSG = 'Provider responded: Ihre SMS wurde erfolgreich versendet'
				else:
					STATUS = False
					MSG = 'Provider responded: Ihre SMS wurde nicht versendet'
			except :
				STATUS = False
				MSG = 'Übertragung fehlgeschlagen'
			MainWindow.Stat.close()
			return STATUS, MSG
			#--------FORM=3------------
			#<frmSMS POST https://email.o2online.de/smscenter_send.osp application/x-www-form-urlencoded
			#<HiddenControl(SID=92227538_eqdujvat) (readonly)>
			#<HiddenControl(MsgContentID=-1) (readonly)>
			#<HiddenControl(FlagDLR=0) (readonly)>
			#<HiddenControl(FlagFlash=0) (readonly)>
			#<HiddenControl(FlagAnonymous=0) (readonly)>
			#<HiddenControl(FlagDefSender=0) (readonly)>
			#<HiddenControl(FlagVCal=0) (readonly)>
			#<HiddenControl(FlagVCard=0) (readonly)>
			#<HiddenControl(CID=-1) (readonly)>
			#<HiddenControl(DID=-1) (readonly)>
			#<HiddenControl(RepeatStartDate=2010,1,6,16,45,00) (readonly)>
			#<HiddenControl(RepeatEndDate=2010,1,6,16,45,00) (readonly)>
			#<HiddenControl(RepeatType=0) (readonly)>
			#<HiddenControl(RepeatEndType=0) (readonly)>
			#<HiddenControl(FolderID=0) (readonly)>
			#<HiddenControl(SMSToNormalized=) (readonly)>
			#<HiddenControl(FID=) (readonly)>
			#<HiddenControl(RURL=smscenter_new.osp?Autocompletion=1&SID=92227538_eqdujvat&MsgContentID=-1&REF=1262792073) (readonly)>
			#<HiddenControl(REF=1262792073) (readonly)>
			#<TextareaControl(SMSTo=)>
			#<TextareaControl(SMSText=)>
			#<TextControl(SMSFrom=)>
			#<SelectControl(Frequency=[*5, 6, 1, 2, 3, 4])>
			#<SelectControl(StartDateDay=[*01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])>
			#<SelectControl(StartDateMonth=[*01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12])>
			#<SelectControl(StartDateYear=[*2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015])>
			#<SelectControl(StartDateHour=[*00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])>
			#<SelectControl(StartDateMin=[*00, 15, 30, 45])>
			#<SelectControl(EndDateDay=[*01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])>
			#<SelectControl(EndDateMonth=[*01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12])>
			#<SelectControl(EndDateYear=[*2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015])>
			#<SelectControl(EndDateHour=[*00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23])>
			#<SelectControl(EndDateMin=[*00, 15, 30, 45])>>
			#---------------------------

# vodafone.nl 1.0
class provider_vodafone_nl(provider):
	def getName(self):
		return 'Vodefone Nederland'
	def hasAdvancedFeatures(self):
		return False
	def sendSMS(self, MainWindow, app, NUMBER, SMSTEXT, LOGIN, PASSWORD, SCHEDULE=None, SENDER=None, FLASH=None):
		# TODO: synchronize number verification with main code (UpdateChars() perhaps?)
		# TODO: block SMS longer than 1 message
		# TODO: enforce maximum SMS size of 125 characters (*not* 160)
		# TODO: check whether sending worked
		# TODO: handle "2 per day maximum"
		# TODO: localization support (at least English and Dutch)

		# get rid of whitespace and dots
		number = re.sub(r'(\s|\.)+', '', NUMBER)

		# handle a couple of number formats (only mobile numbers allowed)
		if re.search(r'^\+316\d{8}$', number):	# ITU format, +31 is the Netherlands
			number = number[3:]
		elif re.search(r'^06\d{8}$', number):	# local dialing format
			number = number[1:]
		else:
			return False, 'Only Dutch mobile phone numbers allowed'

                # XXX: GUI manipulation
		MainWindow.Stat.ui.progressBar.setMinimum(0)
		MainWindow.Stat.ui.progressBar.setMaximum(8)

		# set up our browser
		UpdatePbar(self, MainWindow, app, "1", "Initiating the browser")
		br = mechanize.Browser()
		cj = cookielib.LWPCookieJar()
		br.set_cookiejar(cj)

		# login
		try:
			UpdatePbar(self, MainWindow, app, "2", "Connecting to login page")
			br.open('https://my.vodafone.nl/prive/my_vodafone')
			UpdatePbar(self, MainWindow, app, "3", "Logging in")
			br.select_form(name='login')
			br.form['username'] = LOGIN
			br.form['password'] = PASSWORD
			br.submit()
		except:
			return False, "Error logging in"


		# verify our login worked and return error if not
	   	UpdatePbar(self, MainWindow, app, "4", "Checking login")
		br.response().read()
		try:
			br.find_link(text='Uitloggen')
		except mechanize.LinkNotFoundError:
			return False, 'Login failed'

		# send the SMS
   	        UpdatePbar(self, MainWindow, app, "5", "Opening SMS page")
		try:
			br.open('https://my.vodafone.nl/Prive/My_Vodafone/gratis_sms_versturen')
		except:
			return False, 'Error opening free SMS web page'
   	        UpdatePbar(self, MainWindow, app, "6", "Checking maximum SMS per day")
		response = br.response().read()
		if re.search(r'Je hebt het maximum aantal gratis SMS\'jes bereikt voor vandaag.', response):
			return False, "Provider responded: Je hebt het maximum aantal gratis SMS'jes bereikt voor vandaag."

   	        UpdatePbar(self, MainWindow, app, "7", "Sending SMS")
		try:
			br.select_form(name='controle')
			br.form['phoneNumber'] = number
			br.form['body'] = SMSTEXT
			br.submit()
		except:
			print response
			return False, 'Error submitting SMS form'

		# check to see if our send worked
   	        UpdatePbar(self, MainWindow, app, "8", "Confirming SMS sent")
		response = br.response().read()
		if re.search(r'Je sms\'je is verstuurd.', response):
			return True, "Provider responded: Je sms'je is verstuurd."
		elif re.search(r'Je hebt het maximum aantal gratis SMS\'jes voor vandaag verstuurd.', response):
			return False, "Provider responded: Je hebt het maximum aantal gratis SMS'jes voor vandaag verstuurd."
		else:
			return False, 'Message not sent'
        	MainWindow.Stat.close()
