Mon CV

Script d’export des coordonnées utilisateur au format vCard depuis un serveur LDAP

31 décembre 2013

Petite problématique du jour : comment exporter dans un fichier vCard les informations et coordonnées entrées sur un LDAP, en l’occurrence ici un OpenDirectory sur serveur Mac 10.6.

Je n’ai pas trouvé d’outil vraiment satisfaisant pour ce que je recherchais sur le net, du coup, j’ai codé ce qui me fallait. Je pense que cela peut être pas mal optimisé encore (ici je fais notamment des requêtes en cascade sur le serveur LDAP, alors qu’on doit arriver à simplifier).

Cet outil peut être utilisé en exportant la totalité des utilisateurs enregistrés dans le LDAP, ou en limitant l’export à certains groupes, qu’il s’agisse de groupes de type groupOfNames ou posixGroup.

Les données disponibles pour vos utilisateurs dépendent des attributs disponibles dans le schema LDAP que vous utilisez. Ici le script exploite les attributs disponibles sur un OpenDirectory (Apple Mac OS X Server 10.6). Si vous utilisez des attributs un peu exotiques dans votre LDAP, il faudra donc adapter le script.

Installer LDAP2vCard

Pour installer cet outil, téléchargez le script dans le dossier où vous voulez l’installer :

wget --no-check-certificate https://raw.github.com/yvangodard/ldap2vcard/master/ldap2vcard.sh ; 
sudo chmod 755 ldap2vcard.sh

Utiliser le script

Le script s’utilise de la manière suivante :

./ldap2vcard.sh [-h] | -d <DN de base> -a <LDAP admin UID> -p <LDAP admin password>
                [-s <URL Serveur LDAP>] [-u <DN relatif de la branche utilisateurs>]                 [-D <domaine prioritaire pour les adresses email>] [-P <dossier vers lequel exporter le fichier vCard>]                 [-G <groupes à exporter> -t <LDAP group objectClass> -g <DN relatif de la branche des groupes>]                 [-e <option de rapport par email>] [-E <adresse email pour les rapports>] [-j <fichier journal>]

Pour une aide complète, installez le script et lancez :

./ldap2vcard.sh help

Options obligatoires :

  • -d <DN de base> :  DN de base (ex. : ‘dc=server,dc=office,dc=com‘)
  • -a <LDAP admin UID> : UID de l’administrateur LDAP utilisé pour accéder au serveur (ex. : ‘diradmin‘)
  • -p <LDAP admin password> : mot de passe de l’administrateur LDAP (sera demandé si non renseigné)

