#!/bin/bash

PATH=/bin:/usr/bin:/sbin:/usr/sbin

TZ_SYS_RO_SHARE=`tzplatform-get TZ_SYS_RO_SHARE | cut -d= -f2`
SCRIPT_DIR=$(readlink -f "$0" | xargs dirname)
PRIVILEGE_DB_DIR="$TZ_SYS_RO_SHARE/privilege-manager/"
PRIVILEGE_DB=$PRIVILEGE_DB_DIR".privilege.db"
PRIVILEGE_DB_BKUP=$PRIVILEGE_DB_DIR".privilege.db.bkup"
SECURITY_MANAGER_POLICY_DIR="$TZ_SYS_RO_SHARE/security-manager/policy/"
SECURITY_MANAGER_POLICY_FILE_PRE="usertype-"
SECURITY_MANAGER_POLICY_FILE_POST=".profile"
SECURITY_MANAGER_GROUP_MAPPING_FILE=$SECURITY_MANAGER_POLICY_DIR"privilege-group.list"

PRIVILEGE_INFO_CSV="$PRIVILEGE_DB_DIR""privilege_info.csv"
PRIVILEGE_MAPPING_CSV="$PRIVILEGE_DB_DIR""privilege_mapping.csv"
PRIVACY_WHITELIST_CSV="$PRIVILEGE_DB_DIR""privacy_whitelist.csv"
PRIVILEGE_GROUP_MAPPING_LIST="$PRIVILEGE_DB_DIR""privilege-group.list"

SECURITY_MANAGER_DB=`tzplatform-get TZ_SYS_DB | cut -d= -f2`/.security-manager.db

UPDATE_ALL="false"
UPDATE_POLICY="false"

function backup {
    cp $PRIVILEGE_DB $PRIVILEGE_DB_BKUP
    local rst=$?
    if [ $rst -ne 0 ]
    then
        echo "[ERROR] backup failed. Exit status $rst"
        exit $rst
    fi
}
function restoreBackup {
    local trial_num=0
    local rst=1
    while [ $rst -ne 0 ] && [ $trial_num -lt 10 ]
    do
        cp $PRIVILEGE_DB_BKUP $PRIVILEGE_DB
        rst=$?
        ((trial_num++))
    done

    if [ $rst -ne 0 ]
    then
        echo "[ERROR] restoreBackup failed. Exit status $rst"

        exit $rst
    else
        rm $PRIVILEGE_DB_BKUP
    fi
}

function checkUpdateResult {
    local integritycheckresult=`sqlite3 $PRIVILEGE_DB "pragma integrity_check"`
    if [ "$integritycheckresult" == "ok" ]; then
        rm $PRIVILEGE_DB_BKUP
    else
        echo "[ERROR] Update failed. Restore backup."
        restoreBackup
    fi
}

function join { local IFS="$1 "; shift; echo "$*"; }

