#!/bin/bash

###########################################################################
#
#	Shell program to serve as a Mutt Address Book.
#
#	Copyright 2001, USM Bish,<bish@nde.vsnl.net.in>.
#
#	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 2 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.
#
#	Description: Uses abook database in  user's  home directory to
#       get addresses, and then compose under mutt, after  getting the
#       To: and Cc: fields. Subsequently, ver 0.3  added  support  for
#       pine address database. Thereafter, with ver 0.4, native  maddb
#       database support has been added to make this script self suff-
#       icient. It is now possible to add and delete addresses from an
#       existing database through command  line  switches. Support for
#       abook and pine addressbook databases has been retained.
#
#	Revisions:
#
#	Oct/20/2001	File created          .... ver 0.1
#       Oct/21/2001     dialog interface      .... ver 0.2
#                       support for abook db 
#       Oct/23/2001     support for pine      .... ver 0.3
#                       addressbook
#       Oct/27/2001     Uses own addr db      .... ver 0.4
#                       as well  
#
###########################################################################

###########################################################################
# User configurable variables
###########################################################################

#### Ver 0.3 adds support for two types of databases, either abook or pine
#### addressbook. Ver 0.4 also supports its own madbk format for database.
#### Please comment out one of the options below. Only one database can be
#### accessed at one time, so you  need to  choose  between abook, pine or 
#### madbk formats

#### Specify your address database, either 'abook', 'pine' or 'madbk'
#### Only ONE option needs uncommenting in DATABASE and ADDR_DB

#### Uncomment ONE of these for address format
# DATABASE=abook
# DATABASE=pine
DATABASE=madbk

#### Uncomment ONE of these for database file
# ADDR_DB=~/.abook.addressbook  #If abook database
# ADDR_DB=~/.addressbook        #If pine database
ADDR_DB=~/.madbk.addr           #If madbk database

###########################################################################
#	Constants
###########################################################################

PROGNAME=$(basename $0)
VERSION="0.4"

TEMP_FILE1=/tmp/${PROGNAME}.1.$$
TEMP_FILE2=/tmp/${PROGNAME}.2.$$
TEMP_FILE3=/tmp/${PROGNAME}.3.$$
TEMP_FILE4=/tmp/${PROGNAME}.4.$$
TEMP_FILE5=/tmp/${PROGNAME}.5.$$
SCRATCH_FILE=/tmp/${PROGNAME}.scratch
RETURN=/tmp/return

###########################################################################
#	Functions
###########################################################################