Options facultatives :

  • -s <URL Serveur LDAP> : URL du serveur LDAP (par défaut : ‘ldap://127.0.0.1‘)
  • -u <DN relatif de la branche utilisateurs> : DN relatif du DN de base qui contient vos utilisateurs (ex. : ‘cn=allusers‘, par défaut : ‘cn:users‘)
  • -D <domaine prioritaire pour les adresses email> : marquera les adresses contenant ce domaine avec ‘TYPE=PREF‘ dans l’export vCard (ex. : ‘mydomain.fr‘)
  • -G <groupes à exporter> : utilisez cette option pour limiter l’export à certains groupes d’utilisateurs, séparés par ‘%‘ (par exemple : ‘workgroup%team2‘) ou utilisez ‘allgroups‘ pour exporter tous les utilisateurs appartenant à au moins un groupe
  • -t <LDAP group objectClass> : types de groupes à exporter, soit ‘posixGroup‘ ou ‘groupOfNames‘, obligatoire à renseigner si l’option ‘-G‘ est utilisée
  • -g <DN relatif de la branche des groupes> : DN relatif du DN de base qui contient vos groupes de type  ‘posixGroup‘ ou ‘groupOfNames‘ (exemple : ‘cn=groups‘ or ‘ou=groups‘…) – obligatoire à renseigner si l’option ‘-G‘ est utilisée
  • -P <dossier vers lequel exporter le fichier vCard> : chemin vers lequel exporter le fichier vCard (par exemple : ‘~/Desktop/‘ ou ‘/var/vcard/‘…). Par défaut l’export sera réalisé dans le répertoire contenant le script.
  • -e <option de rapport par email> : paramètre d’envoi de rapport d’exécution par email, soit ‘onerror‘, ‘forcemail‘ ou ‘nomail‘ (par défaut : ‘nomail‘)
  • -E <adresse email pour les rapports> : adresse email à laquelle sera envoyé le rapport. Cette option doit être utilisée si  les options  ‘-e forcemail‘ ou ‘-e onerror‘ sont utilisées
  • -j <fichier journal> : cette option active la journalisation à la place de la sortie standard. Spécifiez en argument le chemin du fichier de log (par exemple : ‘/var/log/ldap2vcard.log‘) ou utilisez ‘default‘ (/var/log/ldap2vcard.log)

Et voici le code pour terminer :

#! /bin/bash

#-------------------------------------#
#            LDAP2vCard               #
#-------------------------------------#
#                                     #
#    Export contact informations      #
#   from LDAP branch to vCard file    #
#                                     #
#             Yvan Godard             #
#        godardyvan@gmail.com         #
#                                     #
#    Version 1.0 -- march, 18 2016    #
#         Tool licenced under         #
#   Creative Commons 4.0 BY NC SA     #
#                                     #
#         http://goo.gl/i3gpVV        #
#                                     #
#-------------------------------------#

# Variables initialisation
VERSION="LDAP2vCard 1.0 -- 2016 -- http://goo.gl/i3gpVV"
help="no"
SCRIPT_DIR=$(dirname $0)
SCRIPT_NAME=$(basename $0)
EMAIL_REPORT="nomail"
EMAIL_LEVEL=0
LOG="/var/log/ldap2vcard.log"
LOG_ACTIVE=0
LOG_TEMP=$(mktemp /tmp/LDAP2vCard_LOG.XXXXX)
GROUP_LIMIT=0
LIST_GROUPS=$(mktemp /tmp/LDAP2vCard_group_list.XXXXX)
LIST_USERS=$(mktemp /tmp/LDAP2vCard_users_list.XXXXX)
LIST_USERS_CLEAN=$(mktemp /tmp/LDAP2vCard_users_list_clean.XXXXX)
LIST_GROUP_MEMBERS=$(mktemp /tmp/LDAP2vCard_group_members.XXXXX)
LIST_GROUP_MEMBERS_CLEAN=$(mktemp /tmp/LDAP2vCard_group_members_clean.XXXXX)
DIR_TEMP_USERS=/tmp/LDAP2vCardUsers
LDAP_URL="ldap://127.0.0.1"
LDAP_DN_USER_BRANCH="cn=users"
PATH_EXPORT_VCARD=${SCRIPT_DIR}
DATAFILENAME="LDAP2vCard-$(date +%d.%m.%y-%Hh%M)"
WITH_LDAP_BIND="no"

function help () {
	echo -e "$VERSION\n"
	echo -e "This tool is designed to export to vCard file informations related to users registered in a (or some) LDAP group."
	echo -e "It works both with LDAP groups defined by objectClass posixGroup or groupOfNames."
	echo -e "This tool is licensed under the Creative Commons 4.0 BY NC SA licence."
	echo -e "\nDisclamer:"
	echo -e "This tool is provide without any support and guarantee."
	echo -e "\nSynopsis:"
	echo -e "./${SCRIPT_NAME} [-h] | -d <base namespace>"
	echo -e "                [-a <LDAP admin UID>] [-p <LDAP admin password>]"
	echo -e "                [-s <LDAP server>] [-u <relative DN of user banch>]"
	echo -e "                [-D <main domain for emails>] [-P <Path folder to export>] [-N <Name of export file>]"
	echo -e "                [-G <groups to export> -t <LDAP group objectClass> -g <relative DN of LDAP group base>]"
	echo -e "                [-e <email report option>] [-E <email address>] [-j <log file>]"
	echo -e "\n\t-h:                               prints this help then exit"
	echo -e "\nMandatory option:"
	echo -e "\t-d <base namespace>:              the base DN for each LDAP entry (e.g.: 'dc=server,dc=office,dc=com')"
	echo -e "\nOptional options:"
	echo -e "\t-a <LDAP admin UID>:              the LDAP administrator UID, if bind is needed to access LDAP (e.g.: 'diradmin')"
	echo -e "\t-p <LDAP admin password>:         the password of the LDAP administrator (asked if missing and if )"
	echo -e "\t-s <LDAP server>:                 the LDAP server URL (default: '$LDAP_URL')"
	echo -e "\t-u <relative DN of user banch>:   the relative DN of the LDAP branch that contains the users (e.g.: 'cn=allusers', default: '$LDAP_DN_USER_BRANCH')"
	echo -e "\t-D <main domain for emails>:      will mark addresses containing this domain as 'TYPE=PREF' in vCard (e.g.: 'mydomain.fr')"
	echo -e "\t-G <groups to export>:            use this option to limit export to on ore some groups, separated by '%' (e.g.: 'workgroup%team2')"
	echo -e "\t                                  or use 'allgroups' for all users registed in one or some groups"
	echo -e "\t-t <LDAP group objectClass>:      the type of groups you want to export, must be 'posixGroup' or 'groupOfNames', must be filled if '-G' is used"	
	echo -e "\t-g <relative DN of LDAP group>:   the relative DN of the LDAP branch that contains groups (e.g.: 'cn=groups' or 'ou=groups'...) - must be filled if '-G' is used"
	echo -e "\t-P <Path folder to export>:       the folder where your want to export your vCard (e.g.: '~/Desktop/' or '/var/vcard/'...), by default ${PATH_EXPORT_VCARD}"
	echo -e "\t-N <Name of export file>:         the name of exported file, without spaces and extension (e.g.: 'myExportvCard'), by default ${DATAFILENAME}"
	echo -e "\t-e <email report option>:         settings for sending a report by email, must be 'onerror', 'forcemail' or 'nomail' (default: '$EMAIL_REPORT')"
	echo -e "\t-E <email address>:               email address to send the report, must be filled if '-e forcemail' or '-e onerror' options is used"
	echo -e "\t-j <log file>:                    enables logging instead of standard output. Specify an argument for the full path to the log file"
	echo -e "\t                                  (e.g.: '$LOG') or use 'default' ($LOG)"
	exit 0
}

function error () {
	echo -e "\n*** Error ***"
	echo -e ${1}
	echo -e "\n"${VERSION}
	alldone 1
}

function alldone () {
	# Redirect standard outpout
	exec 1>&6 6>&-
	# Logging if needed 
	[ $LOG_ACTIVE -eq 1 ] && cat $LOG_TEMP >> $LOG
	# Print current log to standard outpout
	[ $LOG_ACTIVE -ne 1 ] && cat $LOG_TEMP
	[ $EMAIL_LEVEL -ne 0 ] && [ $1 -ne 0 ] && cat $LOG_TEMP | mail -s "[ERROR] ${SCRIPT_NAME} on ${HOSTNAME}" ${EMAIL_ADDRESS}
	[ $EMAIL_LEVEL -eq 2 ] && [ $1 -eq 0 ] && cat $LOG_TEMP | mail -s "[OK] ${SCRIPT_NAME} on ${HOSTNAME}" ${EMAIL_ADDRESS}
	# Remove temp files/folder
	rm -R /tmp/LDAP2vCard*
	exit ${1}
}

function base64decode () {
	echo ${1} | grep :: > /dev/null 2>&1
	if [ $? -eq 0 ] 
		then
		VALUE=$(echo ${1} | grep :: | awk '{print $2}' | openssl enc -base64 -d )
		ATTRIBUTE=$(echo ${1} | grep :: | awk '{print $1}' | awk 'sub( ".$", "" )' )
		echo "${ATTRIBUTE} ${VALUE}"
	else
		echo ${1}
	fi
}

# Correction to support LDIF splitted lines, thanks to Guillaume Bougard (gbougard@pkg.fr)
function deleteLineBreaks () {
	perl -n -e 'chomp ; print "\n" unless (substr($_,0,1) eq " " || !defined($lines)); $_ =~ s/^\s+// ; print $_ ; $lines++;' -i ${1}
}

# Remove old temp and create new temp dir
rm -R /tmp/LDAP2vCard*
mkdir -p ${DIR_TEMP_USERS}

optsCount=0
optsCount_limit_groups=0

while getopts "hd:a:p:t:g:s:u:D:G:P:e:E:j:N:" OPTION
do
	case "$OPTION" in
		h)	help="yes"
						;;
		d)	LDAP_DN_BASE=${OPTARG}
			let optsCount=$optsCount+1
						;;
		a)	LDAP_ADMIN_UID=${OPTARG}
			[[ ${LDAP_ADMIN_UID} != "" ]] && WITH_LDAP_BIND="yes"
						;;
		p)	LDAP_ADMIN_PASS=${OPTARG}
                        ;;
	    s) 	LDAP_URL=${OPTARG}
						;;
		u) 	LDAP_DN_USER_BRANCH=${OPTARG}
						;;
		D)	MAIN_DOMAIN=${OPTARG}
                        ;;
		G)	LDAP_GROUPS=${OPTARG}
			if [[ ${LDAP_GROUPS} != "allgroups" ]] 
				then
				echo ${LDAP_GROUPS} | perl -p -e 's/%/\n/g' | perl -p -e 's/ //g' | awk '!x[$0]++' >> $LIST_GROUPS
				GROUP_LIMIT=1
			elif [[ ${LDAP_GROUPS} = "allgroups" ]]
				then
				GROUP_LIMIT=2
			fi
                        ;;
        t)	LDAP_GROUP_OBJECTCLASS=${OPTARG}
			let optsCount_limit_groups=$optsCount_limit_groups+1
                        ;;
		g)	LDAP_GROUP_DN=${OPTARG}
			let optsCount_limit_groups=$optsCount_limit_groups+1
                        ;;
        P)	PATH_EXPORT_VCARD=${OPTARG}
                        ;;
        N)	DATAFILENAME=${OPTARG}
                        ;;
        e)	EMAIL_REPORT=${OPTARG}
                        ;;                             
        E)	EMAIL_ADDRESS=${OPTARG}
                        ;;
        j)	[ $OPTARG != "default" ] && LOG=${OPTARG}
			LOG_ACTIVE=1
                        ;;
	esac
