#!/bin/bash

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

# (c) Antonio Sánchez León <introlinux[fix@]gmail[fix.]com>
# (c) Miguel Anxo Bouzada <mbouzada[fix@]gmail[fix.]com>
# (c) GALPon MinNo Team <minino[fix@]galpon[fix.]org>
# july 2012

## -

##########################################################################################
##											##
## 				Forma de uso de este script				##
##											##
## Debe ejecutarse con permisos de root (su, sudo, gksu, gksudo)			##
##											##
## Dependencias: macchanger, yad							##
##											##
##########################################################################################

export TEXTDOMAIN="mac-spoof"
export TEXTDOMAINDIR="/usr/local/share/locale"

DIRICON="/usr/local/share/icons"

## Inicializar

#nos aseguramos de que no haya quedado ningún fichero basura de un proceso anterior interrumpido
[ -f /tmp/estadoMAC* ] && rm /tmp/estadoMAC*
[ -f /tmp/estadoMAC* ] && rm /tmp/estadoMAC*

## Definir funciones

# Se ejecuta si NO existe yad
function displayQuejaYad(){
	xmessage -fg darkred -center "$(gettext "This program needs YAD
(Yet Another Display) to show dialogs.

Install it with \"apt-get install yad\".")"
[ $? == 0 ] || [ $? == 1 ] && exit
}

# Se ejecuta si NO existe macchanger
function displayQuejaMacchanger(){
	yad --window-icon $DIRICON/mac-spoof.png --title "$(gettext "ERROR")" \
	    --image important --button gtk-ok:0 \
	    --text "$(gettext "\"macchanger\" needs to be installed to run MAC Spoof.\nInstall it with \"apt-get install macchanger\".")"
	exit
}

# Se ejecuta si NO se accede como root
function displayQuejaRoot(){
	yad --window-icon $DIRICON/mac-spoof.png --title "$(gettext "ERROR")" \
	    --image important --button gtk-ok:0 \
	    --text "$(gettext "MAC Spoof requires <b>root</b> priviledges!\n\nBe careful!")"
	exit
}

function aplyCommand(){
	ifconfig $DISP down

	macchanger $MODO $DISP > $FICH

	ifconfig $DISP up
	[ -x /etc/init.d/network-manager ] && service network-manager restart

	NEW=`cat $FICH | grep It`
		if [ "$NEW" == "It's the same MAC!!" ]; then NEW="$(gettext "It's the same MAC!!")"
		else NEW=`cat $FICH  | grep New | cut -f9 -d" "`
		fi
			#' pongo aquí un « \' » para corregir la visualización por culpa del apóstrofe de "It's" en el mensaje
	[ "$NEW" == "" ] && NEW=`cat $FICH  | grep Faked | cut -f5 -d" "`
	[ "$NEW" == "" ] && NEW="$(gettext "<b>Option not available</b>\n\twith this version of\n\t\"macchanger\"")"

	# Notificación final de cambios efectuados
	yad --window-icon $DIRICON/mac-spoof.png --title $(gettext "MAC Spoof") \
	    --image $DIRICON/mac-spoof.png --button gtk-ok:0 \
	    --text " $(gettext "The MAC of") <b>$DISP</b> $(gettext "was changed") \n $VARTEXT \n
	    \n $(gettext "The new MAC is:")\n\t$NEW"

	# Limpiamos ficheros temporales
	[ -f /tmp/estadoMAC$$ ] && rm /tmp/estadoMAC$$

	exit
}

# Cuando en la función «manualIntro» la MAC no sigue una estructura
# correcta devuelve a este mensaje y retorna para su nueva ejecución
function malformedEntry(){
	yad --window-icon $DIRICON/mac-spoof.png --title "$(gettext "ERROR")" \
	    --image $DIRICON/mac-spoof.png --text "$(gettext "The MAC entered does not follow any of the structures: \n\n\t<b>FF:FF:FF:FF:FF:FF</b>\n\t<i>Six Hexadecimal Pairs separated by colons </i>\n\n\t<b>FF-FF-FF-FF-FF-FF</b>\n\t<i>Six Hexadecimal Pairs separated by hyphens </i>\n\n\t<b>FFFFFFFFFFFF</b>\n\t<i>Six Hexadecimal Pairs without separators </i>\n\n<b>Please try again.</b>")"
	[ $? != 0 ] && exit
	manualIntro
}