function delete_from_database
{
        clear
        MADDB=~/.madbk.addr
        #Make a combined file for display
        cat $MADDB | grep "name" | cut -b 6- > $TEMP_FILE1
        
        ##### Find number of lines
        CNT=0
        for i in `cat $TEMP_FILE1`; do
            CNT=$((CNT+1))
        done

        ##### Remove spaces with underscores for search
        OLD=" "
        NEW="_"
        cat $TEMP_FILE1 | sed -e "s/$OLD/$NEW/g" > $TEMP_FILE2
        cat $TEMP_FILE2 > $TEMP_FILE1
        ##### Now get the addresses
        cat $ADDR_DB | grep "email" | cut -b 7- > $TEMP_FILE2

        ##### And 1 file joined
        cat -n $TEMP_FILE1 > $TEMP_FILE3
        cat -n $TEMP_FILE2 > $TEMP_FILE4
        join $TEMP_FILE3 $TEMP_FILE4 > $TEMP_FILE5
            
        ##### Now number the lines
        cat -n $TEMP_FILE5 > $TEMP_FILE3
        cat $TEMP_FILE3 | awk '{print $2,"]\t"$3" <"$4">" $5 $6}' > $TEMP_FILE4
        
        echo ${PROGNAME}"  ....... Delete address fields routine" > $TEMP_FILE5
        echo "" >> $TEMP_FILE5
        echo "The addresses are numbered, and  are being viewed in your pager" >> $TEMP_FILE5
        echo "Press :q when over ... then decide on the number of the address" >> $TEMP_FILE5
        echo "you want to delete from your database" >> $TEMP_FILE5
        echo "" >> $TEMP_FILE5
        cat $TEMP_FILE4 >> $TEMP_FILE5
        less $TEMP_FILE5
        echo -en '\nEnter "0" to exit out of delete routine\n'
        echo -en "\nWhich number record to delete [ 0 or 1 - $CNT ] : "
        read DEL
        if [ "$DEL" = "0" ]; then
           echo "Aborting ..."
           return 
        else
           FILTER="$DEL"' ]'
           cat $TEMP_FILE5 | grep -v "$FILTER" > $TEMP_FILE4
           #cat $TEMP_FILE4
           #read
           cat $TEMP_FILE4 | grep "@" | awk '{print $3$4}' > $TEMP_FILE1
           #cat $TEMP_FILE1
           OLD1="<"
           NEW1=" email="
           OLD2=">"
           NEW2=" "
           echo "" > $TEMP_FILE2
           for i in `cat $TEMP_FILE1`; do
               echo 'name='$i | sed "s/$OLD1/$NEW1/g" | sed "s/$OLD2/$NEW2/g" >> $TEMP_FILE2
               echo >> $TEMP_FILE2
           done
           CNT=0
           echo "" > $TEMP_FILE3
           for i in `cat $TEMP_FILE2`; do
               CNT=$((CNT+1))
               echo $i >> $TEMP_FILE3
               if [ "$CNT" = "2" ]; then
                  CNT=0
                  echo >> $TEMP_FILE3
               fi   
           done 
           cat $TEMP_FILE3 > $MADDB
           delete_from_database         
        fi      
        exit
        
}

function add_to_database
{
        clear
        echo ${PROGNAME}"                    Version : "$VERSION
        echo
        MADDB=~/.madbk.addr
                
        ### Precaution for first run
        if ! [ -s $MADDB ]; then
           echo "New database being created"
           touch $MADDB
        fi   
           
        ### File exists, append to it
        CNT=0
        cat $MADDB | grep "email=" > $TEMP_FILE1
        for i in `cat $TEMP_FILE1`; do
            CNT=$((CNT+1))
        done
        echo "Old database ... Total records : " $CNT
        echo 
        echo "Enter 1] name of the individual"
        echo "      2] e-mail address  (when prompted)"
        echo
        CNT=$((CNT+1))
        echo "Entry No : "$CNT
        echo
        echo -en "Name of addressee (e.g. James_Bond) ... "
        read NAME
        OLD=" "
        NEW="_"
        N=`echo $NAME | sed -e "s/$OLD/$NEW/g"`
        NAME=$N
        echo -en "E-mail id (e.g. jb007@m16.org) ........ "
        read EMAIL
        echo
        echo '"'$NAME'"' '<'$EMAIL'>'
        echo -en "Does this look okay ? [y / n] ... "
        read YN
        case $YN in 
             n|N ) add_to_database;;
             *   ) echo "name="$NAME >> $MADDB
                   echo "email="$EMAIL >> $MADDB
                   echo "" >> $MADDB
                   echo
                   echo -en "More entries ? [y / n] ... "
                   read YN1
                   case $YN1 in 
                       y|Y ) add_to_database;;
                       *   ) echo 
                             graceful_exit
                   esac                      
        esac

}                      
             
function helptext
{
	local tab=$(echo -en "\t\t")
		
	cat <<- -EOF-

        ${PROGNAME}                                 ver. ${VERSION}	

        This is a program to serve as an address-book for mutt
	
        Usage: ${PROGNAME} [-h | --help] [-a] [-d] OR
               ${PROGNAME}  (without options for exec mode)
               
        Options: All command line switches are for $PROGNAME native
                 format for database entry. Fo abook and pine, edit
                 datanase through abook or pine ...
	
        -h, --help	Display this help message and exit.
        -a              A]dd record to database ($PROGNAME format)
        -d              D]elete record from database ($PROGNAME format)
                     
        When run without command line options, it enters the
        execute mode with existing address database entries.	
		
	-EOF-
}	

