MAX_IMAGE_WIDTH=4096
BITMAP_FORMAT=png
BAR_ID=BAR1
BAR_VER=1
ARCHIVE_TYPE=TGZ_
SIGNATURE_TYPE=RSA_
END_OF_ARCHIVE=EBAR
export LANG=en_US.UTF-8
CMD=`basename $0`
USAGE="$CMD -x|-c
[ -f|--file bitmap-archive ]
[ -s|--secret secret_key | -p|--private public_key ]
[ -b|--bitmap png|bmp ]
[ file... ] "
COLOR_DEPTH=24
GETOPT_FORM=`getopt -o cxvf:s:p:b: \
--long create,extract,verbose,help,file:,secret:,public:,bitmap: \
-n $CMD -- "$@"`
eval set -- "$GETOPT_FORM"
while true ; do
case "$1" in
-c|--create) OPER_C=Y ; OPERATION=create; shift ;;
-x|--extract) OPER_X=Y ; OPERATION=extract; shift ;;
-v|--verbose) TAR_OPT="-v" ; shift ;;
-f|--file) ARCHIVE_FILE="$2" ; shift 2 ;;
-s|--secret) PRIVATE_KEY="$2" ; shift 2 ;;
-p|--public) PUBLIC_KEY="$2" ; shift 2 ;;
-b|--bitmap) BITMAP_FORMAT_SPEC="$2" ; shift 2 ;;
--help) echo "$USAGE" >&2 ; exit 1 ;;
--) shift ; break ;;
*) echo "Internal error!" >&2 ; exit 1 ;;
esac
done
for arg do SRC_FILES="$SRC_FILES \"$arg\""; done
TAR_TEMP_FILE=`mktemp "$CMD.TAR_XXXXXXXXXX.tgz"`
SIGNATURE_TEMP_FILE=`mktemp "$CMD.SIG_XXXXXXXXXX.sig"`
BMP_Temp_File=`mktemp "$CMD.BMP_XXXXXXXXXX.bmp"`
PNG_Temp_File=`mktemp "$CMD.PNG_XXXXXXXXXX.png"`
trap 'clean_exit 2' 0 INT QUIT TRAP USR1 PIPE TERM
clean_exit ()
{
trap - 0 INT QUIT TRAP USR1 PIPE TERM
rm -rf "$TAR_TEMP_FILE"
rm -rf "$SIGNATURE_TEMP_FILE"
rm -rf "$BMP_Temp_File"
rm -rf "$PNG_Temp_File"
exit $1
}
tohex8 ()
{
DECIMAL=$1
UPPER=`expr \( $DECIMAL - \( $DECIMAL / 256 \* 256 \) \) / 16`
LOWER=`expr $DECIMAL - \( $DECIMAL / 16 \* 16 \)`
HEX_CHARS="0123456789ABCDEF"
echo -n "\\x${HEX_CHARS:$UPPER:1}${HEX_CHARS:$LOWER:1}"
}
tohex16 ()
{
DECIMAL=$1
BYTE_0=`expr \( $DECIMAL - \( $DECIMAL / 65536 \* 65536 \) \) / 256`
BYTE_1=`expr $DECIMAL - \( $DECIMAL / 256 \* 256 \)`
echo -n `tohex8 $BYTE_1;tohex8 $BYTE_0`
}
tohex32 ()
{
DECIMAL=$1
BYTE_0=`expr \( $DECIMAL - \( $DECIMAL / 4294967296 \* 4294967296 \) \) / 16777216`
BYTE_1=`expr \( $DECIMAL - \( $DECIMAL / 16777216 \* 16777216 \) \) / 65536`
BYTE_2=`expr \( $DECIMAL - \( $DECIMAL / 65536 \* 65536 \) \) / 256`
BYTE_3=`expr $DECIMAL - \( $DECIMAL / 256 \* 256 \)`
echo -n `tohex8 $BYTE_3;tohex8 $BYTE_2;tohex8 $BYTE_1;tohex8 $BYTE_0`
}
exec_create ()
{
eval tar zcf $TAR_TEMP_FILE "$TAR_OPT" $SRC_FILES 2> /dev/null
if [ $? -ne 0 ]; then
echo "${CMD}: arciving error." >&2
clean_exit 1
fi
SIGNATURE_BYTES=0
if [ -n "$PRIVATE_KEY" ]; then
MD5SUM=`md5sum -b < "$TAR_TEMP_FILE" | cut -f 1 -d " "`
echo -n "$MD5SUM" | openssl rsautl -out "$SIGNATURE_TEMP_FILE" -sign -inkey "$PRIVATE_KEY" 2> /dev/null
if [ $? -ne 0 ]; then echo "${CMD}: could not generate the SIGNATURE_TEMP_FILE." >&2 ; fi
touch "$SIGNATURE_TEMP_FILE"
SIGNATURE_BYTES=`wc -c "$SIGNATURE_TEMP_FILE" | cut -f 1 -d " "`
fi
IMAGE_WIDTH=$MAX_IMAGE_WIDTH
TAR_TEMP_BYTES=`wc -c "$TAR_TEMP_FILE" | cut -f 1 -d " "`
IMAGE_BYTES=`expr 4 + 4 + 4 + $TAR_TEMP_BYTES + 4 + 4 + $SIGNATURE_BYTES + 4 + 4`
IMAGE_PIXS=`expr \( $IMAGE_BYTES \* 8 + $COLOR_DEPTH - 1 \) / $COLOR_DEPTH`
if [ $IMAGE_PIXS -lt `expr $MAX_IMAGE_WIDTH \* $MAX_IMAGE_WIDTH` ]; then
for (( WIDTH=1 ; WIDTH<=$MAX_IMAGE_WIDTH ; WIDTH*=2 )); do
SQUARE=`expr $WIDTH \* $WIDTH`
if [ $IMAGE_PIXS -lt $SQUARE ]; then break; fi
done
if [ $WIDTH -gt $MAX_IMAGE_WIDTH ]; then WIDTH=$MAX_IMAGE_WIDTH; fi
IMAGE_WIDTH=$WIDTH
fi
IMAGE_HEIGHT=`expr \( $IMAGE_PIXS + $IMAGE_WIDTH - 1 \) / $IMAGE_WIDTH`
PADDING_BYTES=`expr \( $IMAGE_WIDTH \* $IMAGE_HEIGHT \) \* $COLOR_DEPTH / 8 - $IMAGE_BYTES`
BF_TYPE=BM
BF_SIZE=`expr 54 + $IMAGE_BYTES + $PADDING_BYTES`
BF_RESERVED_1=0
BF_RESERVED_2=0
BF_OFFSET=54
BI_HEADER_SIZE=40
BI_WIDTH=$IMAGE_WIDTH
BI_HEIGHT=$IMAGE_HEIGHT
BI_PLANES=1
BI_BITCOUNT=$COLOR_DEPTH
BI_COMPRESSION=0
BI_IMAGE_SIZE=`expr $IMAGE_BYTES + $PADDING_BYTES`
BI_X_BPM=2834
BI_Y_BPM=2834
BI_COLOR_USED=0
BI_COLOR_IMPORTANT=0
(
exec 2> /dev/null
exec > "$BMP_Temp_File"
echo -n "$BF_TYPE"
echo -n -e `tohex32 $BF_SIZE`
echo -n -e `tohex16 $BF_RESERVED_1`
echo -n -e `tohex16 $BF_RESERVED_2`
echo -n -e `tohex32 $BF_OFFSET`
echo -n -e `tohex32 $BI_HEADER_SIZE`
echo -n -e `tohex32 $BI_WIDTH`
echo -n -e `tohex32 $BI_HEIGHT`
echo -n -e `tohex16 $BI_PLANES`
echo -n -e `tohex16 $BI_BITCOUNT`
echo -n -e `tohex32 $BI_COMPRESSION`
echo -n -e `tohex32 $BI_IMAGE_SIZE`
echo -n -e `tohex32 $BI_X_BPM`
echo -n -e `tohex32 $BI_Y_BPM`
echo -n -e `tohex32 $BI_COLOR_USED`
echo -n -e `tohex32 $BI_COLOR_IMPORTANT`
# echo -n -e $RGB_QUAD_1
# echo -n -e $RGB_QUAD_2
echo -n "$BAR_ID"
echo -n -e `tohex32 4`
echo -n -e `tohex32 $BAR_VER`
echo -n "$ARCHIVE_TYPE"
echo -n -e `tohex32 $TAR_TEMP_BYTES`
cat $TAR_TEMP_FILE
echo -n "$SIGNATURE_TYPE"
echo -n -e `tohex32 $SIGNATURE_BYTES`
if [ $SIGNATURE_BYTES -ne 0 ]; then
cat "$SIGNATURE_TEMP_FILE"
fi
echo -n "$END_OF_ARCHIVE"
echo -n -e `tohex32 0`
head -c "$PADDING_BYTES" /dev/zero
)
SOURCE_TEMP_FILE="$BMP_Temp_File"
if [ "$BITMAP_FORMAT" = png ]; then
convert "$BMP_Temp_File" "$PNG_Temp_File"
SOURCE_TEMP_FILE="$PNG_Temp_File"
fi
if [ -z "$ARCHIVE_FILE" ]; then
cat "$SOURCE_TEMP_FILE"
else
cp "$SOURCE_TEMP_FILE" "$ARCHIVE_FILE"
fi
}
exec_extract ()
{
if [ -z "$ARCHIVE_FILE" ]; then
cat > "$PNG_Temp_File"
else
cp -f "$ARCHIVE_FILE" "$PNG_Temp_File"
fi
FILE_TYPE=`file -b "$PNG_Temp_File" | cut -f 1 -d ","`
case "$FILE_TYPE" in
"PNG image data")
convert "$PNG_Temp_File" "$BMP_Temp_File"
;;
"PC bitmap data")
cp -f "$PNG_Temp_File" "$BMP_Temp_File"
;;
*)
echo "${CMD}: input data type \"$FILE_TYPE\" is unknown." >&2
clean_exit 1
;;
esac
DEFAULT_OFFSET=54
BF_TYPE=`hexdump -s 0 -n 2 -e "\"%c\"" "$BMP_Temp_File"`
if [ "$BF_TYPE" != "BM" ]; then echo "${CMD}: Archive format error." >&2 ; clean_exit 1; fi
BF_SIZE=`hexdump -s 2 -n 4 -e "\"%u\"" "$BMP_Temp_File"`
BF_RESERVED_1=`hexdump -s 6 -n 2 -e "\"%u\"" "$BMP_Temp_File"`
BF_RESERVED_2=`hexdump -s 8 -n 2 -e "\"%u\"" "$BMP_Temp_File"`
BF_OFFSET=`hexdump -s 10 -n 4 -e "\"%u\"" "$BMP_Temp_File"`
if [ "$BF_OFFSET" -ne "$DEFAULT_OFFSET" ]; then echo "${CMD}: Archive format error." >&2 ; clean_exit 1; fi
TOTAL_NET_SIZE=0
FRAME_OFFSET=`expr $BF_OFFSET`
FRAME_NAME=`hexdump -s $FRAME_OFFSET -n 4 -e "\"%c\"" "$BMP_Temp_File"`
FRAME_BYTES_OFFSET=`expr $FRAME_OFFSET + 4`
FRAME_BYTES=`hexdump -s $FRAME_BYTES_OFFSET -n 4 -e "\"%u\"" "$BMP_Temp_File"`
FRAME_BODY_OFFSET=`expr $FRAME_OFFSET + 8`
TOTAL_NET_SIZE=`expr $TOTAL_NET_SIZE + 4 + 4 + $FRAME_BYTES`
while [ "$FRAME_NAME" != "$END_OF_ARCHIVE" ]; do
case "$FRAME_NAME" in
"$BAR_ID")
BAR_VAR=`hexdump -s $FRAME_BODY_OFFSET -n $FRAME_BYTES -e "\"%u\"" "$BMP_Temp_File"`
;;
"$ARCHIVE_TYPE")
tail -c +`expr $FRAME_BODY_OFFSET + 1` "$BMP_Temp_File" 2> /dev/null \
| head -c "$FRAME_BYTES" 2> /dev/null \
> "$TAR_TEMP_FILE"
if [ $? -ne 0 ]; then echo "${CMD}: Extracting archive error." >&2 ; clean_exit 1; fi
tar xf "$TAR_TEMP_FILE" "$TAR_OPT"
if [ $? -ne 0 ]; then echo "${CMD}: Extracting file error." >&2 ; clean_exit 1; fi
;;
"$SIGNATURE_TYPE")
if [ $FRAME_BYTES -ne 0 ]; then
tail -c +`expr $FRAME_BODY_OFFSET + 1` "$BMP_Temp_File" 2> /dev/null \
| head -c "$FRAME_BYTES" 2> /dev/null \
> "$SIGNATURE_TEMP_FILE"
if [ $? -ne 0 ]; then echo "${CMD}: WARNING, Extracting signature error." >&2 ; return 1; fi
if [ -n "$PUBLIC_KEY" ]; then
SIGNATURE=`openssl rsautl -in "$SIGNATURE_TEMP_FILE" -verify -pubin -inkey "$PUBLIC_KEY" 2> /dev/null`
if [ -n "$SIGNATURE" ]; then
MD5SUM=`md5sum -b < "$TAR_TEMP_FILE" | cut -f 1 -d " "`
if [ "$SIGNATURE" = "$MD5SUM" ]; then
echo "${CMD}: SIGNATURE was verified." >&2
else
echo "${CMD}: WARNING, SIGNATURE was incorrect." >&2
fi
else
echo "${CMD}: WARNING, unable to extract SIGNATURE." >&2
fi
else
echo "${CMD}: WARNING, SIGNATURE was not verified, Public key was missing." >&2
fi
fi
;;
*)
echo "${CMD}: Unknown frame error." >&2
clean_exit 1
;;
esac
FRAME_OFFSET=`expr $FRAME_OFFSET + 4 + 4 + $FRAME_BYTES`
FRAME_NAME=`hexdump -s $FRAME_OFFSET -n 4 -e "\"%c\"" "$BMP_Temp_File"`
FRAME_BYTES_OFFSET=`expr $FRAME_OFFSET + 4`
FRAME_BYTES=`hexdump -s $FRAME_BYTES_OFFSET -n 4 -e "\"%u\"" "$BMP_Temp_File"`
FRAME_BODY_OFFSET=`expr $FRAME_OFFSET + 8`
TOTAL_NET_SIZE=`expr $TOTAL_NET_SIZE + 4 + 4 + $FRAME_BYTES`
done
if [ "$TOTAL_NET_SIZE" -gt "$BF_SIZE" ]; then echo "${CMD}: Format error." >&2 ; clean_exit 1; fi
}
if [ "${OPER_C}${OPER_X}" != "Y" ];then echo "$USAGE" >&2 ; clean_exit 1; fi
case $OPERATION in
create)
if [ -z "$SRC_FILES" ]; then
echo "${CMD}: Cowardly refusing to create an empty archive" >&2
clean_exit 1
fi
if [ -n "$ARCHIVE_FILE" ]; then
if [ -e "$ARCHIVE_FILE" ]; then
if [ ! -f "$ARCHIVE_FILE" ]; then
echo "${CMD}: \"$ARCHIVE_FILE\": Cannot read: Is not a regular file" >&2
clean_exit 1;
fi
if [ ! -w "$ARCHIVE_FILE" ]; then
echo "${CMD}: \"$ARCHIVE_FILE\": Cannot open: Permission denied" >&2
clean_exit 1;
fi
fi
SUFFIX=`basename "$ARCHIVE_FILE" | tr "." "\n" | tail -1`
case "$SUFFIX" in
png|PNG) BITMAP_FORMAT=png ;;
bmp|BMP) BITMAP_FORMAT=bmp ;;
esac
fi
case "$BITMAP_FORMAT_SPEC" in
png|PNG) BITMAP_FORMAT=png ;;
bmp|BMP) BITMAP_FORMAT=bmp ;;
"") ;;
*)
echo "${CMD}: Bitmap format \"$BITMAP_FORMAT\" is invalid." >&2
clean_exit 1
;;
esac
if [ -n "$PRIVATE_KEY" -a -e "$PRIVATE_KEY" ]; then
if [ ! -f "$PRIVATE_KEY" ]; then
echo "${CMD}: \"$PRIVATE_KEY\": Cannot read: Is not a regular file" >&2
clean_exit 1;
fi
if [ ! -r "$PRIVATE_KEY" ]; then
echo "${CMD}: \"$PRIVATE_KEY\": Cannot open: Permission denied" >&2
clean_exit 1;
fi
fi
if [ -n "$PUBLIC_KEY" ]; then
echo "${CMD}: \"secret (private)\" key is needed." >&2
clean_exit 1;
fi
exec_create
;;
extract)
if [ -n "$ARCHIVE_FILE" ]; then
if [ ! -e "$ARCHIVE_FILE" ]; then
echo "${CMD}: \"$ARCHIVE_FILE\": Cannot open: No such file or directory" >&2
clean_exit 1;
fi
if [ ! -f "$ARCHIVE_FILE" ]; then
echo "${CMD}: \"$ARCHIVE_FILE\": Cannot read: Is not a regular file" >&2
clean_exit 1;
fi
if [ ! -r "$ARCHIVE_FILE" ]; then
echo "${CMD}: \"$ARCHIVE_FILE\": Cannot open: Permission denied" >&2
clean_exit 1;
fi
fi
if [ -n "$PRIVATE_KEY" ]; then
echo "${CMD}: \"public\" key is needed." >&2
clean_exit 1;
fi
if [ -n "$BITMAP_FORMAT_SPEC" ]; then
echo "${CMD}: Bitmap format specification is ignored." >&2
fi
exec_extract
;;
esac
clean_exit 0