function printUsage {

    if [ $# -lt 1 ]; then
        echo -e "There was an error in command-line options:
No option specified, use '-h' or '--help' to print help message"
    else
        if [ "$1" == "help" ]
        then
            echo -e "
[Usage]
privilege-db-update <update-option> [parameters]

[Description]
Starred[*] parameters must be given.

Do all possible update with update-option a or all. (* No parameter required *)
    Prepare files containing update information at /usr/share/privilege-manager/
    with file name privilege_info.csv, privilege_mapping.csv, privacy_whitelist.csv and privilege-group.list

Add new privilege information with update-option i or info.
    Bulk file
        For bulk update, prepare .csv file with following columns:
            package_type,privilege_level,documented,privilege_name,privacy_name,privilege_display,privilege_description,privilege_group
        If the privilege is not a privacy privilege then left privacy_name field as blank. All other fields must be filled.
            [*]-f, --file               Bulk file path.
    Single privilege
            [*]-p, --privilege          Privilege name.
            [*]-t, --packagetype        Whether the privilege is for core, wrt, or metadata.
            -P, --privacy               Privacy group which the given privilege is included in.
                                        Don't give this parameter for NOT privacy privilege.
            [*]-l, --level              Privilege level.
            [*]-d, --display            DID of privilege's display name.
            [*]-D, --description        DID of privilege's description.
            -s, --documented            Whether privilege is added to SDK resources or not.
            [*]-g, --group              Privilege group.

Add new privilege mapping information with update-option m or mapping.
    Bulk file
        For bulk update, prepare .csv file with following columns:
            package_type,privilege_name,from_api_version,to_api_version,mapped_privilege_name
        All field must be filled.
            [*]-f, --file               Bulk file path.
            [*]-u, --usertype           User type. Use '*' to update all usertypes.
    Single privilege mapping
            [*]-p, --privilege          Privilege name.
            [*]-F, --from               api-version from (privilege mappinge {api-version from} <= {api-version}).
            [*]-T, --to                 api-version to (privilege mappinge {api-version} < {api-version to}).
            [*]-t, --packagetype        Whether the privilege is for core or wrt.
            [*]-m, --mappedprivilege    Mapped privilege name.
            [*]-u, --usertype           User type. Use '*' to update all usertypes.

Replace privacy whitelist with update-option w or whitelist. It wipes the existing whitelist and updates it with the given privacy whitelist file.
    For update, prepare .csv file with following columns:
        package_id,cert_level,privacy_option,settable
    All field must be filled.
    [*] <filepath>      Give .csv file path as parameter.

Add new privilege-gid mapping with update-option g or group.
    Bulk file
        For bulk update, prepare file with following format:
            <privilege name> <group name>
                ex) http://tizen.org/privilege/camera priv_camera
                    http://tizen.org/privilege/email priv_email
            [*] <filepath>      Bulk file path.
    Single gid mapping
        [*] <privilege name>    Give privilege name as parameter
        [*] <group name>        Give group name as parameter

ex)
privilege-db-update all
privilege-db-update info --file '/tmp/privilege_info.csv'
privilege-db-update i -p 'http://tizen.org/privilege/new.privilege' -t 'core' -d 'IDS_DISPLAY_NAME' -D 'IDS_DESCRIPTION' -g 'IDS_TPLATFORM_BODY_PERSONAL_INFORMATION_ABB' -s 'yes' -l 'partner'
privilege-db-update mapping --file '/tmp/privilege_mapping.csv' -u admin
privilege-db-update m --packagetype 'core' --privilege 'http://tizen.org/privilege/privilege.name' --from '2.3.1' --to '9.9' --mappedprivilege 'http://tizen.org/privilege/mapped.privilege.name' --usertype admin,system,security
privilege-db-update w '/tmp/privacy_whitelist.csv'
privilege-db-update whitelist '/tmp/privacy_whitelist.csv'
privilege-db-update g '/tmp/privilege-group-mapping.list'
privilege-db-update gid 'http://tizen.org/privilege/privilegename' 'priv_groupname'
            "
        elif [ "$1" == "privacy" ]; then
            privacy_list=`sqlite3 $PRIVILEGE_DB "select distinct privacy_name from privacy_info"`
            echo -e "Privacy name should be one of the followings:\n$privacy_list"
        elif [ "$1" == "packagetype" ]; then
            echo -e "Package type should be one of the followings: core, wrt, metadata"
        elif [ "$1" == "level" ]; then
            echo -e "Privilege level should be one of the followings: public, partner, platform"
        elif [ "$1" == "group" ]; then
            echo -e "Group should be one of the followings:
IDS_TPLATFORM_BODY_HARDWARE_CONTROLS_ABB
IDS_TPLATFORM_OPT_LOCATION_T_LBS
IDS_TPLATFORM_BODY_NETWORK_CONNECTIONS_ABB
IDS_TPLATFORM_BODY_PAID_SERVICES_ABB
IDS_TPLATFORM_BODY_PERSONAL_INFORMATION_ABB
IDS_TPLATFORM_BODY_SYSTEM_SETTINGS_ABB
IDS_TPLATFORM_BODY_OTHER_PRIVILEGES_ABB"
        elif [ "$1" == "documented" ]; then
            echo -e "Documented should be 'yes' or 'no'.\nIf the value is not written then the default value is 'yes'"
        elif [ "$1" == "usertype" ]; then
            local usertypelist=$(join , $(ls $SECURITY_MANAGER_POLICY_DIR | grep usertype | cut -d '-' -f2 | cut -d '.' -f1))
            echo -e "Use '*' to update all usertypes.\nOr choose valid usertypes from followings: $usertypelist
ex) -u '*'
    --usertype admin,security,guest"
        fi
    fi
    exit
}