function get_pine_fields
{
        ##### Create 2 files for names and addresses
        cat $ADDR_DB | awk '{print $1}' > $TEMP_FILE1
        rev $ADDR_DB | awk '{print $1}' > $TEMP_FILE3
        rev $TEMP_FILE3 > $TEMP_FILE2

        ##### And one file joined
        cat -n $TEMP_FILE1 > $TEMP_FILE3
        cat -n $TEMP_FILE2 > $TEMP_FILE4
        join $TEMP_FILE3 $TEMP_FILE4 > $TEMP_FILE5
                
}       ##### end of get_pine_fields
                       
function process_cc
{
   echo $CC | tr -d '"' > /tmp/dd0
   CC=`cat /tmp/dd0`
   rm -f /tmp/dd*
   touch /tmp/dd1
   for i in `echo $CC`; do
       IN=$i
       find_the_addressee
       NEWCC=$OUT
       echo -en $NEWCC >> /tmp/dd1
       echo -en "," >> /tmp/dd1 
   done
   rev /tmp/dd1 | cut -b 2- > /tmp/dd2
   NEWCC=`rev /tmp/dd2`
   rm -f /tmp/dd*
   CC=$NEWCC    
   
}      #####   end of process_cc


function process_to
{
       IN=$TO
       find_the_addressee
       TO=$OUT
}      #####   end of process_to 


function find_the_addressee
{
        cat $TEMP_FILE5 | grep "$IN" > $TEMP_FILE3
        rev $TEMP_FILE3 > $TEMP_FILE4
        cat $TEMP_FILE4 | awk '{print $1}' > $TEMP_FILE3
        rev $TEMP_FILE3 > $TEMP_FILE4
        OUT=`cat $TEMP_FILE4`
        
}       ##### end of find_the_addressee
                       
function get_cc
{
        echo "#!/bin/sh" > $SCRATCH_FILE
        echo "" >> $SCRATCH_FILE
        echo 'dialog --backtitle " Mutt Address Book " \' >> $SCRATCH_FILE
   	echo '       --title "Cc: field selector" \' >> $SCRATCH_FILE
        echo '       --checklist "Use space to select Cc: addressees and [Enter] to exit." 16 72 8 \' >> $SCRATCH_FILE
        cat $TEMP_FILE1 | sed -e 's/.*/"&" "" off \\/' >> $SCRATCH_FILE
	echo "2> /tmp/return" >> $SCRATCH_FILE
	chmod +x $SCRATCH_FILE
        $SCRATCH_FILE
        RETVAL=$?
        if [ -s /tmp/return ]; then
             CC_TAG="Y"                      
             CC=`cat /tmp/return`
        else
             case $RETVAL in

             1)   echo
                  ;;
                  
             255) echo
                  ;;
                  
             *) get_cc
             
             esac
        fi

}       #####   end of get_cc	


function get_to
{
        echo "#!/bin/sh" > $SCRATCH_FILE
        echo "" >> $SCRATCH_FILE
        echo 'dialog --backtitle " Mutt Address Book " \' >> $SCRATCH_FILE
   	echo '       --title "To: field selector ( from abook / pine / madbk database ) " \' >> $SCRATCH_FILE
        echo '       --menu "Use arrow keys to navigate and [Enter] to select TO: addressee." 16 72 8 \' >> $SCRATCH_FILE
        cat $TEMP_FILE1 | sed -e 's/.*/"&" "" \\/' >> $SCRATCH_FILE
	echo "2> /tmp/return" >> $SCRATCH_FILE
	chmod +x $SCRATCH_FILE
        $SCRATCH_FILE
        
        RETVAL=$?  
        
        if [ -s /tmp/return ]; then                        
             TO=`cat /tmp/return`
        else
             case $RETVAL in

             1 | 255 )   echo -en "Quit composing ? [y/n] : "
                         read YN
                         case $YN in 
                         y|Y ) term_exit;;
                         *   ) get_to
                         esac
                         ;;
                  
             *) get_to
             
             esac
        fi
                
}       #####   end of get_to	