done

if [[ ${optsCount} != "1" ]]
	then
        help
        alldone 1
fi

if [[ ${help} = "yes" ]]
	then
	help
fi

if [[ ${WITH_LDAP_BIND} = "yes" ]] && [[ ${LDAP_ADMIN_PASS} = "" ]]
	then
	echo "Password for uid=$LDAP_ADMIN_UID,$LDAP_DN_USER_BRANCH,$LDAP_DN_BASE?" 
	read -s LDAP_ADMIN_PASS
fi

# Verification of DATANAME
if [[ ${DATAFILENAME} = "" ]]
	then
	DATANAME="LDAP2vCard-$(date +%d.%m.%y-%Hh%M).vcf"
	else
	DATANAME=${DATAFILENAME}.vcf
fi

# Redirect standard outpout to temp file
exec 6>&1
exec >> $LOG_TEMP

# Start temp log file
echo -e "\n****************************** `date` ******************************\n"
echo -e "$0 started with options:"
echo -e "\t-d ${LDAP_DN_BASE} (base namespace)"
echo -e "\t-s ${LDAP_URL} (LDAP server)"
echo -e "\t-u ${LDAP_DN_USER_BRANCH} (relative DN of user banch)"
[[ ${MAIN_DOMAIN} != "" ]] && echo -e "\t-D ${MAIN_DOMAIN} (main domain for emails)"
if [[ ${GROUP_LIMIT} != "0" ]]
	then
	echo -e "\t-G ${LDAP_GROUPS} (limit export to these groups)"
	echo -e "\t-t ${LDAP_GROUP_OBJECTCLASS} (LDAP group objectClass)"
	echo -e "\t-g ${LDAP_GROUP_DN} (relative DN of LDAP groups base)"
