diff --git a/stpkg b/stpkg
index d13e08fea7369168780d501ef1f56b588511b377..e03b6da0d2e5d9ab69e5c01fb7790c41948ac61d 100755
--- a/stpkg
+++ b/stpkg
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+shopt -s nocasematch    # Case insensitive
+
 STPKG_CONF_FILE=~/.config/stpkg.sh
 BASE_DIR="$PWD"
 
@@ -18,7 +20,9 @@ if [ "x$STPKG_COLORS" = "x" ]; then
     __green()   { echo -ne '\e[32m'$*'\e[0m'; }
     __yellow()  { echo -ne '\e[33m'$*'\e[0m'; }
 
-    __bold()    { echo -ne '\033[1m'$*'\e[0m'; }
+    __bold()      { echo -ne '\033[1m'$*'\e[0m'; }
+    __italic()    { echo -ne '\033[3m'$*'\e[0m'; }
+    __underline() { echo -ne '\033[4m'$*'\e[0m'; }
 else
     STPKG_COLORS="no"
     error() { echo 'ERROR:' $* >/dev/stderr; }
@@ -30,6 +34,8 @@ else
     alias __yellow=echo
 
     alias __bold=echo
+    alias __italic=echo
+    alias __underline=echo
 fi
 
 die() {
@@ -40,35 +46,22 @@ die() {
 # Be paranoid
 REQUIREMENTS=""
 require() {
-    local __cmd=`which $1`
-    [ $? -ne 0 ] && die "Failed to find the '$1' command"
-    alias $1=$__cmd
-    REQUIREMENTS="$1 $REQUIREMENTS"
+    for CMD in $*; do
+        local __cmd=`which $1`
+        [ $? -ne 0 ] && die "Failed to find the '$1' command"
+        REQUIREMENTS="$CMD $REQUIREMENTS"
+    done
 }
-require md5sum
-require mktemp
-require column
-require uuidgen
-require convert
-require montage
-require identify
-require python
-require curl
-require sed
-require tr
-require git
-require sponge
-require ls
-require find
-require jq
-require chmod
+require \
+    md5sum mktemp column uuidgen convert montage identify python curl \
+    sed tr git sponge ls find jq chmod cat expr iconv
 __grep=`which egrep`
 if [ $? -ne 0 ]; then
     __grep=`which grep`
     [ $? -ne 0 ] && die "Failed to find 'grep' or 'egrep'"
-    warn "Cound not find 'grep', will use 'egrep 'instead"
+    warn "Cound not find 'egrep', will use 'grep' instead." \
+         "Please, note that some functionalities may not work with regular expressions."
 fi
-alias grep=$__grep
 
 SELF=`readlink -f "$0"`
 MD5=`md5sum $SELF`
@@ -90,50 +83,49 @@ STPKG_HOMESERV=`echo "$STPKG_HOMESERV" | iconv -c -t ascii//TRANSLIT | sed -e 's
 # Some basic functions #
 ########################
 
-__exit() {
-    cd "$BASE_DIR"
-    exit $1
-}
+__exit() { cd "$BASE_DIR"; exit $1; }
 __EXIT() { cd "$BASE_DIR"; }
 trap __exit EXIT
 alias exit=__exit
 
 usage() {
-    local BASE_NAME=`basename $0`
+    local BASE_NAME=$(basename $0)
+    echo `__bold "$BASE_NAME usage:"`
+    local BASE_NAME=`__green "$BASE_NAME"`
 cat << EOF
-`__bold $BASE_NAME usage:`
-    $BASE_NAME -install [-sshfs username@server -local mnt_point] [install path]
+    $BASE_NAME -install [`__yellow "-sshfs 'username@server' -local mnt_point"`] [`__yellow "install_path"`]
+    $BASE_NAME show
+    $BASE_NAME help
     $BASE_NAME update
-    $BASE_NAME list [-p -e -np] [bash regex]
-    $BASE_NAME add <pack>
-    $BASE_NAME del <pack>
-    $BASE_NAME pack [-t token] [name] <pack folder>
+    $BASE_NAME list [`__yellow "-p -e -np"`] [`__yellow "bash_regex"`]
+    $BASE_NAME add|del <`__yellow "pack"`>
+    $BASE_NAME pack [`__yellow "-t token"`] [`__yellow "name"`] <`__yellow "pack_folder"`>
+    $BASE_NAME display [`__yellow "-dl folder"`] <`__yellow "pack_name"`> [`__yellow "sticker_regex"`]
+    $BASE_NAME edit <`__yellow "pack_name"`> add|del <`__yellow "sticker"`> [`__yellow "file"`]
 
 `__bold Flags:`
-    -e / -ne    The pack is enabled / disabled
-    -p / -np    The pack is present / not present in the sticker repo
-    -t    Matrix user token
-
-`__bold ENV variables:`
-    STPKG_INSTALL  [path]        The cloned stickerpicker project location. [~/html/stickerpicker]
-    STPKG_BASE     [path]        Where the sticker project is located.
-    STPKG_COLORS   ['yes'|'no']  Use colors for output. ['yes']
-    STPKG_NO_MSG   ['yes'|'no']  Disable messages, no 'info', 'warn' or 'error'. ['no']
-    STPKG_TOKEN    [token]       The Matrix access token `__bold \! Sensitive data \!`
-    STPKG_HOMESERV [homeserv]    The Matrix home server. ['iiens.net']
+    `__yellow "-e"` / `__yellow "-ne"`    The pack is enabled / disabled
+    `__yellow "-p"` / `__yellow "-np"`    The pack is present / not present in the sticker repo
+    `__yellow "-t"`          Matrix user token
+    `__yellow "-dl"`         Specify a folder to dl, may exists or not
+
+`__bold Configuration variables from $(echo '~/.config/stpkg.sh'):`
+    `__green STPKG_INSTALL`  [`__italic 'path'`]      The cloned stickerpicker project location. [$(__yellow `__italic '~/html/stickerpicker'`)]
+    `__green STPKG_BASE`     [`__italic 'path'`]      Where the sticker project is located.
+    `__green STPKG_COLORS`   [`__italic "yes|no"`]    Use colors for output. [$(__yellow `__italic "yes"`)]
+    `__green STPKG_NO_MSG`   [`__italic "yes|no"`]    Disable messages, no 'info' or 'warn'. [$(__yellow `__italic 'no'`)]
+    `__green STPKG_TOKEN`    [`__italic 'token'`]     The Matrix access token. $(__red `__bold \! Sensitive data \!`)
+    `__green STPKG_HOMESERV` [`__italic 'homeserv'`]  The Matrix home server. [$(__yellow `__italic 'iiens.net'`)]
 
 `__bold Notes:`
-    The 'stpkg -install [path]' must be called only once. The default install
-    path is ~/html/stickerpicker. This command will give you a STPKG_INSTALL
-    and a STPKG_BASE env that you must put in your bashrc for the rest of the
+    The `__italic "$(__yellow 'stpkg -install [path]')"` must be called only once. The default install
+    path is `__italic "$(__yellow '~/html/stickerpicker')"`. This command will give you a `__italic $(__yellow STPKG_INSTALL)`
+    and a `__italic $(__yellow STPKG_BASE)` env that you must put in your bashrc for the rest of the
     stpkg commands to work.
 
 `__bold Requirements:`
-    The stpkg command requires 'jq' and 'egrep'. If 'egrep' is not found,
-    'grep' will be used. 'git' is obviously required, but if you are using this
-    repo you should have clone it so it's ok.
-
-    Here is a list of all the requirements:
+    The stpkg command requires `__italic $(__yellow 'egrep')`. If `__italic $(__yellow 'egrep')` is not found, `__italic $(__yellow 'grep')` will be
+    used instead. Here is a list of all the requirements:
     $REQUIREMENTS
 EOF
     exit 0
@@ -147,8 +139,98 @@ slugify() {
 }
 
 default_index() {
-    jq -n "{ \"homeserver_url\": \"https://matrix.iiens.net\",
-             \"packs\": [ \"scalar-privacy_pam.json\" ] }"
+    jq -n "{ \"homeserver_url\": \"https://matrix.iiens.net\", \"packs\": [ \"scalar-privacy_pam.json\" ] }"
+}
+
+validate_token_internal() {
+    curl -s -X POST "https://$STPKG_HOMESERV/_matrix/media/r0/upload?access_token=$STPKG_TOKEN" | \
+        python3 -c "import sys, json; print(json.load(sys.stdin)['errcode'])" # TODO: Use jq here
+}
+
+validate_token() {
+    local RES=`validate_token_internal`
+    [ "x$RES" = "xM_UNKNOWN_TOKEN" ] && die "The token is incorrect or doesn't exist on '$STPKG_HOMESERV'"
+    [ ! "x$RES" = "xM_UNKNOWN" ]     && die "Got an 'yet implemented' error"
+    info "Token is valid on homeserv '$STPKG_HOMESERV'"
+}
+
+validate_homeserv() {
+    curl "https://$STPKG_HOMESERV" >/dev/null 2>&1
+    [ $? -ne 0 ] && die "Homeserv '$STPKG_HOMESERV' doesn't exist or is inaxessible"
+}
+
+file_get_width() {
+    local WIDTH=$(identify -format "%w" "$1") >/dev/null
+    local WIDTH=$(( $WIDTH  > 256 ? 256 : $WIDTH ))
+    echo "$WIDTH"
+}
+
+file_get_height() {
+    local HEIGHT=$(identify -format "%h" "$1") >/dev/null
+    local HEIGHT=$(( $HEIGHT > 256 ? 256 : $HEIGHT ))
+    echo "$HEIGHT"
+}
+
+file_get_type() { [[ "$1" =~ .*\.gif ]] && echo 'gif' || echo 'png'; }
+file_get_name() { echo "$1" | cut -f1 -d'.'; }
+
+upload_file() {
+    local TYPE=$1   # The type of file (png/gif)
+    local FILE=$2   # The file
+    local NAME=$3   # The pretty name for the sticker
+    # TODO: Use jq here
+    curl -s -X POST -H \
+        "Content-Type: image/$TYPE" --data-binary "@$DEST" "https://$STPKG_HOMESERV/_matrix/media/r0/upload?access_token=$STPKG_TOKEN" | \
+        tee /tmp/toto | python -c "import sys, json; print(json.load(sys.stdin)['content_uri'])"
+    [ $? -ne 0 ] && die "Failed to upload sticker $NAME for pack $PACK_NAME to $STPKG_HOMESERV"
+}
+
+picture_process_sticker() {
+    # NOTE: This command will display some progress dots...
+
+    local FILE=$1   # The source file
+    local DEST=$2   # The destination file
+    local NAME=$3   # The pretty name of the sticker
+    local WIDTH=$4  # The WIDTH!
+    local HEIGHT=$5 # The HEIGHT!
+    local TYPE=$6   # The type of the file (png/gif)
+
+    local OPTS=`[ "$TYPE" = "png" ] && echo '-type TrueColor PNG32:' || echo ''`
+
+    convert "$FILE" -bordercolor none -border 1 "$DEST" 1>&2    && progress_dot || die "$NAME failed on border"
+    convert "$DEST" -trim +repage "$DEST" 1>&2                  && progress_dot || die "$NAME failed on trim"
+    convert -background none -gravity center "$DEST" -resize "${WIDTH}x${HEIGHT}" $OPTS"$DEST" 1>&2 \
+        && progress_dot \
+        || die "$NAME failed on ${WIDTH}x${HEIGHT} resize"
+}
+
+picture_resize_preview() {
+    local DEST=$1   # The file
+    local NAME=$2   # The pretty name for the sticker
+    convert "$DEST" -resize "128x128" "$DEST" 1>&2 && progress_dot || die "$NAME failed at 128x128 resize"
+}
+
+create_sticker_json() {
+    local PACK_NAME=$1  # Pack name
+    local NAME=$2       # Pretty name for the sticker
+    local WIDTH=$3      # The WIDTH!
+    local HEIGHT=$4     # The HEIGHT!
+    local TYPE=$5       # The type of the picture (png/gif)
+    local MXC=$6        # The MXC URL
+
+    echo -n "{\"body\":\"$NAME\",\"info\":{\"mimetype\":\"image/$TYPE\",\"h\":$HEIGHT," \
+            "\"w\":$WIDTH,\"thumbnail_url\":\"$MXC\"},\"msgtype\":\"m.sticker\",\"url\":\"$MXC\"" \
+            ",\"id\":\"$PACK_NAME-$NAME\"}"
+}
+
+mxc_to_https() {
+    # The transformation is the following
+    # `mxc://<serv>/<id>` => `https://<serv>/_matrix/media/r0/download/<serv>/<id>`
+    # It seems that every requests should be made to matrix.org...
+    # `mxc://<serv>/<id>` => `https://matrix.org/_matrix/media/r0/download/<serv>/<id>`
+    local SERV=`echo "$1" | awk -F/ '{print $3}'`
+    local ID=`echo "$1" | awk -F/ '{print $4}'`
+    echo "https://matrix.org/_matrix/media/r0/download/$SERV/$ID"
 }
 
 ################################
@@ -169,7 +251,7 @@ __install() {
                 shift 2
                 ;;
             *)
-                PARSE_FLAGS=0
+                local PARSE_FLAGS=0
                 ;;
         esac
     done
@@ -177,6 +259,7 @@ __install() {
     # Create the ~/config/stpkg.sh
     [ ! -d ~/config ] && mkdir ~/config
 cat > $STPKG_CONF_FILE << EOF
+# Please, only modify the 'STPKG_TOKEN'
 if [ ! "x\$INSTALL" = "xyes" ]; then
 STPKG_BASE="$BASE_DIR"
 STPKG_HOMESERV='matrix.org'
@@ -192,17 +275,23 @@ EOF
         info "Detected a sshfs install"
         [ "x$MNT" = "x" ] && die "You must specify a mount point with '-local /mount/pount' when using the '-sshfs' option"
         local STPKG_INSTALL=$1
-        STPKG_INSTALL=$MNT${STPKG_INSTALL:="/html/stickerpicker/"}
+        local STPKG_INSTALL=$MNT${STPKG_INSTALL:="/html/stickerpicker/"}
 
         # The sshfs hook
 cat >> $STPKG_CONF_FILE << EOF
 STPKG_SSHFS='yes'
 STPKG_INSTALL="$STPKG_INSTALL"
+SSHFS_USER="$SSHFS"
+SSHFS_MNT="`echo "$MNT" | sed "s+$HOME+~+g"`"
 mountpoint $MNT >/dev/null 2>&1
-if [ \$? -ne 0 -a ! "x\$INSTALL" = "xyes" ]; then
-[ ! -d "\$STPKG_INSTALL" ] && { sshfs $SSHFS: $MNT || die "Failed to mount $SSHFS:~/ to $MNT"; }
-[ ! -d "\$STPKG_INSTALL" ] && die 'Failed to mount $SSHFS:~/ to $MNT, sshfs problems?'
-fi
+[ \$? -ne 0 -a ! "x\$INSTALL" = "xyes" ] && {
+    [ ! -d "\$STPKG_INSTALL" ] && {
+        sshfs $SSHFS: $MNT \
+            || die "Failed to mount $SSHFS:~/ to $MNT";
+    }
+    [ ! -d "\$STPKG_INSTALL" ] \
+        && die 'Failed to mount $SSHFS:~/ to $MNT, sshfs problems?'
+}
 EOF
 
         # Do the sshfs hook
@@ -213,7 +302,7 @@ EOF
         sshfs $SSHFS: $MNT || die "Failed to mount $SSHFS:~/ to $MNT"
     else
         local STPKG_INSTALL=$1
-        STPKG_INSTALL=${STPKG_INSTALL:="~/html/stickerpicker/"}
+        local STPKG_INSTALL=${STPKG_INSTALL:="~/html/stickerpicker/"}
         echo "STPKG_INSTALL=$STPKG_INSTALL" >> $STPKG_CONF_FILE
     fi
 
@@ -239,7 +328,7 @@ if [ "x$1" = "x-install" ]; then
     [ "x$STPKG_NO_MSG" = "xyes" ] \
         && echo "!!! STPKG_NO_MSG is turn on, you won't see what's going on during the install"
     shift
-    REPO_DIR="$(dirname SELF)"
+    local REPO_DIR="$(dirname SELF)"
     [ ! "$REPO_DIR" = "$BASE_DIR" ] && die "You must run this script from the root of the sticker repo"
     __install $*
     exit 0
@@ -256,15 +345,80 @@ if [ ! -d "$STPKG_INSTALL" ]; then
 fi
 info "Use STPKG_INSTALL: $STPKG_INSTALL`[ "x$STPKG_SSHFS" = "xyes" ] && echo ' (this is an sshfs install)'`"
 
-if [ "x$STPKG_BASE" = "x" ]; then
-    die "The STPKG_BASE env var is mendatory, it must point to the sticker repo." \
-        "It should have been given by the install script"
-fi
+[ "x$STPKG_BASE" = "x" ] && die \
+    "The STPKG_BASE env var is mendatory, it must point to the sticker repo. It should have been given by the install script"
 
 #########################
 # Cmd handler functions #
 #########################
 
+__show() {
+    local COLOR_STCOLOR=`[ "x$STPKG_COLORS" = "xyes" ] && echo '__green' || echo '__yellow'`
+    local COLOR_STNOMSG=`[ "x$STPKG_NO_MSG" = "xyes" ] && echo '__green' || echo '__yellow'`
+    local COMMITS=`git -C $STPKG_BASE rev-list --count HEAD 2>/dev/null`
+    local REVISION=`git -C $STPKG_BASE rev-list --count master 2>/dev/null`
+    local REVISION=`expr $COMMITS - $REVISION`
+    local BRANCH=`git -C $STPKG_BASE branch 2>&1 | grep --color=auto "\*" | sed -e "s/* //" -e "s/$/ /"`
+
+    local SAFE=0
+    local UNSAFE=0
+    local UNSAFE_CMD=""
+    for CMD in $REQUIREMENTS; do
+        [[ "`which $CMD`" =~ ^(/usr/bin|/bin|/sbin|/usr/sbin) ]] \
+            && local SAFE=`expr $SAFE + 1` \
+            || {
+                local UNSAFE=`expr $UNSAFE + 1`
+                local UNSAFE_CMD="$CMD $UNSAFE_CMD"
+            }
+    done
+    [ $UNSAFE -gt 0 ] && local UNSAFE=`__yellow $UNSAFE` || local UNSAFE=`__green $UNSAFE`
+
+    if [ "x$STPKG_TOKEN" = "x" ]; then
+        local TOKEN=`__yellow 'absent' `
+    else
+        local TOKEN=`validate_token_internal`
+        case "$TOKEN" in
+            M_UNKNOWN_TOKEN)    local TOKEN=`__red '[invalid token]'`;;
+            M_UNKNOWN)          local TOKEN=`__green '[valid]'`;;
+            *)                  local TOKEN=`__yellow '[unimplemented]'`;;
+        esac
+        local TOKEN="$TOKEN `__red "Sensitive data, I won't show it!"`"
+    fi
+
+    ## SSHFS stuff
+    if [ "x$STPKG_SSHFS" = "xyes" ]; then
+cat << EOF
+`__bold stpkg with sshfs install:`
+    sshfs             `[ -d $STPKG_INSTALL ] && __green 'mounted' || { __yellow 'umounted'; echo " (should not be the case at this point)"; }`
+    user              $SSHFS_USER
+    mountpoint        $SSHFS_MNT
+EOF
+    fi
+
+    ## Version stuff
+cat << EOF
+`__bold stpkg version:`
+    branch            $BRANCH
+    commits           $COMMITS
+    revision          $REVISION
+`__bold stpkg options and variables:`
+    `__green STPKG_INSTALL`     `__italic $STPKG_INSTALL`
+    `__green STPKG_BASE`        `__italic $STPKG_BASE`
+    `__green STPKG_COLORS`      `__italic $($COLOR_STCOLOR $STPKG_COLORS)`
+    `__green STPKG_NO_MSG`      `__italic $($COLOR_STNOMSG $STPKG_NO_MSG)`
+    `__green STPKG_HOMESERV`    `__italic $STPKG_HOMESERV`
+    `__green STPKG_TOKEN`       $TOKEN
+`__bold required commands due to the '"require"' function:`
+    safe (system)     `__green $SAFE`
+    unsafe (user)     $UNSAFE
+EOF
+    [ ! -z "$UNSAFE_CMD" ] && {
+        echo -ne '    '`__yellow unsafe commands`'   '
+        for CMD in $UNSAFE_CMD; do echo -n "$CMD "; done
+        echo ''
+    }
+}
+
 __update() {
     info "Updating packs..."
 
@@ -282,12 +436,71 @@ __update() {
     cp $STPKG_BASE/packs/*/*.json $STPKG_INSTALL/web/packs/ || die "Failed to copy packs Json files"
 
     local NEW_MD5=`md5sum $(readlink -f "$STPKG_BASE/stpkg")`
-    [ ! "$NEW_MD5" = "$MD5" ] && { cp "$STPKG_BASE/stpkg" $SELF && { info "Update 'stpkg'"; exit 0; } || die "Failed to copy new stpkg script to "; }
+    if [ ! "$NEW_MD5" = "$MD5" ]; then
+        info "... creating update script"
+        local UPDATE=`mktemp --suffix=.sh`
+cat > $UPDATE << EOF
+`declare -f __yellow`
+`declare -f __green`
+`declare -f __red`
+`declare -f die`
+__yellow "... Update stpkg ... "
+cp "$STPKG_BASE/stpkg" "$SELF" && __green "success!" || __red "failed!"
+rm "$UPDATE" || die "Failed to delete the update script"
+echo ""
+EOF
+        exec bash "$UPDATE" \
+            || die "Failed to run the update script." \
+                   "You will need to copy manually '$STPKG_BASE/stpkg' to '$SELF' manually."
+    fi
 
     info "Update finished!"
     exit 0
 }
 
+__display() {
+    if [ "x$1" = "x-dl" ]; then
+        local DL_SWITCH="yes"
+        local DL_FOLDER="$2"
+        if [ ! -d "$DL_FOLDER" ]; then
+            info "Need to create folder '$DL_FOLDER'";
+            mkdir "$DL_FOLDER" || die "Failed to create folder '$DL_FOLDER'";
+        else
+            warn "Folder '$DL_FOLDER' already exists"
+        fi
+        info "Will use the '$DL_FOLDER' to dl found stickers"
+        shift 2
+    fi
+
+    local FILE="${STPKG_INSTALL}web/packs/$1.json"
+    [ ! -r "$FILE" ] && die "Pack '$1' is not available (check with 'pack list'). The corresponfig file should be '$FILE'"
+    echo "Display the sticker pack $(__green `jq '.title' < "$FILE"`):"
+
+    local FIRST="yes"
+    jq '.stickers[] | "\(.body) \(.info.thumbnail_url) \(.info.mimetype)"' < "$FILE" | while IFS= read LINE; do
+        local NAME=`echo "$LINE" | awk -F '"| ' '{print $2}'`
+        local URL=` echo "$LINE" | awk -F '"| ' '{print $3}'`
+        local TYPE=`echo "$LINE" | awk -F '"| ' '{print $4}' | awk -F '/' '{print $2}'`
+        [ ! "x$2" = "x" ] && { [[ "$NAME" =~ $2 ]] || continue; }
+        local URL=`mxc_to_https "$URL"`
+
+        # Header if first
+        if [ "x$FIRST" = "xyes" ]; then
+            local FIRST="no"
+            echo "Name Download_URL Type"
+        fi
+
+        echo -ne "$NAME $URL $TYPE"
+        if [ "x$DL_SWITCH" = "xyes" ]; then
+            curl "$URL" --create-dirs --output "$DL_FOLDER/$NAME.$TYPE" >/dev/null 2>&1 \
+                && echo " `__green DL`" \
+                || echo " `__red Failed`"
+        else
+            echo ""
+        fi
+    done | column -t
+}
+
 __list() {
     # Handle -e and -p flags
     local PARSE_FLAGS=1
@@ -310,7 +523,7 @@ __list() {
                 shift
                 ;;
             *)
-                PARSE_FLAGS=0
+                local PARSE_FLAGS=0
                 ;;
         esac
     done
@@ -321,7 +534,7 @@ __list() {
         && die "The -e and -ne flags are incompatible"
 
     # Get the regex
-    REG="$*"
+    local REG="$*"
 
     # A sticker pack can be:
     # - enabled and present in the picker folder
@@ -340,17 +553,69 @@ __list() {
         local PRESENT=`find $STPKG_BASE/packs/ -type f -name "$LINE.json"`
         [ "x$FILTER_PRESENT"     = "xyes" -a   "x$PRESENT" = "x" ] && continue
         [ "x$FILTER_NOT_PRESENT" = "xyes" -a ! "x$PRESENT" = "x" ] && continue
-        PRESENT=`[ ! "x$PRESENT" = "x" ] && echo 'p' || echo 'a'`
+        local PRESENT=`[ ! "x$PRESENT" = "x" ] && echo 'p' || echo 'a'`
 
         local ENABLED=`jq -r ".packs | index(\"$LINE.json\") | ." < $STPKG_INSTALL/web/packs/index.json`
         [ "x$FILTER_ENABLED"  = "xyes" -a   "x$ENABLED" = "xnull" ] && continue
         [ "x$FILTER_DISABLED" = "xyes" -a ! "x$ENABLED" = "xnull" ] && continue
-        ENABLED=`[ "x$ENABLED" = "xnull" ] && echo 'd' || echo 'e'`
+        local ENABLED=`[ "x$ENABLED" = "xnull" ] && echo 'd' || echo 'e'`
 
         echo -ne "$PRESENT$ENABLED $LINE\n"
     done
 }
 
+__edit() {
+    # <pack name> <add|del> <sticker> [image file to use]
+    local PACK_NAME="$1"
+    local ACTION="$2"
+    local STICKER_NAME="$3"
+    [ -z "$PACK_NAME" -o -z "$ACTION" -o -z "$STICKER_NAME" ] && die "Command argument are invalid, check the usage"
+    shift 3
+
+    local FILE="${STPKG_INSTALL}web/packs/$PACK_NAME.json"
+    [ ! -r "$FILE" ] && die "Can't read file '$FILE' associated to the '$PACK_NAME' pack"
+
+    local TEMP=`mktemp --suffix=.stpkg`
+    cp $FILE $TEMP
+
+    case "$ACTION" in
+        add)
+            [ $# -eq 0 ] && die "You must specify an image file for the add action"
+            local FILE="$1"
+            [ ! -r "$FILE" ] && die "Failed to find file '$FILE'"
+
+            validate_homeserv   # Check if homeserv exists (see __pack)
+            validate_token      # Validate token, will exit if invalid (see __pack)
+
+            # Get sizes (see __pack)
+            local WIDTH=$(file_get_width "$FILE")
+            local HEIGHT=$(file_get_height "$FILE")
+            local TYPE=$(file_get_type "$FILE")
+            local NAME=$(file_get_name "$FILE")
+            local DEST=$(mktemp --suffix=".$TYPE")
+
+            picture_process_sticker "$FILE" "$DEST" "$NAME" "$WIDTH" "$HEIGHT" "$TYPE"  # Transform sticker picture (see __pack)
+            upload_file "$TYPE" "$DEST" "$NAME"                                         # Upload transformed file (see __pack)
+
+            jq "del(.stickers[] | select(.body == \"$STICKER_NAME\"))" < "$TEMP" | sponge "$TEMP"
+            local ST_JSON=$(create_sticker_json "$PACK_NAME" "$NAME" "$WIDTH" "$HEIGHT" "$TYPE" "$MXC")
+            jq ".stickers += [$ST_JSON]" < $TEMP | sponge $TEMP
+            ;;
+        del)
+            [ $# -ne 0 ] && die "Extra argument are present: $*"
+            jq "del(.stickers[] | select(.body == \"$STICKER_NAME\"))" < "$TEMP" | sponge "$TEMP"
+            ;;
+        *)
+            die "Unknown action '$ACTION', should be 'add' or 'del'"
+            ;;
+    esac
+
+    # TODO [OPTIONAL] Update the preview
+
+    jq < $TEMP
+    #cp $TEMP $FILE
+}
+
 __add() {
     [ "x$1" = "x" ] && die "You must specify a pack for the 'add' command"
     info "Enable pack '$1'"
@@ -368,7 +633,6 @@ __add() {
 __del() {
     [ "x$1" = "x" ] && die "You must specify a pack 'del' command"
     info "Disable pack '$1'"
-    local INDEX=0
     local TEMP=`mktemp --suffix=.stpkg`
     cp $STPKG_INSTALL/web/packs/index.json $TEMP
     jq "{ \"homeserver_url\": .homeserver_url, \"packs\": .packs | map(select(. != \"$1.json\")) }" \
@@ -381,14 +645,11 @@ __default() {
     default_index > $STPKG_INSTALL/web/packs/index.json || die "Failed to create default index.json file"
 }
 
-
 progress()       { echo 1>&2 -n "$*";       }
 progress_dot()   { progress '.';            }
 progress_reset() { echo 1>&2 -en "\r"; }
 __pack() {
-    # Check if homeserv exists
-    curl "https://$STPKG_HOMESERV" >/dev/null 2>&1
-    [ $? -ne 0 ] && die "Homeserv '$STPKG_HOMESERV' doesn't exist or is inaxessible"
+    validate_homeserv # Check if homeserv exists
 
     # Get the token
     if [ "x$1" = "x-t" ]; then
@@ -400,12 +661,7 @@ __pack() {
         echo ''
     fi
 
-    # Check token
-    local RES=`curl -s -X POST "https://$STPKG_HOMESERV/_matrix/media/r0/upload?access_token=$STPKG_TOKEN" \
-        | python3 -c "import sys, json; print(json.load(sys.stdin)['errcode'])"` # TODO: Use jq here
-    [ "x$RES" = "xM_UNKNOWN_TOKEN" ] && die "The token is incorrect or doesn't exist on '$STPKG_HOMESERV'"
-    [ ! "x$RES" = "xM_UNKNOWN" ]     && die "Got an 'yet implemented' error"
-    info "Token is valid on homeserv '$STPKG_HOMESERV'"
+    validate_token # Validate token, will exit if invalid
 
     # The pack source folder and the pack name
     if [ $# -eq 1 ]; then
@@ -419,7 +675,7 @@ __pack() {
     else
         die "Invalid number of arguments for the 'pack' command"
     fi fi
-    PACK_NAME=`slugify $PACK_NAME`
+    local PACK_NAME=`slugify $PACK_NAME`
     info "Will pack the folder '$PACK_FOLDER' into '$PACK_NAME'"
     [ ! -d "$PACK_FOLDER" ] && die "Source folder '$PACK_FOLDER' doesn't exsit"
 
@@ -446,62 +702,41 @@ __pack() {
         # if the stderr of stpkg is redirected, progress messages will be lost.
 
         # Get sizes
-        local WIDTH=$( identify -format "%w" "$FILE") >/dev/null
-        local HEIGHT=$(identify -format "%h" "$FILE") >/dev/null
-        WIDTH=$((  $WIDTH  > 256 ? 256 : $WIDTH  ))
-        HEIGHT=$(( $HEIGHT > 256 ? 256 : $HEIGHT ))
-
-        # Get the type
-        if [[ "$FILE" =~ .*\.gif ]]; then
-            local TYPE="gif"
-            local OPTS=""
-        else
-            local TYPE="png"
-            local OPTS="-type TrueColor PNG32:"
-        fi
+        local WIDTH=$(file_get_width "$FILE")
+        local HEIGHT=$(file_get_height "$FILE")
 
-        local NAME=`echo "$FILE" | cut -f1 -d'.'`
+        # Get the names and extentions
+        local TYPE=$(file_get_type "$FILE")
+        local NAME=$(file_get_name "$FILE")
         local DEST="$DEST_FOLDER/$NAME.$TYPE"
 
         # For the progress
         progress "($CURRENT_FILE/$TOTAL_FILES) $NAME "
-        CURRENT_FILE=$[ $CURRENT_FILE + 1 ]
+        local CURRENT_FILE=$[ $CURRENT_FILE + 1 ]
 
         # Transform sticker source picture
-        convert "$FILE" -bordercolor none -border 1 "$DEST" 1>&2 \
-            && progress_dot || die "$NAME failed on border"
-        convert "$DEST" -trim +repage "$DEST" 1>&2 \
-            && progress_dot || die "$NAME failed on trim"
-        convert -background none -gravity center "$DEST" -resize "${WIDTH}x${HEIGHT}" $OPTS"$DEST" 1>&2 \
-            && progress_dot || die "$NAME failed on ${WIDTH}x${HEIGHT} resize"
+        picture_process_sticker "$FILE" "$DEST" "$NAME" "$WIDTH" "$HEIGHT" "$TYPE"
 
         # Add a ',' only if it's not the first in the array
         echo -n "$FIRST_IN_ARRAY" >> $DEST_INDEX
 
-        # Upload
-        # TODO: Use jq here
-        local MXC=`curl -s -X POST -H "Content-Type: image/$TYPE" --data-binary "@$DEST" \
-                    "https://$STPKG_HOMESERV/_matrix/media/r0/upload?access_token=$STPKG_TOKEN" | \
-                    python -c "import sys, json; print(json.load(sys.stdin)['content_uri'])" \
-                    || die "Failed to upload sticker $NAME for pack $PACK_NAME to $STPKG_HOMESERV"`
+        # Upload the transformed file
+        upload_file "$TYPE" "$DEST" "$NAME"
         progress_dot
 
         # Calculate the 128x128 format
         local INIT_WIDTH=$WIDTH
         local INIT_HEIGHT=$HEIGHT
-        convert "$DEST" -resize "128x128" "$DEST" 1>&2 \
-            && progress_dot || die "$NAME failed at 128x128 resize"
-        WIDTH=$( identify -format "%w" "$DEST") >/dev/null
-        HEIGHT=$(identify -format "%h" "$DEST") >/dev/null
+        picture_resize_preview "$DEST" "$NAME"
+        local WIDTH=$( identify -format "%w" "$DEST") >/dev/null
+        local HEIGHT=$(identify -format "%h" "$DEST") >/dev/null
 
         # Add the sticker to the index file
-        echo -n "{\"body\":\"$NAME\",\"info\":{\"mimetype\":\"image/$TYPE\",\"h\":$HEIGHT," \
-                "\"w\":$WIDTH,\"thumbnail_url\":\"$MXC\"},\"msgtype\":\"m.sticker\",\"url\":\"$MXC\"" \
-                ",\"id\":\"$PACK_NAME-$NAME\"}" >> $DEST_INDEX
+        create_sticker_json "$PACK_NAME" "$NAME" "$WIDTH" "$HEIGHT" "$TYPE" "$MXC" >> $DEST_INDEX
 
         # For the report
         [ "x$FIRST_IN_ARRAY" = "x" ] && echo -e "StickerName MXC Type Width Height"
-        FIRST_IN_ARRAY=","
+        local FIRST_IN_ARRAY=","
         echo -e "$NAME ($MXC) $TYPE $INIT_WIDTH $INIT_HEIGHT"
 
         progress_reset
@@ -522,11 +757,14 @@ __pack() {
 
 [ "x$1" = "x" ] && usage
 case "$1" in
-    update)         __update    ;;
-    list)   shift;  __list $*   ;;
-    add)    shift;  __add $*    ;;
-    del)    shift;  __del $*    ;;
-    default)        __default   ;;
-    pack)   shift;  __pack $*   ;;
-    *)              usage       ;;
+    show)               __show      ;;
+    update)             __update    ;;
+    list)       shift;  __list $*   ;;
+    add)        shift;  __add $*    ;;
+    del)        shift;  __del $*    ;;
+    default)            __default   ;;
+    pack)       shift;  __pack $*   ;;
+    display)    shift;  __display $*;;
+    edit)       shift;  __edit $*   ;;
+    *)                  usage       ;;
 esac