function get_abook_fields
{
        ##### Create 2 files for names and addresses
        cat $ADDR_DB | grep "name" | cut -b 6- > $TEMP_FILE1
        ##### Remove spaces with underscores for search
        OLD=" "
        NEW="_"
        cat $TEMP_FILE1 | sed -e "s/$OLD/$NEW/g" > $TEMP_FILE2
        cat $TEMP_FILE2 > $TEMP_FILE1
        ##### Now get the addresses
        cat $ADDR_DB | grep "email" | cut -b 7- > $TEMP_FILE2

        ##### And 1 file joined
        cat -n $TEMP_FILE1 > $TEMP_FILE3
        cat -n $TEMP_FILE2 > $TEMP_FILE4
        join $TEMP_FILE3 $TEMP_FILE4 > $TEMP_FILE5
        
}       ##### end of get_abook_fields
                
function clean_up
{
         rm -f /tmp/${PROGNAME}.1.$$
         rm -f /tmp/${PROGNAME}.2.$$
         rm -f /tmp/${PROGNAME}.3.$$
         rm -f /tmp/${PROGNAME}.4.$$
         rm -f /tmp/${PROGNAME}.5.$$
         rm -f /tmp/${PROGNAME}.scratch
         rm -f /tmp/return
}


function graceful_exit
{
	clean_up
	exit
}


function error_exit 
{
	echo "${PROGNAME}: ${1:-"Unknown Error"}" >&2
	clean_up
	exit 1
}


function term_exit
{
	echo "${PROGNAME}: Terminated"
	clean_up
	exit
}


function int_exit
{
	echo "${PROGNAME}: Aborted by user"
	clean_up
	exit
}


###########################################################################
#	Program starts here
###########################################################################

# Trap TERM, HUP, and INT signals and properly exit

trap term_exit TERM HUP
trap int_exit INT



if [ "$1" = "" ]; then

    ### Check if abook database is there

    if ! [ -s $ADDR_DB ]; then
       echo $PROGNAME"         Version : "$VERSION
       echo "Not found : "$ADDR_DB
       echo "Set your abook database and re-run"
       term_exit
    fi
   
    ### get fields from database

    case $DATABASE in

         abook ) get_abook_fields
                 ;;
         pine  ) get_pine_fields
                 ;;
         madbk ) get_abook_fields
                 ;;
         * ) echo "Only pine, abook and madbk databases permitted"
             echo "Please edit configurable section on top of the"
             echo "script [ "$PROGNAME" ] and re-run"
             echo
             echo "Press [Enter] to quit ..."
             read
             term_exit        
    esac            

    ### Get the To: field
    get_to
    process_to

    ### Get the Cc: field
    get_cc
    process_cc

    ### Hand over to mutt
    if [ "$CC_TAG" = "Y" ]; then
       mutt $TO -c $CC
    else
       mutt $TO
    fi       

else # Command line arguments are there

    if [ "$1" = "--help" ]; then
         helptext
 	 graceful_exit
    fi

    while getopts ":hadi:" opt; do
	case $opt in
	   a )	add_to_database 
	        ;;
	   
	   d )	# For testing only
	        # cp ~/madbk.addr ~/.madbk.addr
	        delete_from_database
	        ;;

	   h )	helptext
		graceful_exit 
		;;
		
	   * )	helptext
		exit 1
	esac
    done
fi

### And quit
graceful_exit

###########################################################################
#       Everything below this is ignored
###########################################################################