fi
echo -e "\t-e ${EMAIL_REPORT} (email report option)"
if [[ ${EMAIL_REPORT} != "nomail" ]] 
	then
	echo -e "\t-E ${EMAIL_ADDRESS} (email report address)"
fi
if [[ ${LOG_ACTIVE} != "0" ]]
	then
	echo -e "\t-j ${LOG} (log file)"
fi
echo -e "Export to ${PATH_EXPORT_VCARD}/${DATANAME}"

# Need '-t' and '-g' to be filled if '-G' is used
[[ ${GROUP_LIMIT} != "0" ]] && [[ ${optsCount_limit_groups} != "2" ]] && error "Trying to use '-G' option but '-t <LDAP group objectClass>' and '-g <relative DN of LDAP group>' are not filled." 

# Verification of LDAP_GROUP_OBJECTCLASS parameter
[[ ${GROUP_LIMIT} != "0" ]] && [[ ${LDAP_GROUP_OBJECTCLASS} != "posixGroup" ]] && [[ ${LDAP_GROUP_OBJECTCLASS} != "groupOfNames" ]] && error "Parameter '-t ${LDAP_GROUP_OBJECTCLASS}' is not correct.\n-t must be 'posixGroup' or 'groupOfNames'"

# Path to export needs to be a valid folder
if [[ ${PATH_EXPORT_VCARD} != ${SCRIPT_DIR} ]]
	then
	[[ ! -d  ${PATH_EXPORT_VCARD} ]] && echo -e "This export path filled with '-P ${PATH_EXPORT_VCARD}' doesn't exist. Export will be done at ${SCRIPT_DIR}." && PATH_EXPORT_VCARD=${SCRIPT_DIR}
fi

# Verification of LDAP_URL parameter
[[ ${LDAP_URL} = "" ]] && echo -e "You used option '-s' but you have not entered any LDAP url. Wi'll try to continue with url 'ldap://127.0.0.1'" && LDAP_URL="ldap://127.0.0.1"

# Test of sending email parameter and check the consistency of the parameter email address
if [[ ${EMAIL_REPORT} = "forcemail" ]]
	then
	EMAIL_LEVEL=2
	if [[ -z ${EMAIL_ADDRESS} ]]
		then
		echo -e "You use option '-e ${EMAIL_REPORT}' but you have not entered any email info.\n\t-> We continue the process without sending email."
		EMAIL_LEVEL=0
	else
		echo "${EMAIL_ADDRESS}" | grep '^[a-zA-Z0-9._-]*@[a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]*$' > /dev/null 2>&1
		if [ $? -ne 0 ]
			then
    		echo -e "This address '${EMAIL_REPORT}' does not seem valid.\n\t-> We continue the process without sending email."
    		EMAIL_LEVEL=0
    	fi
    fi
elif [[ ${EMAIL_REPORT} = "onerror" ]]
	then
	EMAIL_LEVEL=1
	if [[ -z ${EMAIL_ADDRESS} ]]
		then
		echo -e "You use option '-e ${EMAIL_REPORT}' but you have not entered any email info.\n\t-> We continue the process without sending email."
		EMAIL_LEVEL=0
	else
		echo "${EMAIL_ADDRESS}" | grep '^[a-zA-Z0-9._-]*@[a-zA-Z0-9._-]*\.[a-zA-Z0-9._-]*$' > /dev/null 2>&1
		if [ $? -ne 0 ]
			then	
    		echo -e "This address '${EMAIL_REPORT}' does not seem valid.\n\t-> We continue the process without sending email."
    		EMAIL_LEVEL=0
    	fi
    fi
elif [[ ${EMAIL_REPORT} != "nomail" ]]
	then
	echo -e "\nOption '-e ${EMAIL_REPORT}' is not valid (must be: 'onerror', 'forcemail' or 'nomail').\n\t-> We continue the process without sending email."
	EMAIL_LEVEL=0
elif [[ ${EMAIL_REPORT} = "nomail" ]]
	then
	EMAIL_LEVEL=0
fi

# LDAP connection test
echo -e "\nConnecting LDAP at $LDAP_URL ..."

[[ ${WITH_LDAP_BIND} = "yes" ]] && LDAP_COMMAND_BEGIN="ldapsearch -LLL -H ${LDAP_URL} -D uid=${LDAP_ADMIN_UID},${LDAP_DN_USER_BRANCH},${LDAP_DN_BASE} -w ${LDAP_ADMIN_PASS}"
[[ ${WITH_LDAP_BIND} = "no" ]] && LDAP_COMMAND_BEGIN="ldapsearch -LLL -H ${LDAP_URL} -x"