# Mensaje de error cuando hay un par no hexadecimal
function messageErrorPair(){
	yad --window-icon $DIRICON/mac-spoof.png --title "$(gettext "ERROR")" \
	    --image $DIRICON/mac-spoof.png --text "$(gettext "There is an error in the MAC entry, \nhas at least one incorrect hex value. \n\n<b>Please try again.</b>")"
	[ $? != 0 ] && exit
	manualIntro
}

# Convertimos una entrada de seis pares sin separador a separados por «:»
function convertFormatWithoutColons(){
	echo $MAC > /tmp/tempMAC

	P1=`cut -c1,2 /tmp/tempMAC`
	P2=`cut -c3,4 /tmp/tempMAC`
	P3=`cut -c5,6 /tmp/tempMAC`
	P4=`cut -c7,8 /tmp/tempMAC`
	P5=`cut -c9,10 /tmp/tempMAC`
	P6=`cut -c11-12 /tmp/tempMAC`

	MAC="$P1:$P2:$P3:$P4:$P5:$P6"

	rm /tmp/tempMAC
}


# Convertimos una entrada de seis pares separados por «-» a separados por «:»
function convertFormatWithHyphen(){
	echo $MAC > /tmp/tempMAC
	P1=`cut -c1,2 /tmp/tempMAC`
	P2=`cut -c4,5 /tmp/tempMAC`
	P3=`cut -c7,8 /tmp/tempMAC`
	P4=`cut -c10,11 /tmp/tempMAC`
	P5=`cut -c13,14 /tmp/tempMAC`
	P6=`cut -c16,17 /tmp/tempMAC`

	MAC="$P1:$P2:$P3:$P4:$P5:$P6"

	rm /tmp/tempMAC
}

# Rutina que solicita la MAC personalizada
# si MAC == "" o si se pulsa en "Volver atrás" lanza de nuevo
# la rutina previa que solicita los parámetros para macchanger
# Cuando la MAC no sigue la estructura FF:FF:FF:FF:FF:FF
# devuelve a la entrada con un mensaje en la función anterior
function manualIntro(){
	[ -f ~/.macspoof ] && CUSTOM=`cat ~/.macspoof`
	MAC=$(yad --entry --window-icon $DIRICON/mac-spoof.png --title "$(gettext "Custom MAC")" --entry-text "$CUSTOM" --entry-label MAC: \
	--image $DIRICON/mac-spoof.png --button "$(gettext "_Go Back")":2 --button gtk-cancel:1 --button gtk-ok:0 \
	--text "$(gettext "Type your custom MAC.\n\nRemember, the format must be one of the following: \n\n\t<b>01:23:45:67:89:ab</b>\n\t<i>Six Hexadecimal Pairs separated by colons </i> \n\n\t<b>01-23-45-67-89-ab</b>\n\t<i>Six Hexadecimal Pairs separated by hyphens </i>\n\n\t<b>0123456789ab</b>\n\t<i>Six Hexadecimal Pairs without separators </i>\n")" ) 
	ret=$?

	[ $ret = 1 ] || [ $ret = 252 ] && exit
	[ $ret = 2 ] && entryCommand # Cuando se pulsa el botón «Go Back»
	[ "$MAC" == "" ] && entryCommand # Si no se escribió nada, Envía a la función para solicitar la MAC personalizada

	#Convertimos formatos si es necesario
	[[ "$MAC" == ???????????? ]] && convertFormatWithoutColons
	[[ "$MAC" == ??-??-??-??-??-?? ]] && convertFormatWithHyphen

	[[ $MAC != ??:??:??:??:??:?? ]] && malformedEntry

	# Comprobación de formato hexadecimal de los pares de la cadena MAC
	TEST=`echo "$MAC" | sed -n '/\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}/ p'`
	[ "$TEST" == "" ] && messageErrorPair

	echo $MAC > ~/.macspoof 
	MODO="--mac=$MAC" 
	VARTEXT="$(gettext "with the customized MAC. ")"
	aplyCommand
}

