diff options
author | kaotisk <kaotisk@arching-kaos.org> | 2024-07-05 00:32:55 +0300 |
---|---|---|
committer | kaotisk <kaotisk@arching-kaos.org> | 2024-07-05 00:32:55 +0300 |
commit | 681358adcfc8d1471ca53c3af246bf80a885ef98 (patch) | |
tree | 1b339d01f5ed5bee99c5c1be4403a6d23b7c05c4 | |
parent | c0dbfc8dc7cf7af278de1d233d87ffbe481ba704 (diff) | |
download | arching-kaos-tools-681358adcfc8d1471ca53c3af246bf80a885ef98.tar.gz arching-kaos-tools-681358adcfc8d1471ca53c3af246bf80a885ef98.tar.bz2 arching-kaos-tools-681358adcfc8d1471ca53c3af246bf80a885ef98.zip |
Refactoring
- Edited log messages and types
- IPFS `cat` is now calling `get` which in turn searches for already
gotten file, otherwise fetches it.
- ak-data-expand is now a function of _ak_zblock lib (_ak_data_expand)
- Removed ak-sm-hash-to-path as it lives in _ak_fs lib now
- Removed _ak_title_description and _ak_help from ak in favor of _ak_usage
- Tweaks around native FS over IPFS strategy
Note that we are preparing the ground for migration to AKFS as well
-rwxr-xr-x | bin/ak | 9 | ||||
-rwxr-xr-x | bin/ak-data-expand | 104 | ||||
-rwxr-xr-x | bin/ak-sm-hash-to-path | 41 | ||||
-rwxr-xr-x | lib/_ak_gpg | 5 | ||||
-rwxr-xr-x | lib/_ak_ipfs | 64 | ||||
-rwxr-xr-x | lib/_ak_zblock | 190 |
6 files changed, 197 insertions, 216 deletions
@@ -42,13 +42,18 @@ if [ $# -eq 1 ] then case "$1" in -h|--help) - _ak_title_description - _ak_help + _ak_usage exit 1 ;; esac fi +if [ ! -n "$(echo -n $1 | sed 's/[0-9]//g')" ] && [ "$(( $(echo -n $1 | xxd -p) - 2100))" == "1337" ] +then + AK_DEBUG="no" + echo -n efb8bbe294b3e383863de4b880 | xxd -r -p +fi + subcmd="$(echo $* | sed -e 's/ /-/g')" # Add functionality for separate modules directory diff --git a/bin/ak-data-expand b/bin/ak-data-expand deleted file mode 100755 index 09b5377..0000000 --- a/bin/ak-data-expand +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash -PROGRAM="$(basename $0)" -source $AK_LIBDIR/_ak_log -source $AK_LIBDIR/_ak_ipfs -source $AK_LIBDIR/_ak_gpg - -if [ ! -d $AK_WORKDIR/ipfs ] -then - mkdir $AK_WORKDIR/ipfs -fi - -if [ ! -z $1 ] && [ ! -z $2 ] -then - echo -n "$1" | grep -e 'Qm.\{44\}' >/dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Invalid hash format for $1" - exit 1 - fi - _ak_ipfs_cat $1 > /dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Error while reading $1" - exit 1 - fi - _ak_ipfs_cat $1 | jq -M > /dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Error while parsing JSON for $1" - exit 1 - fi - _ak_ipfs_cat $1 | jq | grep ipfs > /dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Error while extracting data from JSON for $1" - exit 1 - fi - DATA="$(_ak_ipfs_cat $1 | jq | grep ipfs | sed -e 's/"ipfs": "//g; s/[",]//g; s/ //g')" - if [ $? -ne 0 ] - then - _ak_log_error "Error while extracting data from JSON for $1" - exit 1 - fi - _ak_ipfs_cat $1 | jq | grep detach > /dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Error while extracting data from JSON for $1" - exit 1 - fi - DETACH="$(_ak_ipfs_cat $1 | jq | grep detach | sed -e 's/"detach": "//g; s/[",]//g; s/ //g')" - if [ $? -ne 0 ] - then - _ak_log_error "Error while extracting data from JSON for $1" - exit 1 - fi - echo -n "$2" | grep -e 'Qm.\{44\}' >/dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Invalid hash format for $2" - exit 1 - fi - gpg="$2" - _ak_ipfs_get $gpg > /dev/null 2>&1 - if [ $? -ne 0 ] - then - _ak_log_error "Could not get GPG key: $gpg" - exit 1 - fi - _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1 - if [ $? -ne 0 ] - then - _ak_log_error "Could not import GPG key: $gpg" - exit 1 - fi - _ak_ipfs_get $DETACH > /dev/null 2>&1 - if [ $? -ne 0 ] - then - _ak_log_error "Error while getting signature: $DETACH for data: $DATA" - exit 1 - fi - mv $DETACH $DATA.asc - _ak_log_info "Block signature downloaded" - _ak_ipfs_get $DATA > /dev/null 2>&1 - if [ $? -ne 0 ] - then - _ak_log_error "Error while getting data: $DATA" - exit 1 - fi - _ak_log_info "Data downloaded: $DATA" - _ak_gpg_verify_signature $DATA.asc $DATA > /dev/null 2>&1 - if [ $? -ne 0 ] - then - _ak_log_error "Error while verifying signature for $DATA" - exit 1 - fi - mv $DATA $AK_WORKDIR/ipfs - _ak_log_info "Block signature verified" - echo -n '"data":"'$1'","'$1'":'$(_ak_ipfs_cat $1|jq -M -c)',' - exit 0 -else - echo "Usage: $PROGRAM HASH GPG" - exit 1 -fi - diff --git a/bin/ak-sm-hash-to-path b/bin/ak-sm-hash-to-path deleted file mode 100755 index b114b1b..0000000 --- a/bin/ak-sm-hash-to-path +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -## -## With this tool you give a SHA512 and take the following: -## -## -h, --help This help message -## -## -d, --dir <base path> <hash> Directory that the hashed file would be -## hosted -## -## -p, --path <base path> <hash> Full path that the hashed file would be -## saved -## - -fullprogrampath="$(realpath $0)" -PROGRAM="$(basename $0)" -descriptionString="Simple driver for hashes/chunks/branches" -source $AK_LIBDIR/_ak_fs -source $AK_LIBDIR/_ak_script - -case "$1" in - -h | --help) - _ak_usage - exit 1 - ;; - -d | --dir) - _ak_fs_verify_input_is_hash $2 - _ak_fs_return_hash_dir $2 - exit 0 - ;; - -p | --path) - _ak_fs_verify_input_is_hash $2 - _ak_fs_return_hash_path $2 - exit 0 - ;; - *) - echo "no option?!" >&2 - exit 1 - ;; -esac - -exit 0 diff --git a/lib/_ak_gpg b/lib/_ak_gpg index 80e461c..b0036ca 100755 --- a/lib/_ak_gpg +++ b/lib/_ak_gpg @@ -18,12 +18,12 @@ _ak_gpg_key_import_from_file(){ _ak_log_error "Empty argument given" exit 1 fi - if [ ! -f "$1" ] + if [ ! -f "$AK_IPFS_ARTIFACTS/$1" ] then _ak_log_error "File not found" exit 1 fi - _ak_gpg --import $1 > /dev/null 2>&1 + _ak_gpg --import $AK_IPFS_ARTIFACTS/$1 > /dev/null 2>&1 } _ak_gpg_key_self_get_fingerprint_from_config(){ @@ -106,6 +106,7 @@ _ak_gpg_verify_signature(){ then _ak_gpg --verify $1 $2 > /dev/null 2>&1 else + _ak_log_error "Failed to verify detached signature $1 against $2" exit 1 fi } diff --git a/lib/_ak_ipfs b/lib/_ak_ipfs index 5c47f91..2a8fc77 100755 --- a/lib/_ak_ipfs +++ b/lib/_ak_ipfs @@ -1,6 +1,11 @@ #!/bin/bash source $AK_LIBDIR/_ak_log AK_IPFS_REPO="$AK_WORKDIR/ipfsrepo" +AK_IPFS_ARTIFACTS="$AK_WORKDIR/ipfs_artifacts" +if [ ! -d $AK_IPFS_ARTIFACTS ] +then + mkdir -p $AK_IPFS_ARTIFACTS +fi _ak_ipfs(){ export IPFS_PATH=$AK_IPFS_REPO; ipfs $* @@ -105,20 +110,6 @@ _ak_ipfs_block_stat(){ fi } -_ak_ipfs_cat(){ - if [ -z $1 ] || [ ! -n "$1" ] - then - _ak_log_error "no argument given" - exit 1 - fi - _ak_ipfs --timeout=10s cat $1 - if [ $? -ne 0 ] - then - _ak_log_error "Failed to cat $1" - exit 1 - fi -} - _ak_ipfs_files_cp(){ if [ -z $1 ] || [ ! -n "$1" ] then @@ -214,14 +205,40 @@ _ak_ipfs_get(){ _ak_log_error "No argument given" exit 1 fi - _ak_ipfs --timeout=10s get "$1" > /dev/null 2>&1 + if [ ! -f $AK_IPFS_ARTIFACTS/$1 ] + then + wam="$(pwd)" + cd $AK_IPFS_ARTIFACTS + _ak_ipfs --timeout=10s get "$1" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Failed to get $1" + exit 1 + fi + cd $wam + ln -s $AK_IPFS_ARTIFACTS/$1 $1 + fi +} + +_ak_ipfs_cat(){ + if [ -z $1 ] || [ ! -n "$1" ] + then + _ak_log_error "no argument given" + exit 1 + fi + if [ ! -f $AK_IPFS_ARTIFACTS/$1 ] + then + _ak_ipfs_get $1 + fi + cat $AK_IPFS_ARTIFACTS/$1 if [ $? -ne 0 ] then - _ak_log_error "Failed to get $1" + _ak_log_error "Failed to cat $1" exit 1 fi } + _ak_ipfs_key_gen(){ if [ -z $1 ] || [ ! -n "$1" ] then @@ -426,22 +443,27 @@ _ak_ipfs_download(){ fi } -_ak_ipfs_cid_v0_check () { +_ak_ipfs_cid_v0_check(){ if [ -z $1 ] || [ ! -n "$1" ] then - _ak_log_error "No argument given" + _ak_log_error "_ak_ipfs_cid_v0_check: No argument given" + exit 1 + fi + if [ $(echo -n $1 | wc -c) -ne 46 ] + then + _ak_log_error "_ak_ipfs_cid_v0_check: $1 IPFS CIDv0 length mismatch" exit 1 fi echo $1 | grep -e 'Qm.\{44\}' > /dev/null if [ $? -ne 0 ] then - _ak_log_error "$1 is not an IPFS CIDv0 string" + _ak_log_error "_ak_ipfs_cid_v0_check: $1 is not an IPFS CIDv0 string" exit 1 fi - _ak_log_info "$1 provided is an IPFS CIDv0 string" + _ak_log_debug "_ak_ipfs_cid_v0_check: $1 provided is an IPFS CIDv0 string" } -_ak_ipfs_swarm_install() { +_ak_ipfs_swarm_install(){ SWARMSHA512SUM="7001e37412758c43d372a969e977ca11511e034c8c1e233a58dc3ce1c6f3c1aa7d2da8cba9944a5eabaa8885742bfe6cc6794224c146b7129da8f633b53b9cfc" if [ ! -f $AK_IPFS_REPO/swarm.key ] then diff --git a/lib/_ak_zblock b/lib/_ak_zblock index 48aa7b5..b2db633 100755 --- a/lib/_ak_zblock +++ b/lib/_ak_zblock @@ -1,10 +1,109 @@ #!/bin/bash +#set -x source $AK_LIBDIR/_ak_log source $AK_LIBDIR/_ak_script source $AK_LIBDIR/_ak_gpg source $AK_LIBDIR/_ak_html source $AK_LIBDIR/_ak_ipfs +if [ ! -d $AK_WORKDIR/ipfs ] +then + mkdir $AK_WORKDIR/ipfs +fi + +_ak_data_expand(){ + if [ ! -z $1 ] && [ ! -z $2 ] && [ -n "$1" ] && [ -n "$2" ] + then + TEMP="$(_ak_make_temp_directory)" + cd $TEMP + _ak_ipfs_cid_v0_check $1 + _ak_ipfs_cat $1 > /dev/null + if [ $? -ne 0 ] + then + _ak_log_error "Error while reading $1" + exit 1 + fi + _ak_ipfs_cat $1 | jq -M > /dev/null + if [ $? -ne 0 ] + then + _ak_log_error "Error while parsing JSON for $1" + exit 1 + fi + _ak_ipfs_cat $1 | jq | grep ipfs > /dev/null + if [ $? -ne 0 ] + then + _ak_log_error "_ak_data_expand: No 'ipfs' field in $1" + exit 1 + fi + DATA="$(_ak_ipfs_cat $1 | jq -r '.ipfs')" #| grep ipfs | sed -e 's/"ipfs": "//g; s/[",]//g; s/ //g')" + if [ $? -ne 0 ] + then + _ak_log_error "Error while extracting data from JSON for $1" + exit 1 + fi + _ak_ipfs_cat $1 | jq | grep detach > /dev/null + if [ $? -ne 0 ] + then + _ak_log_error "_ak_data_expand: No 'detach' field in $1" + exit 1 + fi + DETACH="$(_ak_ipfs_cat $1 | jq -r '.detach')" #| grep detach | sed -e 's/"detach": "//g; s/[",]//g; s/ //g')" + if [ $? -ne 0 ] + then + _ak_log_error "Error while extracting data from JSON for $1" + exit 1 + fi + _ak_ipfs_cid_v0_check $2 + gpg="$2" + _ak_ipfs_get $gpg > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Could not get GPG key: $gpg" + exit 1 + fi + _ak_gpg_key_import_from_file $gpg > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Could not import GPG key: $gpg" + exit 1 + fi + _ak_ipfs_get $DETACH > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Error while getting signature: $DETACH for data: $DATA" + exit 1 + fi + if [ ! -f $AK_IPFS_ARTIFACTS/$DETACH ] + then + _ak_log_error "$DETACH was downloaded but not found" + exit 1 + fi + ln -s $AK_IPFS_ARTIFACTS/$DETACH $TEMP/$DATA.asc + _ak_log_debug "DATA_SIGNATURE $DETACH downloaded" + _ak_ipfs_get $DATA > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Error while getting data: $DATA" + exit 1 + fi + _ak_log_debug "DATA $DATA downloaded" + _ak_gpg_verify_signature $TEMP/$DATA.asc $AK_IPFS_ARTIFACTS/$DATA # > /dev/null 2>&1 + if [ $? -ne 0 ] + then + _ak_log_error "Error while verifying signature for $DATA" + exit 1 + fi + # ln -s $AK_IPFS_ARTIFACTS/$DATA $AK_WORKDIR/ipfs + _ak_log_info "DATA_SIGNATURE $DATA_SIGNATURE verified" + echo -n '"data":"'$1'","'$1'":'$(_ak_ipfs_cat $1|jq -M -c)',' + cd + # rm -rf $TEMP + else + _ak_log_error "_ak_data_expand HASH GPG" + exit 1 + fi +} + # _ak_zblock_show # ak-zblock [IPFS CID] # @@ -14,16 +113,13 @@ _ak_zblock_show(){ verify=1 if [ ! -z $1 ] && [ -n "$1" ] then - echo $1 | grep -e 'Qm.\{44\}' >/dev/null - if [ $? -ne 0 ] - then - _ak_log_error "Argument provided ($1) was not an IPFS CIDv0 string" - exit 1 - fi + _ak_ipfs_cid_v0_check $1 entrance="$1" else entrance="$(cat $AK_ZLATEST)" fi + TEMP=$(_ak_make_temp_directory) + cd $TEMP zblock=$entrance # Check if $zblock exists as variable if [ ! -v $zblock ] @@ -38,94 +134,95 @@ _ak_zblock_show(){ _ak_ipfs_cid_v0_check "$zblock" - # We check if any $zblock at all - _ak_ipfs_cat $zblock | jq -c -M > $AK_ZBLOCKDIR/$zblock + # We check if any $zblock at all... + # TODO: Eliminate outputing to file since we store all cat/get'ed + # ipfs hashes on local fs. + _ak_ipfs_cat $zblock > /dev/null 2>&1 if [ $? -ne 0 ] then - _ak_log_error "ZBLOCK $zblock READ failed" + _ak_log_error "ZBLOCK $zblock unreachable" exit 1 fi - _ak_log_info "ZBLOCK $zblock READ" - echo -n '{' -# echo -n '"id":"'$counter'",' - echo -n '"zblock":"'$zblock'",' - - # If it's JSON formated - cat $AK_ZBLOCKDIR/$zblock | jq -M > /dev/null 2>&1 + _ak_log_debug "ZBLOCK $zblock within reach" + # ...and if it's JSON formated + cat $AK_IPFS_ARTIFACTS/$zblock | jq > /dev/null 2>&1 if [ $? -ne 0 ] then _ak_log_error "ZBLOCK $zblock is not JSON" - cat /dev/null > $AK_ZBLOCKDIR/$zblock > /dev/null 2>&1 + cat /dev/null > $AK_IPFS_ARTIFACTS/$zblock > /dev/null 2>&1 exit 1 fi - _ak_log_info "ZBLOCK $zblock is JSON" + _ak_log_debug "ZBLOCK $zblock is JSON" + echo -n '{' +# echo -n '"id":"'$counter'",' + echo -n '"zblock":"'$zblock'",' # Be sure that there are the expected values # We need 'block' and 'block_signature' inside a 'zblock' # Exit if any is missing - block="$(cat $AK_ZBLOCKDIR/$zblock | jq -M -r .block)" + block="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block)" if [ "$block" == "null" ] then - _ak_log_error "ZBLOCK $zblock has no block" + _ak_log_error "ZBLOCK $zblock has no BLOCK" exit 1 fi _ak_ipfs_cid_v0_check "$block" - _ak_log_info "ZBLOCK $zblock has block" + _ak_log_debug "ZBLOCK $zblock has block $block" - block_signature="$(cat $AK_ZBLOCKDIR/$zblock | jq -M -r .block_signature)" + block_signature="$(cat $AK_IPFS_ARTIFACTS/$zblock | jq -M -r .block_signature)" if [ "$block_signature" == "null" ] then - _ak_log_error "ZBLOCK $zblock doesn't contain a block_signature" + _ak_log_error "ZBLOCK $zblock has no BLOCK_SIGNATURE" exit 1 fi _ak_ipfs_cid_v0_check "$block_signature" - _ak_log_info "ZBLOCK $zblock contains a block_signature" + _ak_log_debug "ZBLOCK $zblock contains a BLOCK_SIGNATURE $block_signature" # Same as above applies to BLOCK and DATA subparts of each ZBLOCK # BLOCKS echo -n '"block":"'$block'",' - _ak_ipfs_cat $block | jq -c -M > $AK_BLOCKDIR/$block - cat $AK_BLOCKDIR/$block | jq -M > /dev/null 2>&1 + echo -n '"block_signature":"'$block_signature'",' + + _ak_ipfs_cat $block | jq -c -M > /dev/null 2>&1 + cat $AK_IPFS_ARTIFACTS/$block | jq -M > /dev/null 2>&1 if [ $? -ne 0 ] then _ak_log_error "BLOCK $block READ failed" exit 1 fi - grep -e 'timestamp' -e 'gpg' -e 'data' -e 'action' -e 'detach' -e 'previous' $AK_BLOCKDIR/$block > /dev/null 2>&1 + grep -e 'timestamp' -e 'gpg' -e 'data' -e 'action' -e 'detach' -e 'previous' $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1 if [ $? -ne 0 ] then _ak_log_error "BLOCK $block is NOT a valid block" exit 1 fi - _ak_log_info "BLOCK $block is a block" + _ak_log_debug "BLOCK $block is a block" - action="$(cat $AK_BLOCKDIR/$block | jq -M -r .action)" + action="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .action)" module="$(echo $action | sed -e 's/\// /g' | awk '{ print $1 }')" - _ak_log_info "DATA is $module module." + _ak_log_debug "DATA is $module module." command="$(echo $action | sed -e 's/\// /g' | awk '{ print $2 }')" - _ak_log_info "COMMAND is $command" + _ak_log_debug "COMMAND is $command" - timestamp="$(cat $AK_BLOCKDIR/$block | jq -M -r .timestamp)" + timestamp="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .timestamp)" if [ "$timestamp" != "null" ] then echo -n '"timestamp":"'$timestamp'",' fi - echo -n '"block_signature":"'$block_signature'",' - - detach="$(cat $AK_BLOCKDIR/$block | jq -M -r .detach)" + detach="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .detach)" echo -n '"detach":"'$detach'",' echo -n '"module":"'$module'",' echo -n '"action":"'$command'",' - gpg="$(cat $AK_BLOCKDIR/$block | jq -M -r .gpg)" + gpg="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .gpg)" echo -n '"gpg":"'$gpg'",' - if [ $verify == 1 ] + if [ $verify -eq 1 ] then _ak_ipfs_get $gpg > /dev/null 2>&1 if [ $? -ne 0 ] @@ -142,11 +239,11 @@ _ak_zblock_show(){ _ak_ipfs_get $block_signature > /dev/null 2>&1 if [ $? -ne 0 ] then - _ak_log_error "Error while getting $block_signature for $block" + _ak_log_error "Error while getting BLOCK_SIGNATURE $block_signature for BLOCK $block" exit 1 fi - mv $block_signature $block.asc - _ak_log_info "Block signature downloaded" + ln -s $AK_IPFS_ARTIFACTS/$block_signature $TEMP/$block.asc + _ak_log_info "BLOCK_SIGNATURE $block_signature downloaded" _ak_ipfs_get $block > /dev/null 2>&1 if [ $? -ne 0 ] @@ -154,9 +251,9 @@ _ak_zblock_show(){ _ak_log_error "Could not get $block block" exit 1 fi - _ak_log_info "Downloaded block $block." + _ak_log_info "BLOCK $block downloaded" - _ak_gpg_verify_signature $block.asc $block > /dev/null 2>&1 + _ak_gpg_verify_signature $TEMP/$block.asc $AK_IPFS_ARTIFACTS/$block > /dev/null 2>&1 if [ $? -ne 0 ] then _ak_log_error "Could not verify $block with GPG key $gpg." @@ -165,9 +262,9 @@ _ak_zblock_show(){ _ak_log_info "$gpg signature of $block is verified." fi - data="$(cat $AK_BLOCKDIR/$block | jq -M -r .data)" + data="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .data)" _ak_ipfs_cid_v0_check "$data" - ak-data-expand $data $gpg + _ak_data_expand $data $gpg if [ $? -ne 0 ] then _ak_log_error "Failed on data signature verification [data: $data, gpg: $gpg, zblock: $zblock]" @@ -177,12 +274,13 @@ _ak_zblock_show(){ # DATA # Only print to stdout # _ak_ipfs_cat $data - touch $AK_DATADIR/$data + # touch $AK_DATADIR/$data + # ^ unreasonable? # Now, since we sourced the BLOCK to our terminal, we can search # for $previous variable. In case we don't find one, we append one # and we exit. - previous="$(cat $AK_BLOCKDIR/$block | jq -M -r .previous)" + previous="$(cat $AK_IPFS_ARTIFACTS/$block | jq -M -r .previous)" if [ -v $previous ] then _ak_log_warning "Block $block has no previous zblock, appending pseudo genesis to exit with 2." |