${LDAP_COMMAND_BEGIN} -b ${LDAP_DN_USER_BRANCH},${LDAP_DN_BASE} > /dev/null 2>&1
if [ $? -ne 0 ]
	then 
	error "Error connecting to LDAP server.\nPlease verify your LDAP_URL and, if needed to bind LDAP, user and pass."
else
	echo "OK!"
fi

# Export user list : all users registered in LDAP
if [[ ${GROUP_LIMIT} = "0" ]]
	then
	echo -e "\nExporting all users..."
	${LDAP_COMMAND_BEGIN} -b ${LDAP_DN_USER_BRANCH},${LDAP_DN_BASE} uid | grep uid: | awk '{print $2}' >> ${LIST_USERS}
fi

# Test bind to ${LDAP_GROUP_DN},${LDAP_DN_BASE}
if [[ ${GROUP_LIMIT} != "0" ]]
	then
	${LDAP_COMMAND_BEGIN} -b ${LDAP_GROUP_DN},${LDAP_DN_BASE} > /dev/null 2>&1
	[ $? -ne 0 ] && error "Error binding to LDAP server at ${LDAP_GROUP_DN},${LDAP_DN_BASE}.\nPlease verify your URL and user/pass."
fi

# Export user list : all users registered in some groups
if [[ ${GROUP_LIMIT} = "2" ]]
	then
	echo -e "\nExporting users registered in one or some groups in ${LDAP_GROUP_DN},${LDAP_DN_BASE}:"
	if [[ -z $(${LDAP_COMMAND_BEGIN} -b ${LDAP_GROUP_DN},${LDAP_DN_BASE} cn | grep cn: | awk '{print $2}') ]] 
		then 
		error "No group found in ${LDAP_GROUP_DN},${LDAP_DN_BASE}"
	else
		${LDAP_COMMAND_BEGIN} -b ${LDAP_GROUP_DN},${LDAP_DN_BASE} cn | grep cn: | awk '{print $2}' | grep -v $(echo ${LDAP_GROUP_DN} | awk -F'=' '{print $2}')  >> ${LIST_GROUPS}
	fi
fi

# Test group parameters if -G used
[[ ${GROUP_LIMIT} = "1" ]] && [[ -z $(cat ${LIST_GROUPS}) ]] && error "Trying to use '-G' with any group name or parameter 'allgroups'. Please re-try with minimum a group name"

# Export users : all users registered in groups selected
if [[ ${GROUP_LIMIT} != "0" ]]
	then
	echo -e "\nExporting users in groups below, objectClass ${LDAP_GROUP_OBJECTCLASS}:"
	echo -e "$(cat ${LIST_GROUPS} | perl -p -e 's/\n/ - /g' | awk 'sub( "...$", "" )')\n"
	for GROUP in $(cat ${LIST_GROUPS})
	do
		CONTENT_GROUP=$(mktemp /tmp/LDAP2vCard_group_content.XXXXX)
		CONTENT_GROUP_CLEAN=$(mktemp /tmp/LDAP2vCard_group_content_clean.XXXXX)
		${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} > /dev/null 2>&1
		if [ $? -ne 0 ]
			then 
			echo -e "-> Error binding wth group '${GROUP}' (cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE}).\n\tPlease verify this group exists on LDAP."
		elif [[ ${LDAP_GROUP_OBJECTCLASS} = "groupOfNames" ]] 
			then
			echo -e "-> Processing group '${GROUP}'"
			if [[ -z $(${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} member | grep ^member: ) ]] 
				then 
				echo -e "\tUser list on LDAP group is empty"
			else
				${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} member >> ${CONTENT_GROUP}
				deleteLineBreaks ${CONTENT_GROUP}
				OLDIFS=$IFS; IFS=$'\n'
				for LINE in $(cat ${CONTENT_GROUP})
				do
					base64decode ${LINE} | grep ^member: | awk '{print $2}' | awk -F',' '{print $1}' | awk -F'=' '{print $2}' >> ${CONTENT_GROUP_CLEAN}
				done
				IFS=$OLDIFS
			fi
		elif [[ ${LDAP_GROUP_OBJECTCLASS} = "posixGroup" ]]
			then
			echo -e "-> Processing group '${GROUP}'"
			if [[ -z $(${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} memberUid | grep ^memberUid: ) ]] 
				then 
				echo -e "\tUser list on LDAP group is empty"
			else
				${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} memberUid >> ${CONTENT_GROUP}
				deleteLineBreaks ${CONTENT_GROUP}
				OLDIFS=$IFS; IFS=$'\n'
				for LINE in $(cat ${CONTENT_GROUP})
				do
					base64decode ${LINE} | grep ^memberUid: | awk '{print $2}' >> ${CONTENT_GROUP_CLEAN}
				done
				IFS=$OLDIFS
			fi
		fi
		if [ -f ${CONTENT_GROUP_CLEAN} ] && [[ ! -z $(cat ${CONTENT_GROUP_CLEAN}) ]]; then
			cat ${CONTENT_GROUP_CLEAN} >> ${LIST_USERS}
			GROUP_FULL_NAME=""
			if [[ ${LDAP_GROUP_OBJECTCLASS} = "posixGroup" ]]; then
				if [[ ! -z $(${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} apple-group-realname | grep ^apple-group-realname: ) ]]; then
					GROUP_NAME=$(mktemp /tmp/LDAP2vCard_group_name.XXXXX)
					GROUP_NAME_CLEAN=$(mktemp /tmp/LDAP2vCard_group_name_clean.XXXXX)
					${LDAP_COMMAND_BEGIN} -b cn=${GROUP},${LDAP_GROUP_DN},${LDAP_DN_BASE} apple-group-realname >> ${GROUP_NAME}
					deleteLineBreaks ${GROUP_NAME}
					OLDIFS=$IFS; IFS=$'\n'
					for LINE in $(cat ${GROUP_NAME})
					do
						base64decode ${LINE} | grep ^apple-group-realname: | perl -p -e 's/apple-group-realname: //g' >> ${GROUP_NAME_CLEAN}
					done
					IFS=$OLDIFS
					GROUP_FULL_NAME=$(cat ${GROUP_NAME_CLEAN})
					echo "   ...Group full name: ${GROUP_FULL_NAME}"
					rm ${GROUP_NAME_CLEAN}
					rm ${GROUP_NAME}
				fi
			fi
			for CONTENT_GROUP_USER in $(cat ${CONTENT_GROUP_CLEAN})
			do
				echo "${CONTENT_GROUP_USER} ${GROUP} $(echo ${GROUP_FULL_NAME} | perl -p -e 's/ /%%%/g')" >> ${LIST_GROUP_MEMBERS}
			done
		fi
		rm ${CONTENT_GROUP}
		rm ${CONTENT_GROUP_CLEAN}
	done