# Rutina que ejecuta las ordenes de macchanger
# lo primero que se hace es rectificar la orden, tal y como la entrega
# yad, para convertirla en la correcta. Después se asigna el mensaje que
# corresponde a cada acción para ser usado en el mensaje final
# En el caso de "m|" se va a la rutina anterior, que solicita la MAC personalizada
function executeMacChanger(){
	[ "$MODO" == "r|" ] && MODO="--random" && VARTEXT="$(gettext "with a random one. ")" && aplyCommand
	[ "$MODO" == "e|" ] && MODO="--ending" && VARTEXT="$(gettext "preserving the vendors bytes. ")" && aplyCommand
	[ "$MODO" == "p|" ] && MODO="--permanent" && VARTEXT="$(gettext "with the permanent MAC. ")" && aplyCommand
	[ "$MODO" == "m|" ] && manualIntro # Envía a la función para solicitar la MAC personalizada
	[ "$MODO" == "" ] && yad --window-icon $DIRICON/mac-spoof.png --image important --title "$(gettext "ERROR")" \
				 --text "$(gettext "No change MAC mode selected. \nRelaunch change mode?")"
			[ $? = 0 ] && entryCommand # Si no se seleccionó nada, Envía a la función para solicitar selección
			[ $? != 0 ] && exit
}

# Rutina que solicita los parámetros para macchanger
function entryCommand(){
	MODO=$(yad --window-icon $DIRICON/mac-spoof.png --title "$(gettext "MAC Spoof")" \
		--image $DIRICON/mac-spoof.png --width 350 --height 250 \
		--text "\n$(gettext "The permanent MAC is: ")\t$PERM\n$(gettext "The current MAC is:   ")\t$CURR\n\n<b>$(gettext "Change mode")</b>" \
		--list --print-column 1 ---no-headers \
		--column control --column accion:tip --hide-column 1 \
		r "$(gettext "Set fully random MAC.")" \
	    	e "$(gettext "Don't change the vendor bytes.")" \
		p "$(gettext "Recover the permanent MAC.")" \
		m "$(gettext "Enter the MAC manually")")
			#' pongo aquí un « \' » para corregir la visualización por culpa del apóstrofe de "Don't" en el mensaje
	[ $? != 0 ] && exit

	executeMacChanger # Ejecutamos esta función para ejecutar la opción elegida
}

## Comprobaciones al inicio

[ ! -x /usr/bin/yad ] && displayQuejaYad

[ ! -x /usr/bin/macchanger ] && displayQuejaMacchanger

[ $(whoami) != "root" ] && displayQuejaRoot

# Buscamos que dispositivos hay instalados
DISPOSITIVOS=$(cat /proc/net/dev | tail -n +3 | cut -f1 -d: | grep -v lo)

## Iniciamos la ejecución

# Selección de dispositivo sobre el que hacer el cambio
DISP=$(yad --entry --window-icon $DIRICON/mac-spoof.png \
    --title "$(gettext "MAC Spoof")" \
    --image $DIRICON/mac-spoof.png \
    --text "<b>$(gettext "Select your device.")</b>" \
    --width 230 --height 110 --entry-text $DISPOSITIVOS)
[ $? != 0 ] && exit

# Creamos un fichero temporal para listar las MAC
# Al final creamos un mensaje cuando se repite la MAC.
# Esto puede suceder cuando ya tenemos asignada la MAC permanente
# y le pedimos que recupere la MAC permanente
FICH="/tmp/estadoMAC$$"

macchanger $DISP > $FICH

PERM=`cat $FICH  | grep Permanent | cut -f3 -d" "`
CURR=`cat $FICH  | grep Current | cut -f5 -d" "`

[ "$PERM" == "" ] && PERM="$(gettext "<i>Unknow</i>")"
[ "$CURR" == "" ] && CURR=`cat $FICH  | grep Current | cut -f3 -d" "`

# execute functions
entryCommand #Iniciamos el proceso, eligiendo la orden a aplicar

EOF