function policy_load {
    find "$SECURITY_MANAGER_POLICY_DIR" -name "usertype-*.profile" |
    while read file
    do
        bucket="`echo $file | sed -r 's|.*/usertype-(.*).profile$|USER_TYPE_\1|' | tr '[:lower:]' '[:upper:]'`"

        grep -v ^\' $file |
        while read app privilege
        do
            user="*"        # Match any user id
            policy="0xFFFF" # ALLOW (FIXME: cyad should parse policy names, not numeric values)
            printf '%s;%s;%s;%s;%s;\n' "$bucket" "$user" "$app" "$privilege" "$policy"
        done |
        cyad --set-policy --bulk=-
    done

}

function gid_mapping {
    (
    echo "BEGIN;"
    echo "DELETE FROM privilege_group;"
    grep -v '^#' "$SECURITY_MANAGER_GROUP_MAPPING_FILE" |
    while read privilege group
    do
        echo "INSERT INTO privilege_group (privilege_name, group_name) VALUES ('$privilege', '$group');"
    done
    echo "COMMIT;"
    ) | sqlite3 "$SECURITY_MANAGER_DB"
}

function add_privilege_info {
    local mode bulkfile privilege level level_id display description group group_id packagetype packagetype_id
    local privacy="N/A" is_privacy=0 documented="yes"
    local input=(`echo "$@"`)

    for ((x=1; x<${#input[@]}; x=x+2));
    do
        if [ "${input[x]}" == "-f" ] || [ "${input[x]}" == "--file" ]
        then
            if [ "$mode" == "single" ]
            then
                echo "[ERROR] Do not use -p,--privilege with -f,--file"
                printUsage
            fi
            if [ -r ${input[$((x+1))]} ] && [ -f ${input[$((x+1))]} ]
            then
                bulkfile=${input[$((x+1))]}
            elif [ -r $SCRIPT_DIR"/${input[$((x+1))]}" ] && [ -f $SCRIPT_DIR"/${input[$((x+1))]}" ]
            then
                bulkfile=$SCRIPT_DIR"/${input[$((x+1))]}"
            fi
            if [ "$bulkfile" == "" ]; then
                echo "[ERROR] file(${input[$((x+1))]}) not exist or unreadable!!!"
                exit
            fi
            mode="bulk"
        elif [ "${input[x]}" == "-p" ] || [ "${input[x]}" == "--privilege" ]
        then
            if [ "$mode" == "bulk" ]
            then
                echo "[ERROR] Do not use -p,--privilege with -f,--file"
                printUsage
            fi
            privilege=${input[$((x+1))]}
            mode="single"
        elif [ "${input[x]}" == "-P" ] || [ "${input[x]}" == "--privacy" ]
        then
            privacy_exist=`sqlite3 $PRIVILEGE_DB "select exists(select 1 from privacy_info where privacy_name='${input[$((x+1))]}')"`
            if [ "$privacy_exist" != "1" ]; then
                echo "[ERROR] privacy ${input[$((x+1))]} not exist!"
                printUsage "privacy"
            fi
            privacy=${input[$((x+1))]}
            is_privacy=1
        elif [ "${input[x]}" == "-l" ] || [ "${input[x]}" == "--level" ]
        then
            level=${input[$((x+1))]}
            if [ "$level" == "public" ]; then
                level_id=0
            elif [ "$level" == "partner" ]; then
                level_id=1
            elif [ "$level" == "platform" ]; then
                level_id=2
            else
                echo "[ERROR] wrong privilege level"
                printUsage "level"
            fi
        elif [ "${input[x]}" == "-d" ] || [ "${input[x]}" == "--display" ]
        then
            display=${input[$((x+1))]}
        elif [ "${input[x]}" == "-D" ] || [ "${input[x]}" == "--description" ]
        then
            description=${input[$((x+1))]}
        elif [ "${input[x]}" == "-s" ] || [ "${input[x]}" == "--documented" ]
        then
            if [ "${input[$((x+1))]}" != "yes" ] && [ "${input[$((x+1))]}" != "no" ]
            then
                printUsage "documented"
            fi
            documented=${input[$((x+1))]}
        elif [ "${input[x]}" == "-g" ] || [ "${input[x]}" == "--group" ]
        then
            if [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_HARDWARE_CONTROLS_ABB" ]; then
                group_id=0
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_OPT_LOCATION_T_LBS" ]; then
                group_id=1
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_NETWORK_CONNECTIONS_ABB" ]; then
                group_id=2
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_PAID_SERVICES_ABB" ]; then
                group_id=3
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_PERSONAL_INFORMATION_ABB" ]; then
                group_id=4
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_SYSTEM_SETTINGS_ABB" ]; then
                group_id=5
            elif [ "${input[$((x+1))]}" == "IDS_TPLATFORM_BODY_OTHER_PRIVILEGES_ABB" ]; then
                group_id=6
            else
                echo "[ERROR] wrong group"
                printUsage "group"
            fi
            group=${input[$((x+1))]}
        elif [ "${input[x]}" == "-t" ] || [ "${input[x]}" == "--packagetype" ]
        then
            packagetype=${input[$((x+1))]}
            if [ "$packagetype" == "core" ]; then
                packagetype_id=1
            elif [ "$packagetype" == "wrt" ]; then
                packagetype_id=0
            elif [ "$packagetype" == "metadata" ]; then
                packagetype_id=2
            else
                echo "[ERROR] wrong packagetype"
                printUsage "packagetype"
            fi
        else
            printUsage
        fi
    done

    if [ "$mode" == "bulk" ]
    then
        bulk_add_privilege_info $bulkfile
    elif [ "$mode" == "single" ]
    then
        if [ "$privilege" == "" ]; then
            echo "[ERROR] privilege required"
            printUsage
        elif [ "$packagetype" == "" ]; then
            echo "[ERROR] packagetype required"
            printUsage "packagetype"
        elif [ "$display" == "" ] || [ "$description" == "" ]
        then
            echo "[ERROR] display and description required"
            printUsage
        elif [ "$group" == "" ]
        then
            echo "[ERROR] group required"
            printUsage "group"
        elif [ "$level" == "" ]
        then
            echo "[ERROR] privilege level required"
            printUsage "level"
        fi

        echo -e "Add privilege\n\nPackage type: $packagetype\nLevel: $level\nPrivilege: $privilege\nPrivacy: $privacy\nDisplay name: $display\nDescription: $description\nGroup: $group\nDocumented: $documented"

        backup

        sqlite3 $PRIVILEGE_DB "insert into privilege_info (
                                    package_type_id, package_type, privilege_level_id, privilege_level, documented, privilege_name,
                                    is_privacy, privacy_name, privilege_display, privilege_description, privilege_group_id, privilege_group)
                                values ($packagetype_id, '$packagetype', $level_id, '$level', '$documented', '$privilege',
                                        '$is_privacy', '$privacy', '$display', '$description', $group_id, '$group')"

        checkUpdateResult
    else
        printUsage
    fi
}

function bulk_add_privilege_info {

    sed -e "s/#//g" $1 > "$PRIVILEGE_DB_DIR/tmp.csv"

    backup
    sqlite3 -csv -separator "," $PRIVILEGE_DB ".import "$PRIVILEGE_DB_DIR/tmp.csv" tmp"

    # check if there's missing column
    cols=`sqlite3 $PRIVILEGE_DB "PRAGMA table_info(tmp)" | tr '[:upper:]' '[:lower:]' | cut -d "|" -f2`
    check_cols_num=8
    local i
    for i in ${cols[@]}
    do
        if [ "$i" == "package_type" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_name" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_display" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_description" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_group" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privacy_name" ]; then
            ((check_cols_num--))
        elif [ "$i" == "documented" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_level" ]; then
            ((check_cols_num--))
        fi
    done

    if [ $check_cols_num -ne 0 ]; then
        # missing column exists
        echo "[ERROR] There's missing column field in the given csv file: $1"
        rm "$PRIVILEGE_DB_DIR/tmp.csv"
        restoreBackup
        exit
    fi

    sqlite3 $PRIVILEGE_DB "
    insert into privilege_info (package_type_id, package_type, privilege_level_id, privilege_level, documented, privilege_name, is_privacy, privacy_name, privilege_display, privilege_description, privilege_group_id, privilege_group)
    select
        (case package_type
            when 'wrt' then 0
            when 'core' then 1
            when 'metadata' then 2 end),
        package_type,
        (case privilege_level
            when 'public' then 0
            when 'partner' then 1
            when 'platform' then 2 end),
        privilege_level,
        documented,
        privilege_name,
        case when package_type='core' and privacy_name != '' then 1 else 0 end,
        case when package_type='core' and privacy_name != '' then privacy_name else 'N/A' end,
        privilege_display,
        privilege_description,
        (case privilege_group
            when 'IDS_TPLATFORM_BODY_HARDWARE_CONTROLS_ABB' then 0
            when 'IDS_TPLATFORM_OPT_LOCATION_T_LBS' then 1
            when 'IDS_TPLATFORM_BODY_NETWORK_CONNECTIONS_ABB' then 2
            when 'IDS_TPLATFORM_BODY_PAID_SERVICES_ABB' then 3
            when 'IDS_TPLATFORM_BODY_PERSONAL_INFORMATION_ABB' then 4
            when 'IDS_TPLATFORM_BODY_SYSTEM_SETTINGS_ABB' then 5
            when 'IDS_TPLATFORM_BODY_OTHER_PRIVILEGES_ABB' then 6 end),
        privilege_group
        from tmp"
    sqlite3 $PRIVILEGE_DB "drop table tmp"
    rm "$PRIVILEGE_DB_DIR/tmp.csv"

    checkUpdateResult
}

function add_privilege_mapping {
    local mode bulkfile privilege mapped_privilege package_type version_from version_to usertype
    local input=("$@")

    # Get all input parameters
    for ((x=1; x<${#input[@]}; x=x+2));
    do
        if [ "${input[x]}" == "-f" ] || [ "${input[x]}" == "--file" ]
        then
            if [ "$mode" == "single" ]
            then
                echo "[ERROR] Do not use -p,--privilege with -f,--file"
                printUsage
            fi
            if [ -r ${input[$((x+1))]} ] && [ -f ${input[$((x+1))]} ]
            then
                bulkfile=${input[$((x+1))]}
            elif [ -r $SCRIPT_DIR"/${input[$((x+1))]}" ] && [ -f $SCRIPT_DIR"/${input[$((x+1))]}" ]
            then
                bulkfile=$SCRIPT_DIR"/${input[$((x+1))]}"
            fi
            if [ "$bulkfile" == "" ]; then
                echo "[ERROR] file(${input[$((x+1))]}) not exist  or unreadable!!!"
                exit
            fi
            mode="bulk"
        elif [ "${input[x]}" == "-u" ] || [ "${input[x]}" == "--usertype" ]
        then
            usertype="${input[$((x+1))]}"
            if [ "$usertype" != "*" ]
            then
                IFS=',' read -r -a usertypes <<< "$usertype"
                for userbucket in "${usertypes[@]}"
                do
                    check_userbucket=`find $SECURITY_MANAGER_POLICY_DIR -name "$SECURITY_MANAGER_POLICY_FILE_PRE$userbucket$SECURITY_MANAGER_POLICY_FILE_POST"`
                    if [ "$check_userbucket" == "" ]; then
                        echo "[ERROR] usertype $userbucket not exist!"
                        printUsage "usertype"
                    fi
                done
            else
                usertype=$(join , $(ls $SECURITY_MANAGER_POLICY_DIR | grep usertype | cut -d '-' -f2 | cut -d '.' -f1))
            fi
        elif [ "${input[x]}" == "-p" ] || [ "${input[x]}" == "--privilege" ]
        then
            if [ "$mode" == "bulk" ]
            then
                echo "[ERROR] Do not use -p,--privilege with -f,--file"
                printUsage
            fi
            mode="single"
            privilege=${input[$((x+1))]}
        elif [ "${input[x]}" == "-F" ] || [ "${input[x]}" == "--from" ]
        then
            version_from=${input[$((x+1))]}
        elif [ "${input[x]}" == "-T" ] || [ "${input[x]}" == "--to" ]
        then
            version_to=${input[$((x+1))]}
        elif [ "${input[x]}" == "-t" ] || [ "${input[x]}" == "--packagetype" ]
        then
            packagetype=${input[$((x+1))]}
            if [ "$packagetype" == "core" ]; then
                packagetype_id=1
            elif [ "$packagetype" == "wrt" ]; then
                packagetype_id=0
            else
                echo "[ERROR] wrong packagetype"
                printUsage "packagetype"
            fi
        elif [ "${input[x]}" == "-m" ] || [ "${input[x]}" == "--mappedprivilege" ]
        then
            mapped_privilege=${input[$((x+1))]}
        fi
    done

    if [ "$usertype" == "" ]; then
        echo "[ERROR] usertype required"
        printUsage "usertype"
    fi

    if [ "$mode" == "bulk" ]; then
        bulk_add_privilege_mapping $bulkfile $usertype
    elif [ "$mode" == "single" ]; then
        if [ "$privilege" == "" ]; then
            echo "[ERROR] privilege required"
            printUsage
        elif [ "$version_from" == "" ] || [ "$version_to" == "" ]
        then
            echo "[ERROR] api-version from/to required"
            printUsage
        elif [ "$mapped_privilege" == "" ]; then
            echo "[ERROR] mapped privilege required"
            printUsage
        elif [ "$packagetype" == "" ]; then
            echo "[ERROR] packagetype required"
            printUsage
        fi

        backup

        sqlite3 $PRIVILEGE_DB "insert into
        privilege_mapping (package_type_id, package_type, privilege_name, from_api_version, to_api_version, mapped_privilege_name)
        values ($packagetype_id, '$packagetype', '$privilege', '$version_from', '$version_to', '$mapped_privilege')"

        checkUpdateResult

        IFS=',' read -r -a usertypes <<< "$usertype"

        local userbucket_update=0
        for userbucket in "${usertypes[@]}"
        do
            userbucket_path="$SECURITY_MANAGER_POLICY_DIR$SECURITY_MANAGER_POLICY_FILE_PRE$userbucket$SECURITY_MANAGER_POLICY_FILE_POST"
            if [ -a "$userbucket_path" ]; then
                check_userbucket=`grep -rn "$mapped_privilege$" $userbucket_path | wc -l`

                if [ $check_userbucket -eq 0 ]; then
                    echo "*	$mapped_privilege" >> $userbucket_path
                    ((userbucket_update++))
                fi
            fi
        done
        if [ $userbucket_update -gt 0 ]; then
            if [ "$UPDATE_ALL" == "false" ]; then
                policy_load
            else
                UPDATE_POLICY="true"
            fi
        fi
    else
        printUsage
    fi
}

function bulk_add_privilege_mapping {
    sed -e "s/#//g" $1 > "$PRIVILEGE_DB_DIR/tmp.csv"

    backup
    sqlite3 -csv -separator "," $PRIVILEGE_DB ".import "$PRIVILEGE_DB_DIR/tmp.csv" tmp"

    cols=`sqlite3 $PRIVILEGE_DB "PRAGMA table_info(tmp)" | tr '[:upper:]' '[:lower:]' | cut -d "|" -f2`
    check_cols_num=5
    local i

    for i in ${cols[@]}
    do
        if [ "$i" == "package_type" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privilege_name" ]; then
            ((check_cols_num--))
        elif [ "$i" == "from_api_version" ]; then
            ((check_cols_num--))
        elif [ "$i" == "to_api_version" ]; then
            ((check_cols_num--))
        elif [ "$i" == "mapped_privilege_name" ]; then
            ((check_cols_num--))
        fi
    done
    if [ $check_cols_num -ne 0 ]; then
        echo "[ERROR] There's missing column field in the given csv file: $1"
        rm "$PRIVILEGE_DB_DIR/tmp.csv"
        restoreBackup
        exit
    fi

    sqlite3 $PRIVILEGE_DB "
    insert into privilege_mapping (package_type_id, package_type, privilege_name, from_api_version, to_api_version, mapped_privilege_name)
    select
        (case package_type
            when 'wrt' then 0
            when 'core' then 1 end),
        package_type,
        privilege_name,
        from_api_version,
        to_api_version,
        mapped_privilege_name
    from tmp"
    IFS=$'\r\n' read -r -a privileges <<< `sqlite3 $PRIVILEGE_DB "select distinct mapped_privilege_name from tmp"`
    sqlite3 $PRIVILEGE_DB "drop table tmp"
    rm "$PRIVILEGE_DB_DIR/tmp.csv"

    checkUpdateResult

    IFS=',' read -r -a usertypes <<< "$2"

    local userbucket_update=0
    for userbucket in "${usertypes[@]}"
    do
        userbucket_path="$SECURITY_MANAGER_POLICY_DIR$SECURITY_MANAGER_POLICY_FILE_PRE$userbucket$SECURITY_MANAGER_POLICY_FILE_POST"
        for privilege in $privileges
        do
                local check_userbucket=`grep -rn "$privilege$" $userbucket_path | wc -l`
                if [ $check_userbucket -eq 0 ]; then
                    echo "*	$privilege" >> $userbucket_path
                    ((userbucket_update++))
                fi

        done
    done
    if [ $userbucket_update -gt 0 ]; then
        if [ "$UPDATE_ALL" == "false" ]; then
            policy_load
        else
            UPDATE_POLICY="true"
        fi
    fi
}

function add_privacy_whitelist {
    if [ $# -lt 2 ]; then
        printUsage
    fi
    local bulkfile
    if [ -r $2 ] && [ -f $2 ]
    then
        bulkfile=$2
    elif [ -r $SCRIPT_DIR"/$2" ] && [ -f $SCRIPT_DIR"/$2" ]
    then
        bulkfile=$SCRIPT_DIR"/$2"
    fi
    if [ "$bulkfile" == "" ]; then
        echo "[ERROR] file($2) not exist or unreadable!!!"
        exit
    fi

    sed -e "s/#//g" $bulkfile > "$PRIVILEGE_DB_DIR/tmp.csv"

    backup

    sqlite3 -csv -separator "," $PRIVILEGE_DB ".import "$PRIVILEGE_DB_DIR/tmp.csv" tmp"

    cols=`sqlite3 $PRIVILEGE_DB "PRAGMA table_info(tmp)" | tr '[:upper:]' '[:lower:]' | cut -d "|" -f2`
    check_cols_num=4
    local i

    for i in ${cols[@]}
    do
        if [ "$i" == "package_id" ]; then
            ((check_cols_num--))
        elif [ "$i" == "privacy_option" ]; then
            ((check_cols_num--))
        elif [ "$i" == "settable" ]; then
            ((check_cols_num--))
        elif [ "$i" == "cert_level" ]; then
            ((check_cols_num--))
        fi
    done
    sqlite3 $PRIVILEGE_DB "drop table tmp"
    rm "$PRIVILEGE_DB_DIR/tmp.csv"
    if [ $check_cols_num -ne 0 ]; then
        echo "[ERROR] There's missing column field in the given csv file: $2"
        rm $PRIVILEGE_DB_BKUP
        exit
    fi
    local i
    local privacy_info_list=`sqlite3 $PRIVILEGE_DB "select distinct privacy_id, privacy_name from privacy_info"`
    for i in $privacy_info_list
    do
        PRIVACY_ID=`echo $i | cut -d "|" -f1`
        PRIVACY_NAME=`echo $i | cut -d "|" -f2`
        PRIVACY_NAME_ONLY=`echo $PRIVACY_NAME | cut -d "/" -f5`
        declare ${PRIVACY_NAME_ONLY}=$((PRIVACY_ID))
    done

    PRIVACY_NUM=$((PRIVACY_ID++))

    #Wipe existing whitelist and insert new privacy whitelist to avoid conflicts
    sqlite3 $PRIVILEGE_DB "delete from privacy_whitelist"
    for i in `cat $bulkfile`
    do
        temp=`echo $i | awk '/^#/'`
        if [ ! "$temp" = "" ]
        then
            continue
        fi
        PKG_ID=`echo $i | cut -d "," -f1`
        CERT_LEVEL=`echo $i | cut -d "," -f2`
        if [ "$CERT_LEVEL" = "platform" ]; then
            CERT_LEVEL_ID=2
        elif [ "$CERT_LEVEL" = "partner" ]; then
            CERT_LEVEL_ID=1
        else
            CERT_LEVEL_ID=0
        fi
        PRIVACY_OPTION=`echo $i | cut -d "," -f3`
        IFS='-+ ' read -r -a array <<< $PRIVACY_OPTION
        # init
        TEMP=0
        while [ $((TEMP)) -lt $((PRIVACY_ID)) ]
        do
            option_array[$((TEMP++))]=0
        done
        # privacy list set
        for element in "${array[@]}"
        do
            if [ "$element" = "*" ]; then
                TEMP=0
                while [ $((TEMP)) -lt $PRIVACY_ID ]
                do
                    option_array[$((TEMP++))]=1
                done
            else
                if [ "${option_array[${element}]}" = "1" ]; then
                    option_array[${element}]=0
                else
                    option_array[${element}]=1
                fi
            fi
        done
        SETTABLE=`echo $i | cut -d "," -f4`
        # privacy option string
        TEMP=0
        PRIVACY_OPTION_STRING=""
        while [ $((TEMP)) -lt $((PRIVACY_ID)) ]
        do
            PRIVACY_OPTION_STRING="$PRIVACY_OPTION_STRING""${option_array[$((TEMP++))]}"
        done
        #echo "insert into privacy_whitelist(pkg_id, cert_level, privacy_option, settable) values ('$PKG_ID', $CERT_LEVEL_ID, '$PRIVACY_OPTION_STRING', '$SETTABLE')"
        sqlite3 $PRIVILEGE_DB "insert into privacy_whitelist(pkg_id, cert_level, privacy_option, settable) values ('$PKG_ID', $CERT_LEVEL_ID, '$PRIVACY_OPTION_STRING', '$SETTABLE')"
    done
    checkUpdateResult
}

function add_gid_mapping {
    if [ $# -lt 2 ];then
        printUsage
    elif [ $# -eq 2 ]; then
        local bulkfile
        if [ -r $2 ] && [ -f $2 ]
        then
            bulkfile="$2"
        elif [ -r $SCRIPT_DIR"/$2" ] && [ -f $SCRIPT_DIR"/$2" ]
        then
            bulkfile="$SCRIPT_DIR/$2"
        fi
        if [ "$bulkfile" == "" ]
        then
            echo "[ERROR] file($2) not exist or unreadable"
            printUsage
        else
            while IFS='' read -r line || [[ -n "$line" ]]; do
                local check_gid_mapping=`grep -rn "$line$" $SECURITY_MANAGER_GROUP_MAPPING_FILE | wc -l`
                if [ $check_gid_mapping -eq 0 ]; then
                    echo "$line" >> $SECURITY_MANAGER_GROUP_MAPPING_FILE
                fi
            done < $bulkfile
        fi
    elif [ $# -eq 3 ]; then
        local check_gid_mapping=`grep -rn "$2 $3$" $SECURITY_MANAGER_GROUP_MAPPING_FILE | wc -l`
        if [ $check_gid_mapping -eq 0 ]; then
            echo "$2 $3" >> $SECURITY_MANAGER_GROUP_MAPPING_FILE
        fi
    else
        printUsage
    fi
    if [ "$UPDATE_ALL" == "false" ]; then
        gid_mapping
    else
        UPDATE_POLICY="true"
    fi
}

#======================================================================
# [00] Check parameter
#======================================================================

param_count=$#

if [ ! -w $PRIVILEGE_DB ]
then
    echo "[ERROR] DB not writable!!"
    exit 1
fi

if [ ! -e  /usr/bin/security-manager-policy-reload ]
then
    echo "[ERROR] security-manager-policy-reload not exist!"
    exit 1
fi

if [ $param_count -lt 1 ]; then
    printUsage
elif [ "$1" == "a" ] || [ "$1" == "all" ]
then
    UPDATE_ALL="true"
    if [ -r $PRIVILEGE_INFO_CSV ]; then
        bulk_add_privilege_info $PRIVILEGE_INFO_CSV
    fi
    if [ -r $PRIVILEGE_MAPPING_CSV ]; then
        bulk_add_privilege_mapping $PRIVILEGE_MAPPING_CSV '*'
    fi
    if [ -r $PRIVACY_WHITELIST_CSV ]; then
        add_privacy_whitelist w $PRIVACY_WHITELIST_CSV
    fi
    if [ -r $PRIVILEGE_GROUP_MAPPING_LIST ]; then
        add_gid_mapping g $PRIVILEGE_GROUP_MAPPING_LIST
    fi
    if [ "$UPDATE_POLICY" == "true" ]
    then
        policy_load
        gid_mapping
    fi
elif [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
    printUsage "help"
elif [ "$1" == "i" ] || [ "$1" == "info" ]
then
    add_privilege_info $@
elif [ "$1" == "m" ] || [ "$1" == "mapping" ]
then
    add_privilege_mapping "$@"
elif [ "$1" == "w" ] || [ "$1" == "whitelist" ]
then
    add_privacy_whitelist $@
elif [ "$1" == "g" ] || [ "$1" == "gid" ]
then
    add_gid_mapping $@
else
    printUsage
fi
exit