fi

# Remove duplicate users in list
awk '!x[$0]++' ${LIST_USERS} > ${LIST_USERS_CLEAN} 
echo -e "\nThe following users will be exported:"
cat ${LIST_USERS_CLEAN} | perl -p -e 's/\n/ - /g' | awk 'sub( "...$", "" )'

# Verification if there is some users 
[[ -z $(cat ${LIST_USERS_CLEAN}) ]] && error "No user were found. Export aborded!"

for USER in $(cat ${LIST_USERS_CLEAN})
do
	CONTENT_USER=$(mktemp /tmp/LDAP2vCard_user_content.XXXXX)
	${LDAP_COMMAND_BEGIN} -b ${LDAP_DN_USER_BRANCH},${LDAP_DN_BASE} -x uid=${USER} uid uidNumber givenName sn cn apple-company departmentNumber title street postalCode l c telephoneNumber facsimileTelephoneNumber homePhone mobile pager apple-imhandle mail jpegPhoto > ${CONTENT_USER}
	[ $? -ne 0 ] && echo -e "Error while exporting user ${USER}. Please verify vCard result."
	deleteLineBreaks ${CONTENT_USER}
	OLDIFS=$IFS; IFS=$'\n'
	for LINE in $(cat ${CONTENT_USER})
	do
		echo ${LINE} | grep ^jpegPhoto:: > /dev/null 2>&1
		if [[ $? -eq 0 ]]; then
			echo ${LINE} >> ${DIR_TEMP_USERS}/${USER}
		else
			base64decode ${LINE} >> ${DIR_TEMP_USERS}/${USER}
		fi
	done
	IFS=$OLDIFS
	rm ${CONTENT_USER}
done

# Add group informations
if [[ ${GROUP_LIMIT} != "0" ]]
	then
	cat ${LIST_GROUP_MEMBERS} | \
	while read UID_USER GROUP_USER GROUP_FN
	do
		[[ -z ${UID_USER} ]] && [[ -z ${GROUP_USER} ]] && continue
		[[ -z ${GROUP_FN} ]] && echo "memberOf: ${GROUP_USER}" >> ${DIR_TEMP_USERS}/${UID_USER}
		[[ ! -z ${GROUP_FN} ]] && echo "memberOf: $(echo ${GROUP_FN} | perl -p -e 's/%%%/ /g')" >> ${DIR_TEMP_USERS}/${UID_USER}		
	done < ${LIST_GROUP_MEMBERS}
fi

