#!/bin/bash

#Usage : ./sign_deb_package deb_path crt_path [keypath] [wosign_conf] [-force-sign] [-no-tsa]
debug_crt_path="/usr/share/ca-certificates/deepin/private/priv.crt"
debug_key_path="/usr/share/ca-certificates/deepin/private/priv.key"
sign_info_file="sign"
if [ $# -lt 1 ]; then 
    echo "Usage      : $(basename $0) deb_path crt_path keypath wosign_conf -force-sign -no-tsa"
    echo "deb_path   : the deb file to sign"
    echo "crt_path   : the certificate for signature"
    echo "key_path   : the key for signature, it can be absent if you use U-key"
    echo "wosign_conf: the wosign configure file if you specified"
    echo "-force-sign: forced to replace signature"
    echo "-no-tsa    : denote that signature without timestamp"
    exit 1
fi

last_arg=${!#}
declare -i args_without_tsa_option=$#
no_timestamp=""
if [ $last_arg == "-no-tsa" ]; then
    no_timestamp=--no-timestamp
    args_without_tsa_option=$#-1
fi

force_sign=""
if [ -z $no_timestamp ]; then
    if [ $last_arg == "-force-sign" ]; then
        force_sign=--force
        args_without_tsa_option=$#-1
    fi
else
    force_arg=${@:$#-1:1}
    if [ $force_arg == "-force-sign" ]; then
        force_sign=--force
        args_without_tsa_option=$args_without_tsa_option-1
    fi
fi

if [ $args_without_tsa_option -eq 1 ]; then
    deb_path=$1
    key_path=${debug_key_path}
    crt_path=${debug_crt_path}
    crt_arg="-c ${debug_crt_path}"
    key_arg="-k ${debug_key_path}"
fi
if [ $args_without_tsa_option -eq 3 ]; then
    deb_path=$1
    crt_path=$2
    deb_arg="-f $1"
    crt_arg="-c $2"
    tmp=$3
    suffix=${tmp##*.}
    if [ $suffix = "key" ]; then
        key_path=$3
        key_arg="-k $3"
    else
        abosulte_path=`realpath $3` 
        wosign_conf="--wosign-conf=$abosulte_path"
    fi
fi

if [ $args_without_tsa_option -eq 2 ]; then
    deb_path=$1
    crt_path=$2
    deb_arg="-f $1"
    crt_arg="-c $2"
fi


if [ ! -f "$deb_path" ]; then
    echo "deb_path : $deb_path does not exist"
    exit 0
fi

deb_file=$(basename $deb_path)
out_path=$(mktemp -d /tmp/SIGN_DEB_XXXXXXXXXX)

fakeroot dpkg-deb -R $deb_path $out_path

declare -a arr_sign_inode
#sign elfs
function sign_elfs() {
    for element in `ls -a $1`; do
        if [ $element == "." ] || [ $element == ".." ]; then
          continue
        fi
        signed_flag=FALSE
        dir_or_file=$1/$element
        if [ -d $dir_or_file ]; then
            if [ -L $dir_or_file ]; then
                continue
            fi
           sign_elfs $dir_or_file
        else
            if [ -L $1/$element ]; then
                continue
            fi
            magic=`xxd -l 4 -ps $dir_or_file`
            if [ "$magic" = "7f454c46" ]; then
                cur_inode=`ls -i $1/$element | cut -d ' ' -f 1`
                for inode in ${arr_sign_inode[*]}; do
                    if [ $cur_inode == $inode ]; then
                        signed_flag=TRUE
                        echo "$1/$element has signed because of another file with the same inode!"
                        break
                    fi
                done
                if [ $signed_flag = TRUE ]; then
                    continue
                fi
                elf_arg="-f $dir_or_file"
                echo "deepin-elf-sign $elf_arg $key_arg $crt_arg $wosign_conf $force_sign $no_timestamp"
                deepin-elf-sign $elf_arg $key_arg $crt_arg $wosign_conf $force_sign $no_timestamp
                if [ $? != 0 ]; then
                    echo "fatal error!"
                    rm -rf $out_path
                    exit -1
                else
                    arr_sign_inode[${#arr_sign_inode[*]}]=$cur_inode
                fi
            fi
        fi
    done
}

#OLD_ELFSIGN_WITH_OPTION=$ELFSIGN_WITH_OPTION
#export ELFSIGN_WITH_OPTION=Y
sign_elfs $out_path
#ELFSIGN_WITH_OPTION=$OLD_ELFSIGN_WITH_OPTION


#compress
echo "now sign deb file ...."
if [ -n "$DEB_OUT_DIR" ]; then
    out_deb_dir=$DEB_OUT_DIR
else
    out_deb_dir=./signed_deb
fi
if [ ! -d $out_deb_dir ];then
    mkdir $out_deb_dir
fi

out_deb=$out_deb_dir/$deb_file
echo "$out_deb"
fakeroot dpkg-deb -b $out_path $out_deb

# signinfo file can not extract by dpkg-deb -R
# so we should us ar x to extract it in the workspace directory
# then we can find it if we do pkcs7 sign for another certificate.
cp $deb_path $out_path
echo "cp $deb_path to $out_path"
cd $out_path
ar x $deb_file $sign_info_file
rm $deb_file
cd -

if [ -f $out_path/$sign_info_file ]
then
    ar r $out_deb $out_path/$sign_info_file
fi

OLD_DEB_SIGN_METHOD=$DEB_SIGN_METHOD
export DEB_SIGN_METHOD=file

rm -rf $out_path

echo "deepin-deb-sign -f $out_deb $key_arg $crt_arg $wosign_conf $force_sign $no_timestamp"
if deepin-deb-sign -f $out_deb $key_arg $crt_arg $wosign_conf $force_sign $no_timestamp
then
    DEB_SIGN_METHOD=$OLD_DEB_SIGN_METHOD
else
    DEB_SIGN_METHOD=$OLD_DEB_SIGN_METHOD
    rm -rf $out_deb
    exit -1
fi