# Create vCard v3 
&#91;&#91; -f ${PATH_EXPORT_VCARD}/${DATANAME} &#93;&#93; && mv ${PATH_EXPORT_VCARD}/${DATANAME} ${PATH_EXPORT_VCARD}/${DATANAME}.old
for FILE in $(find ${DIR_TEMP_USERS} -type f -maxdepth 1)
do
	FIRST_NAME=$(cat ${FILE} | grep ^givenName: | perl -p -e 's/givenName: //g')
	NAME=$(cat ${FILE} | grep ^sn: | perl -p -e 's/sn: //g')
	FULL_NAME=$(cat ${FILE} | grep ^cn: | perl -p -e 's/cn: //g')
	ORGANIZATION=$(cat ${FILE} | grep ^apple-company: | perl -p -e 's/apple-company: //g')
	TITLE=$(cat ${FILE} | grep ^title: | perl -p -e 's/title: //g')
	ADR="$(cat ${FILE} | grep ^street: | perl -p -e 's/street: //g');$(cat ${FILE} | grep ^l: | perl -p -e 's/l: //g');;$(cat ${FILE} | grep postalCode: | perl -p -e 's/postalCode: //g');$(cat ${FILE} | grep c: | perl -p -e 's/c: //g')"
	UID_VCARD="ldap2vcard-$(cat ${FILE} | grep ^uid: | head -1 | perl -p -e 's/uid: //g')-$(cat ${FILE} | grep uidNumber: | perl -p -e 's/uidNumber: //g')"
	ROLE=$(cat ${FILE} | grep ^apple-departmentNumber: | perl -p -e 's/departmentNumber: //g')
	JPEGPHOTO=$(cat ${FILE} | grep ^jpegPhoto:: | perl -p -e 's/jpegPhoto:: //g')

	# Begining vCard
	echo "BEGIN:VCARD" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "VERSION:3.0" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "N;ENCODING=8BIT;CHARSET=UTF-8:${NAME};${FIRST_NAME}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${FULL_NAME} ]] && echo "FN;ENCODING=8BIT;CHARSET=UTF-8:${FULL_NAME}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${ORGANIZATION} ]] && echo "ORG;ENCODING=8BIT;CHARSET=UTF-8:${ORGANIZATION}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${TITLE} ]] && echo "TITLE;ENCODING=8BIT;CHARSET=UTF-8:${TITLE}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${ADR} ]] && echo "ADR;TYPE=WORK;ENCODING=8BIT;CHARSET=UTF-8:;;${ADR}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${ROLE} ]] && echo "ROLE;ENCODING=8BIT;CHARSET=UTF-8:${ROLE}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	# Processing emails
	LIST_EMAILS_ADDRESS=$(mktemp /tmp/LDAP2vCard_list_emails_addresses.XXXXX)
	SECONDARY_EMAILS=$(mktemp /tmp/LDAP2vCard_list_sec_emails_addresses.XXXXX)
	cat ${FILE} | grep ^mail: | perl -p -e 's/mail: //g' >> ${LIST_EMAILS_ADDRESS}
	LINES_NUMBER=$(cat ${LIST_EMAILS_ADDRESS} | grep "." | wc -l)
    if [[ ! -z ${LIST_EMAILS_ADDRESS} ]] && [ $LINES_NUMBER -eq 1 ]
    	then
    	PRINCIPAL_EMAIL=$(head -n 1 ${LIST_EMAILS_ADDRESS})
    	echo "EMAIL;type=INTERNET;TYPE=PREF;ENCODING=8BIT;CHARSET=UTF-8:${PRINCIPAL_EMAIL}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	elif [[ ! -z ${LIST_EMAILS_ADDRESS} ]] && [ $LINES_NUMBER -gt 1 ]
    	then
    	if [[ -z ${MAIN_DOMAIN} ]]
    		then
    		PRINCIPAL_EMAIL=$(head -n 1 ${LIST_EMAILS_ADDRESS})
	    	echo "EMAIL;type=INTERNET;TYPE=PREF;ENCODING=8BIT;CHARSET=UTF-8:${PRINCIPAL_EMAIL}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	    else
	    	cat ${LIST_EMAILS_ADDRESS} | grep ${MAIN_DOMAIN} > /dev/null 2>&1
	    	if [ $? -ne 0 ]
	    		then
	    		PRINCIPAL_EMAIL=$(head -n 1 ${LIST_EMAILS_ADDRESS})
	    		echo "EMAIL;type=INTERNET;TYPE=PREF;ENCODING=8BIT;CHARSET=UTF-8:${PRINCIPAL_EMAIL}" >> ${PATH_EXPORT_VCARD}/${DATANAME}		
	    	else
	    		PRINCIPAL_EMAIL=$(cat ${LIST_EMAILS_ADDRESS} | grep ${MAIN_DOMAIN} | head -n 1)
	    		echo "EMAIL;type=INTERNET;TYPE=PREF;ENCODING=8BIT;CHARSET=UTF-8:${PRINCIPAL_EMAIL}" >> ${PATH_EXPORT_VCARD}/${DATANAME}		
	    	fi
	    fi
	    cat ${LIST_EMAILS_ADDRESS} | grep -v ${PRINCIPAL_EMAIL} >> ${SECONDARY_EMAILS}
		for SEC_EMAIL in $(cat ${SECONDARY_EMAILS})
		do
			echo "EMAIL;type=INTERNET;ENCODING=8BIT;CHARSET=UTF-8:${SEC_EMAIL}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
		done
    fi
    rm ${LIST_EMAILS_ADDRESS}
    rm ${SECONDARY_EMAILS}
    # Processing phone numbers & IM
	OLDIFS=$IFS; IFS=$'\n'
	for telephoneNumber in $(cat ${FILE} | grep ^telephoneNumber: | perl -p -e 's/telephoneNumber: //g')
	do
		echo "TEL;TYPE=VOICE;TYPE=WORK;ENCODING=8BIT;CHARSET=UTF-8:${telephoneNumber}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for facsimileTelephoneNumber in $(cat ${FILE} | grep ^facsimileTelephoneNumber: | perl -p -e 's/facsimileTelephoneNumber: //g')
	do
		echo "TEL;TYPE=FAX;TYPE=WORK;ENCODING=8BIT;CHARSET=UTF-8:${facsimileTelephoneNumber}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for homePhone in $(cat ${FILE} | grep ^homePhone: | perl -p -e 's/homePhone: //g')
	do
		echo "TEL;TYPE=VOICE;TYPE=HOME;ENCODING=8BIT;CHARSET=UTF-8:${homePhone}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for mobile in $(cat ${FILE} | grep ^mobile: | perl -p -e 's/mobile: //g')
	do
		echo "TEL;TYPE=CELL;TYPE=HOME;ENCODING=8BIT;CHARSET=UTF-8:${mobile}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for pager in $(cat ${FILE} | grep ^pager: | perl -p -e 's/pager: //g')
	do
		echo "TEL;TYPE=PAGER;TYPE=WORK;ENCODING=8BIT;CHARSET=UTF-8:${pager}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for aim in $(cat ${FILE} | grep '^apple-imhandle: AIM:' | perl -p -e 's/apple-imhandle: AIM://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=aim:aim;CHARSET=UTF-8:${aim}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for icq in $(cat ${FILE} | grep '^apple-imhandle: ICQ:' | perl -p -e 's/apple-imhandle: ICQ://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=icq:icq;CHARSET=UTF-8:${icq}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for jabber in $(cat ${FILE} | grep '^apple-imhandle: Jabber:' | perl -p -e 's/apple-imhandle: Jabber://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=jabber:xmpp;CHARSET=UTF-8:${jabber}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for msn in $(cat ${FILE} | grep '^apple-imhandle: MSN:' | perl -p -e 's/apple-imhandle: MSN://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=msn:msn;CHARSET=UTF-8:${msn}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for yahoo in $(cat ${FILE} | grep '^apple-imhandle: Yahoo:' | perl -p -e 's/apple-imhandle: Yahoo://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=yahoo:ymsgr;CHARSET=UTF-8:${yahoo}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for sip in $(cat ${FILE} | grep '^apple-imhandle: SIP:' | perl -p -e 's/apple-imhandle: SIP://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=sip:sip;CHARSET=UTF-8:${sip}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for twitter in $(cat ${FILE} | grep '^apple-imhandle: Twitter:' | perl -p -e 's/apple-imhandle: Twitter://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=twitter:twitter;CHARSET=UTF-8:${twitter}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for googletalk in $(cat ${FILE} | grep '^apple-imhandle: GTalk:' | perl -p -e 's/apple-imhandle: GTalk://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=googletalk:xmpp;CHARSET=UTF-8:${googletalk}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for xmpp in $(cat ${FILE} | grep '^apple-imhandle: XMPP:' | perl -p -e 's/apple-imhandle: XMPP://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=xmpp:xmpp;CHARSET=UTF-8:${xmpp}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for facebook in $(cat ${FILE} | grep '^apple-imhandle: Facebook:' | perl -p -e 's/apple-imhandle: Facebook://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=facebook:xmpp;CHARSET=UTF-8:${facebook}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for skype in $(cat ${FILE} | grep '^apple-imhandle: Skype:' | perl -p -e 's/apple-imhandle: Skype://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=skype:skype;CHARSET=UTF-8:${skype}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for qq in $(cat ${FILE} | grep '^apple-imhandle: QQ:' | perl -p -e 's/apple-imhandle: QQ://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=qq:x-apple;CHARSET=UTF-8:${qq}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	for gadugadu in $(cat ${FILE} | grep '^apple-imhandle: Gadugadu:' | perl -p -e 's/apple-imhandle: Gadugadu://g')
	do
		echo "IMPP;ENCODING=8BIT;X-SERVICE-TYPE=gadugadu:x-apple;CHARSET=UTF-8:${gadugadu}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	done
	# Processing photo
	echo "PHOTO;TYPE=JPEG;ENCODING=b:${JPEGPHOTO}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	# Processing categories
	CATEGORIES=$(cat ${FILE} | grep '^memberOf' | perl -p -e 's/memberOf: //g' | perl -p -e 's/\n/,/g')
	[[ ! -z ${CATEGORIES} ]] && echo "CATEGORIES;ENCODING=8BIT;CHARSET=UTF-8:$(echo ${CATEGORIES} | awk 'sub( ".$", "" )')" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	IFS=$OLDIFS
	echo "REV:$(date +"%Y%m%dT%H%M%SZ")" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "X-ABUID:ABPerson" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "KIND:organization" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "NOTE;ENCODING=8BIT;CHARSET=UTF-8:Export made on ${HOSTNAME}\nwith ${VERSION}\n\n`date +"%Y-%m-%d-%H:%M:%S"`" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	[[ ! -z ${UID_VCARD} ]] && echo "UID:${UID_VCARD}" >> ${PATH_EXPORT_VCARD}/${DATANAME}
	echo "END:VCARD" >> ${PATH_EXPORT_VCARD}/${DATANAME}
done

echo ""
echo "********************************* ${SCRIPT_NAME} finished *********************************"
alldone 0

Evidemment, si vous avez des retours ou des idées d’amélioration, n’hésitez pas !

Posted in Apple et Macintosh, Unix et LinuxTags: