From ef1469762bb953487ce26d240519c2383e0d676c Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Sun, 31 Jan 2016 21:30:39 -0600 Subject: [PATCH 01/14] * Moved no editor warning to edit function * Added message in create_sns_root showing SNS's environment was actually initialized * Changed flag to create SNS's environment from -w to -i --- sns.sh | 22 ++++++++++++++-------- src/includes/create_sns_root.sns.sh | 12 +++++++++--- src/includes/edit.sns.sh | 5 ++++- src/main/stage1.sns.sh | 5 +---- src/main/stage2.sns.sh | 2 +- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/sns.sh b/sns.sh index 4bbfa8c..a2be9c9 100755 --- a/sns.sh +++ b/sns.sh @@ -15,10 +15,10 @@ readonly CONFIG_FILE="$ROOT_DIR/sns.conf" # Section: Functions -function w_conf { +function create_sns_root { -if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; fi -if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; fi +if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi +if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi cat > "$CONFIG_FILE" << EOF @@ -45,6 +45,12 @@ PUBKEY="" EOF chmod 600 "$CONFIG_FILE" + +if [ "$WILL_INIT" == "TRUE" ]; then + printf "%s %s\n" "Environment initialized in" "$ROOT_DIR" +else + printf "%s\n" "Environment already initialized." +fi } function pause { read -rp " Press [Enter] to continue." @@ -123,7 +129,10 @@ function delete(){ fi } function edit(){ -if [ ! -r "$NOTE" ]; then +if [ -z "$EDITOR" ]; then + >&2 echo "Error no editor specified in environment." + exit +elif [ ! -r "$NOTE" ]; then echo "ERROR: Note cannot be opened for editing." exit 40; fi @@ -207,10 +216,7 @@ fi echo "$PROD_STR, $VER_STR" -if [ -z "$EDITOR" ]; then - >&2 echo "Error no editor specified in environment." - -elif [ -n "$ERR_NO_GPG" ]; then +if [ -n "$ERR_NO_GPG" ]; then >&2 echo " Error: Encryption was specified, but GPG is not installed." exit 100 elif [ -n "$ERR_NO_KEY" ]; then diff --git a/src/includes/create_sns_root.sns.sh b/src/includes/create_sns_root.sns.sh index 81cfb01..d3b8bf9 100644 --- a/src/includes/create_sns_root.sns.sh +++ b/src/includes/create_sns_root.sns.sh @@ -1,7 +1,7 @@ -function w_conf { +function create_sns_root { -if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; fi -if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; fi +if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi +if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi cat > "$CONFIG_FILE" << EOF @@ -28,4 +28,10 @@ PUBKEY="" EOF chmod 600 "$CONFIG_FILE" + +if [ "$WILL_INIT" == "TRUE" ]; then + printf "%s %s\n" "Environment initialized in" "$ROOT_DIR" +else + printf "%s\n" "Environment already initialized." +fi } diff --git a/src/includes/edit.sns.sh b/src/includes/edit.sns.sh index e63c412..91f0e7f 100644 --- a/src/includes/edit.sns.sh +++ b/src/includes/edit.sns.sh @@ -1,5 +1,8 @@ function edit(){ -if [ ! -r "$NOTE" ]; then +if [ -z "$EDITOR" ]; then + >&2 echo "Error no editor specified in environment." + exit +elif [ ! -r "$NOTE" ]; then echo "ERROR: Note cannot be opened for editing." exit 40; fi diff --git a/src/main/stage1.sns.sh b/src/main/stage1.sns.sh index af57da1..d0eadd1 100644 --- a/src/main/stage1.sns.sh +++ b/src/main/stage1.sns.sh @@ -27,10 +27,7 @@ fi echo "$PROD_STR, $VER_STR" -if [ -z "$EDITOR" ]; then - >&2 echo "Error no editor specified in environment." - -elif [ -n "$ERR_NO_GPG" ]; then +if [ -n "$ERR_NO_GPG" ]; then >&2 echo " Error: Encryption was specified, but GPG is not installed." exit 100 elif [ -n "$ERR_NO_KEY" ]; then diff --git a/src/main/stage2.sns.sh b/src/main/stage2.sns.sh index 97c0392..b62b775 100644 --- a/src/main/stage2.sns.sh +++ b/src/main/stage2.sns.sh @@ -16,7 +16,7 @@ else elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-w" ] || [ "$ARG" == "--wconf" ]; then create_sns_root; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 else if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" From be3871f85946917062edd423cb8d2d531bbc840a Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Wed, 10 Feb 2016 23:33:43 -0600 Subject: [PATCH 02/14] Formatting changes --- src/includes/{create_sns_root.sns.sh => init_store.sns.sh} | 2 +- src/includes/verify_store.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) rename src/includes/{create_sns_root.sns.sh => init_store.sns.sh} (96%) create mode 100644 src/includes/verify_store.sh diff --git a/src/includes/create_sns_root.sns.sh b/src/includes/init_store.sns.sh similarity index 96% rename from src/includes/create_sns_root.sns.sh rename to src/includes/init_store.sns.sh index d3b8bf9..6883fff 100644 --- a/src/includes/create_sns_root.sns.sh +++ b/src/includes/init_store.sns.sh @@ -1,4 +1,4 @@ -function create_sns_root { +function init_store { if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi diff --git a/src/includes/verify_store.sh b/src/includes/verify_store.sh new file mode 100644 index 0000000..1e75289 --- /dev/null +++ b/src/includes/verify_store.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +# verify_store.sh +# sns +# +# Created by Jon-William Lewis on 1/31/16. +# From 856b14242c7b78121fa0637e0c82fcc5a58539f4 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Wed, 10 Feb 2016 23:34:49 -0600 Subject: [PATCH 03/14] Formatting changes --- .DS_Store | Bin 0 -> 6148 bytes build.sh | 15 +- errors.ref | 5 +- header.sh | 6 +- sns.sh | 223 ++++++++---------- sns.xcodeproj/project.pbxproj | 6 +- .../UserInterfaceState.xcuserstate | Bin 0 -> 11909 bytes src/includes/create.sns.sh | 39 +-- src/includes/delete.sns.sh | 20 +- src/includes/edit.sns.sh | 11 +- src/includes/verify_store.sh | 13 +- src/main/stage1.sns.sh | 70 +++--- src/main/stage2.sns.sh | 73 +++--- src/main/stage3.sns.sh | 68 +++--- 14 files changed, 267 insertions(+), 282 deletions(-) create mode 100644 .DS_Store create mode 100644 sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8f18d2b40318d37d87cebb5cd38ad169030026fc GIT binary patch literal 6148 zcmeHK!A=4(5Pemmh?;oxxJOSU{J~0A6AxbS2b5hE4Y&j)@nW){!AE&A9{d{d&9s4C z5fU#(%?z1&-FBwac}ZIez_rI&3)lltrwY~@G+&5}i!R7o=-DAUog+gN_voGU^K`-6 zI*b8h;I}a#d$*1*#<)QrrTyFO=UtA;!Ej7Hn5wV^G;oO#e>wG@JATCPE7|jX@T9D z?;}!HBI_D*WjSuESs;~6O4YB3>|eLe(tI$~4A?(hooA3INj84qN%`{n^sX^0<{sqP zH@t_v@=9Wvd^1$sTFQR8%5{2=kXE@+#>-y1XfuD50p8gn^=*%4jR9l87??32=R-sl zi~|-P_2{6{Cjha=ZWXrWFN4HH0poy$M~+aO4<-6g7oHf-hqFHlesRFUqYsA*j}I3z zyYNDBnw|4U>JArsG;0hP162mr{pX(C|3}N;|J5M-G6sx+f5m{SC1**SC55|np*Xo~ sBkDO-MEnYm8bTAUV{OP)yiZl(SR@T%9I)`n9*X@DP#Vk_13${Z2O~n95C8xG literal 0 HcmV?d00001 diff --git a/build.sh b/build.sh index aad3dcc..77dd483 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,9 @@ +#!/bin/bash +#========================================================== +# Simple Note System - Build Script +# Copyright 2016, Xenese Labs/Sicron-Perion XNF +#========================================================== + S=sns.sh bash header.sh > "$S" @@ -13,15 +19,6 @@ cat ./src/includes/edit.sns.sh >> "$S" cat ./src/includes/print.sns.sh >> "$S" cat ./src/includes/list.sns.sh >> "$S" printf "%s\n\n\n\n" "# End Section: Functions" >> "$S" - -printf "\n" >> "$S" -printf "%s\n" "###############################################################################" >> "$S" -printf "%s\n" "#==============================================================================" >> "$S" -printf "%s\n" "# Begin Main Program" >> "$S" -printf "%s\n" "#==============================================================================" >> "$S" -printf "%s\n" "###############################################################################" >> "$S" -printf "\n" >> "$S" - cat ./src/main/stage1.sns.sh >> "$S" cat ./src/main/stage2.sns.sh >> "$S" cat ./src/main/stage3.sns.sh >> "$S" diff --git a/errors.ref b/errors.ref index 508077d..620ffb6 100644 --- a/errors.ref +++ b/errors.ref @@ -9,4 +9,7 @@ ERR_INSUFFICIENT_ARGS 30 A required argument was not provided Encryption---------------------------------------------------------------------- ERR_NO_GPG 100 GPG is not installed -ERR_NO_KEY 110 No recipient specified \ No newline at end of file +ERR_NO_KEY 110 No recipient specified + +Create-------------------------------------------------------------------------- +ERR_NOTE_EXiSTS 200 The specified note already exists \ No newline at end of file diff --git a/header.sh b/header.sh index 6ba4564..cd39b16 100644 --- a/header.sh +++ b/header.sh @@ -1,13 +1,12 @@ -#!/bin/bash - PROD_STR="Simple Note System" VER_STR="v2.0a8" +YEAR=2016 cat << EOF #!/bin/bash #========================================================== # $PROD_STR, $VER_STR -# Copyright 2014, Xenese Labs/Sicron-Perion XNF +# Copyright $YEAR, Xenese Labs/Sicron-Perion XNF #========================================================== if [ -z "\$HOME" ]; then HOME=/home/"\$(whoami)"; fi @@ -19,4 +18,5 @@ readonly NOTES_DIR="\$ROOT_DIR"/notes readonly TMP_DIR="\$ROOT_DIR"/tmp readonly CONFIG_FILE="\$ROOT_DIR/sns.conf" + EOF diff --git a/sns.sh b/sns.sh index a2be9c9..8beb03f 100755 --- a/sns.sh +++ b/sns.sh @@ -1,7 +1,7 @@ #!/bin/bash #========================================================== # Simple Note System, v2.0a8 -# Copyright 2014, Xenese Labs/Sicron-Perion XNF +# Copyright 2016, Xenese Labs/Sicron-Perion XNF #========================================================== if [ -z "$HOME" ]; then HOME=/home/"$(whoami)"; fi @@ -14,6 +14,7 @@ readonly TMP_DIR="$ROOT_DIR"/tmp readonly CONFIG_FILE="$ROOT_DIR/sns.conf" + # Section: Functions function create_sns_root { @@ -112,7 +113,6 @@ function create(){ if [ -e "$NOTE" ]; then echo "Created note: $NOTEBOOK/$SECTION/$NAME." fi - } function delete(){ if [ "$DELETE" == "TRUE" ]; then @@ -180,131 +180,114 @@ function list(){ - -############################################################################### -#============================================================================== -# Begin Main Program -#============================================================================== -############################################################################### - -#============================================================================== -# Section: Configuration / Stage 1 -#============================================================================== -if [ -r "$CONFIG_FILE" ]; then - source "$CONFIG_FILE" -else - create_sns_root - source "$CONFIG_FILE" -fi - -if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$PUBKEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - fi - - command -v gpg >/dev/null 2>&1 ||\ - { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } -fi - -if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" - if [ ! -d "$ROOT_DIR"/tmp ]; then - mkdir -p "$ROOT_DIR"/tmp - fi -fi - -echo "$PROD_STR, $VER_STR" - -if [ -n "$ERR_NO_GPG" ]; then - >&2 echo " Error: Encryption was specified, but GPG is not installed." - exit 100 -elif [ -n "$ERR_NO_KEY" ]; then - >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " - exit 110 -fi - - -#============================================================================== -# End Section: Configuration / Stage 1 -#============================================================================== -#============================================================================== -# Section: Argument Parsing / Stage 2 -#============================================================================== - -NAME="" -NOTEBOOK="" -SECTION="" -if [ -z "$1" ]; then help; exit 20 -else - ARGS=( "$@" ) - for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" - elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-w" ] || [ "$ARG" == "--wconf" ]; then create_sns_root; exit 0 - else - if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" - elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" - elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" + #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # Entry Point + #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + #============================================================================== + # Stage 1: Read Configuration + #============================================================================== + if [ -r "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" + else + create_sns_root + source "$CONFIG_FILE" fi - fi - done - if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then - # If we got a note title above, but no notebook, and the list option - # was specified, we assume that the detected note title is actually a - # notebook name. - NOTEBOOK="$NAME" - NAME="" - fi -fi -# Note: w_conf and help have highest priority, as they are the only functions -# that can work without any arguments. + if [ "$ENCRYPTION" == "TRUE" ]; then + if [ -z "$PUBKEY" ]; then + ERR_NO_KEY="TRUE" + ENCRYPTION="FALSE" + fi -#============================================================================== -# End Section: Argument Parsing / Stage 2 -#============================================================================== -#============================================================================== -# Section: Actions / Stage 3 -#============================================================================== -# List only requires a notebook, and is exclusive. -if [ -z "$NOTEBOOK" ]; then - echo " ERROR: Insufficient arguments:" - echo " Notebook not specified" - exit 30 -fi + command -v gpg >/dev/null 2>&1 ||\ + { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } + fi -if [ -n "$LIST" ]; then - list - exit 0 -fi + if [ "$ENCRYPTION" == "TRUE" ]; then + PROD_STR="Simple Note System (Encryption Enabled)" + if [ ! -d "$ROOT_DIR"/tmp ]; then + mkdir -p "$ROOT_DIR"/tmp + fi + fi -#All other functions require a note title and notebook. + echo "$PROD_STR, $VER_STR" -if [ -z "$NAME" ]; then - echo " ERROR: Insufficient arguments:" - echo " Title not specified" - exit 30 -fi - -SESSION_ID="$RANDOM" -NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION"/ + if [ -n "$ERR_NO_GPG" ]; then + >&2 echo " Error: Encryption was specified, but GPG is not installed." + exit 100 + elif [ -n "$ERR_NO_KEY" ]; then + >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " + exit 110 + fi + #============================================================================== + # Stage 2: Argument Parsing + #============================================================================== + NAME="" + NOTEBOOK="" + SECTION="" + if [ -z "$1" ]; then help; exit 20 + else + ARGS=( "$@" ) + for ARG in "${ARGS[@]}"; do + if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" + elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" + elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" + elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" + elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" + elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" + elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 + else + if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" + elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" + elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" + fi + fi + done + if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then + # If a note title was specified, but no notebook, and the list option + # was specified, assume that the detected note title is actually the + # name of a notebook + NOTEBOOK="$NAME" + NAME="" + fi + fi + # w_conf and help are called here to avoid excess stage 3 code. + #============================================================================== + # Section: Actions / Stage 3 + #============================================================================== + # All options not requiring at least a notebook to be specified have been dealt + # with; if one isn't specified, throw code 30. + if [ -z "$NOTEBOOK" ]; then + printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + exit 30 + fi + # List is the only option requiring only a notebook. + # If list isn't the selected option and no note name was specified, throw code 30. + if [ "$LIST" == TRUE ]; then + list + exit 0 + elif [ -z "$NAME" ]; then + printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + exit 30 + fi + + NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" -if [ "$ENCRYPTION" == "TRUE" ]; then readonly NOTE="$NOTE_DIR""$NAME"."$EXT".gpg -else readonly NOTE="$NOTE_DIR""$NAME"."$EXT" -fi + if [ "$ENCRYPTION" == "TRUE" ]; then + SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename + readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" + else + readonly NOTE="$NOTE_DIR/$NAME.$EXT" + echo "$NOTE" + fi -if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi -if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi -if [ "$CREATE" == "TRUE" ]; then create; fi -if [ "$EDIT" == "TRUE" ]; then edit; fi + if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi + if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi + if [ "$CREATE" == "TRUE" ]; then create; fi + if [ "$EDIT" == "TRUE" ]; then edit; fi -#============================================================================== -# End Section: Actions / Stage 3 -#============================================================================== \ No newline at end of file + #============================================================================== + # End Section: Actions / Stage 3 + #============================================================================== diff --git a/sns.xcodeproj/project.pbxproj b/sns.xcodeproj/project.pbxproj index 5eb29b4..d55d3e0 100644 --- a/sns.xcodeproj/project.pbxproj +++ b/sns.xcodeproj/project.pbxproj @@ -15,11 +15,12 @@ 5D22D6A81AFC4F5A0036DC52 /* p_header.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = p_header.sh; sourceTree = ""; }; 5D22D6A91AFC4F5A0036DC52 /* pause.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = pause.sns.sh; sourceTree = ""; }; 5D22D6AA1AFC4F5A0036DC52 /* print.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = print.sns.sh; sourceTree = ""; }; - 5D22D6AB1AFC4F5A0036DC52 /* create_sns_root.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = create_sns_root.sns.sh; sourceTree = ""; }; + 5D22D6AB1AFC4F5A0036DC52 /* init_store.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = init_store.sns.sh; sourceTree = ""; }; 5D22D6AD1AFC4F5A0036DC52 /* stage1.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage1.sns.sh; sourceTree = ""; }; 5D22D6AE1AFC4F5A0036DC52 /* stage2.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage2.sns.sh; sourceTree = ""; }; 5D22D6AF1AFC4F5A0036DC52 /* stage3.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage3.sns.sh; sourceTree = ""; }; 5D22D6B01AFC5B100036DC52 /* libencryption.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = libencryption.sh; sourceTree = ""; }; + 5D75D24F1C5F13DF001E7B33 /* verify_store.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = verify_store.sh; sourceTree = ""; }; 5D7E611F1AB74D33001D49B9 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = ""; }; 5D7E91FB1B27FB620030B30D /* header.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = header.sh; sourceTree = ""; }; 5DE839831AB9DACE006CB4F6 /* sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sns.sh; sourceTree = ""; }; @@ -47,8 +48,9 @@ 5D22D6A81AFC4F5A0036DC52 /* p_header.sh */, 5D22D6A91AFC4F5A0036DC52 /* pause.sns.sh */, 5D22D6AA1AFC4F5A0036DC52 /* print.sns.sh */, - 5D22D6AB1AFC4F5A0036DC52 /* create_sns_root.sns.sh */, + 5D22D6AB1AFC4F5A0036DC52 /* init_store.sns.sh */, 5D22D6B01AFC5B100036DC52 /* libencryption.sh */, + 5D75D24F1C5F13DF001E7B33 /* verify_store.sh */, ); path = includes; sourceTree = ""; diff --git a/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate b/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..137df62d63cb18020d85eabbe75a96261554d626 GIT binary patch literal 11909 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 "$NOTE" - echo "DATE: $(date)" >> "$NOTE" - elif [ "$ENCRYPTION" == "TRUE" ]; then + # Refuse to overwrite a note + if [ -e "$NOTE" ]; then + printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" + exit 200 + # If the notebook doesn't exist, create it. + elif [ ! -d "$NOTE_DIR" ]; then + mkdir -p "$NOTE_DIR" + fi + + # Write the standard note header + if [ "$ENCRYPTION" == "TRUE" ]; then TMP_NOTE="$TMP_DIR"/"$SESSION_ID" p_header > "$TMP_NOTE" encrypt - fi - - if [ -e "$NOTE" ]; then + else + p_header > "$NOTE" + fi + # Make sure the note exists, and inform the user. + if [ -e "$NOTE" ]; then echo "Created note: $NOTEBOOK/$SECTION/$NAME." - fi - + else + printf "%s\n" "Something went wrong." + fi } diff --git a/src/includes/delete.sns.sh b/src/includes/delete.sns.sh index f0b47dc..696d9d1 100644 --- a/src/includes/delete.sns.sh +++ b/src/includes/delete.sns.sh @@ -1,14 +1,10 @@ function delete(){ - if [ "$DELETE" == "TRUE" ]; then - if [ -e "$NOTE" ]; then - rm "$NOTE" - echo "" - echo "Deleted note: $NOTEBOOK/$SECTION/$NAME." - exit - else - echo "" - echo "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." - exit - fi - fi + #Requires: $NOTE, $NOTEBOOK, $SECTION, $NAME + # Given a valid $NOTE, delete removes $NOTE from sns. + if [ -e "$NOTE" ]; then + rm "$NOTE" + printf "\n%s\n" "Deleted note: $NOTEBOOK/$SECTION/$NAME." + else + printf "\n%s\n" "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." + fi } diff --git a/src/includes/edit.sns.sh b/src/includes/edit.sns.sh index 91f0e7f..54702c5 100644 --- a/src/includes/edit.sns.sh +++ b/src/includes/edit.sns.sh @@ -1,15 +1,20 @@ function edit(){ +# Requires: $EDITOR, $NOTE +# Optional: $ENCRYPTION, $TMP_DIR, $SESSION_ID, decrypt, encrypt + +# Verify an editor was specified if [ -z "$EDITOR" ]; then >&2 echo "Error no editor specified in environment." exit +# Verify the note exists elif [ ! -r "$NOTE" ]; then echo "ERROR: Note cannot be opened for editing." exit 40; fi - +# When encryption is enabled, decrypt $NOTE to a temp file if [ "$ENCRYPTION" == "TRUE" ]; then - cp "$NOTE" "$NOTE".bk - if [ ! -d "$ROOT_DIR"/tmp ]; then mkdir "$ROOT_DIR"/tmp; fi + cp "$NOTE" "$NOTE".bk #Insurance + if [ ! -d "$TMP_DIR" ]; then mkdir "$TMP_DIR"; fi TMP_NOTE="$TMP_DIR/$SESSION_ID" decrypt > "$TMP_NOTE" else TMP_NOTE="$NOTE"; fi diff --git a/src/includes/verify_store.sh b/src/includes/verify_store.sh index 1e75289..f4fc06f 100644 --- a/src/includes/verify_store.sh +++ b/src/includes/verify_store.sh @@ -1,7 +1,6 @@ -#!/bin/sh - -# verify_store.sh -# sns -# -# Created by Jon-William Lewis on 1/31/16. -# +function verify_store { + STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR") + for DIR in ${STORE_DIRS[]}; do + mkdir -p "$DIR" + done +} \ No newline at end of file diff --git a/src/main/stage1.sns.sh b/src/main/stage1.sns.sh index d0eadd1..b2ddef2 100644 --- a/src/main/stage1.sns.sh +++ b/src/main/stage1.sns.sh @@ -1,41 +1,41 @@ -#============================================================================== -# Section: Configuration / Stage 1 -#============================================================================== -if [ -r "$CONFIG_FILE" ]; then - source "$CONFIG_FILE" -else - create_sns_root - source "$CONFIG_FILE" -fi + #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # Entry Point + #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + #============================================================================== + # Stage 1: Read Configuration / Verify Integrity + #============================================================================== + if [ -r "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" + else + init_store + source "$CONFIG_FILE" + fi -if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$PUBKEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - fi + verify_store - command -v gpg >/dev/null 2>&1 ||\ - { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } -fi + if [ "$ENCRYPTION" == "TRUE" ]; then + if [ -z "$PUBKEY" ]; then + ERR_NO_KEY="TRUE" + ENCRYPTION="FALSE" + fi -if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" - if [ ! -d "$ROOT_DIR"/tmp ]; then - mkdir -p "$ROOT_DIR"/tmp - fi -fi + command -v gpg >/dev/null 2>&1 ||\ + { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } + fi -echo "$PROD_STR, $VER_STR" + if [ "$ENCRYPTION" == "TRUE" ]; then + PROD_STR="Simple Note System (Encryption Enabled)" + if [ ! -d "$ROOT_DIR"/tmp ]; then + mkdir -p "$ROOT_DIR"/tmp + fi + fi -if [ -n "$ERR_NO_GPG" ]; then - >&2 echo " Error: Encryption was specified, but GPG is not installed." - exit 100 -elif [ -n "$ERR_NO_KEY" ]; then - >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " - exit 110 -fi + echo "$PROD_STR, $VER_STR" - -#============================================================================== -# End Section: Configuration / Stage 1 -#============================================================================== + if [ -n "$ERR_NO_GPG" ]; then + >&2 echo " Error: Encryption was specified, but GPG is not installed." + exit 100 + elif [ -n "$ERR_NO_KEY" ]; then + >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " + exit 110 + fi diff --git a/src/main/stage2.sns.sh b/src/main/stage2.sns.sh index b62b775..0fcc5fc 100644 --- a/src/main/stage2.sns.sh +++ b/src/main/stage2.sns.sh @@ -1,41 +1,34 @@ -#============================================================================== -# Section: Argument Parsing / Stage 2 -#============================================================================== - -NAME="" -NOTEBOOK="" -SECTION="" -if [ -z "$1" ]; then help; exit 20 -else - ARGS=( "$@" ) - for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" - elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 - else - if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" - elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" - elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" + #============================================================================== + # Stage 2: Argument Parsing + #============================================================================== + NAME="" + NOTEBOOK="" + SECTION="" + if [ -z "$1" ]; then help; exit 20 + else + ARGS=( "$@" ) + for ARG in "${ARGS[@]}"; do + if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" + elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" + elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" + elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" + elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" + elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" + elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 + else + if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" + elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" + elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" + fi + fi + done + if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then + # If a note title was specified, but no notebook, and the list option + # was specified, assume that the detected note title is actually the + # name of a notebook + NOTEBOOK="$NAME" + NAME="" + fi fi - fi - done - if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then - # If we got a note title above, but no notebook, and the list option - # was specified, we assume that the detected note title is actually a - # notebook name. - NOTEBOOK="$NAME" - NAME="" - fi -fi - -# Note: w_conf and help have highest priority, as they are the only functions -# that can work without any arguments. - -#============================================================================== -# End Section: Argument Parsing / Stage 2 -#============================================================================== + # w_conf and help are called here to avoid excess stage 3 code. diff --git a/src/main/stage3.sns.sh b/src/main/stage3.sns.sh index da7f738..67deb52 100644 --- a/src/main/stage3.sns.sh +++ b/src/main/stage3.sns.sh @@ -1,39 +1,37 @@ -#============================================================================== -# Section: Actions / Stage 3 -#============================================================================== -# List only requires a notebook, and is exclusive. -if [ -z "$NOTEBOOK" ]; then - echo " ERROR: Insufficient arguments:" - echo " Notebook not specified" - exit 30 -fi - -if [ -n "$LIST" ]; then - list - exit 0 -fi - -#All other functions require a note title and notebook. - -if [ -z "$NAME" ]; then - echo " ERROR: Insufficient arguments:" - echo " Title not specified" - exit 30 -fi - -SESSION_ID="$RANDOM" -NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION"/ + #============================================================================== + # Section: Actions / Stage 3 + #============================================================================== + # All options not requiring at least a notebook to be specified have been dealt + # with; if one isn't specified, throw code 30. + if [ -z "$NOTEBOOK" ]; then + printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + exit 30 + fi + # List is the only option requiring only a notebook. + # If list isn't the selected option and no note name was specified, throw code 30. + if [ "$LIST" == TRUE ]; then + list + exit 0 + elif [ -z "$NAME" ]; + printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + exit 30 + fi + + NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" -if [ "$ENCRYPTION" == "TRUE" ]; then readonly NOTE="$NOTE_DIR""$NAME"."$EXT".gpg -else readonly NOTE="$NOTE_DIR""$NAME"."$EXT" -fi + if [ "$ENCRYPTION" == "TRUE" ]; then + SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename + readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" + else + readonly NOTE="$NOTE_DIR/$NAME.$EXT" + fi -if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi -if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi -if [ "$CREATE" == "TRUE" ]; then create; fi -if [ "$EDIT" == "TRUE" ]; then edit; fi + if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi + if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi + if [ "$CREATE" == "TRUE" ]; then create; fi + if [ "$EDIT" == "TRUE" ]; then edit; fi -#============================================================================== -# End Section: Actions / Stage 3 -#============================================================================== \ No newline at end of file + #============================================================================== + # End Section: Actions / Stage 3 + #============================================================================== From 993a6508d33d59ba29a6440530f0b4bbf6e025a9 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Thu, 11 Feb 2016 00:22:34 -0600 Subject: [PATCH 04/14] Code cleanup --- build.sh | 5 +- errors.ref | 7 +- header.sh | 5 +- sns.sh | 150 ++++++++++-------- sns.xcodeproj/project.pbxproj | 8 +- .../UserInterfaceState.xcuserstate | Bin 11909 -> 15437 bytes src/includes/help.sns.sh | 2 +- src/includes/init_store.sns.sh | 35 ++-- ...{libencryption.sh => libencryption.sns.sh} | 0 src/includes/verify_store.sh | 6 - src/includes/verify_store.sns.sh | 7 + src/main/stage2.sns.sh | 15 +- src/main/stage3.sns.sh | 7 +- 13 files changed, 135 insertions(+), 112 deletions(-) rename src/includes/{libencryption.sh => libencryption.sns.sh} (100%) delete mode 100644 src/includes/verify_store.sh create mode 100644 src/includes/verify_store.sns.sh diff --git a/build.sh b/build.sh index 77dd483..d23b4e5 100755 --- a/build.sh +++ b/build.sh @@ -8,11 +8,12 @@ S=sns.sh bash header.sh > "$S" echo -e "\n# Section: Functions" >> "$S" -cat ./src/includes/create_sns_root.sns.sh >> "$S" +cat ./src/includes/init_store.sns.sh >> "$S" +cat ./src/includes/verify_store.sns.sh >> "$S" cat ./src/includes/pause.sns.sh >> "$S" cat ./src/includes/help.sns.sh >> "$S" cat ./src/includes/p_header.sh >> "$S" -cat ./src/includes/libencryption.sh >> "$S" +cat ./src/includes/libencryption.sns.sh >> "$S" cat ./src/includes/create.sns.sh >> "$S" cat ./src/includes/delete.sns.sh >> "$S" cat ./src/includes/edit.sns.sh >> "$S" diff --git a/errors.ref b/errors.ref index 620ffb6..28754c8 100644 --- a/errors.ref +++ b/errors.ref @@ -4,12 +4,11 @@ Error Code Reference General------------------------------------------------------------------------- ERR_NO_ARGS 10 No arguments were specified ERR_NO_OP 20 -ERR_INSUFFICIENT_ARGS 30 A required argument was not provided - +ERR_NO_NOTEBOOK 30 A required argument was not provided Encryption---------------------------------------------------------------------- -ERR_NO_GPG 100 GPG is not installed -ERR_NO_KEY 110 No recipient specified +ERR_NO_GPG 100 Encryption is enabled, but GPG is not installed +ERR_NO_KEY 110 Encryption is enabled, but no recipient was specified Create-------------------------------------------------------------------------- ERR_NOTE_EXiSTS 200 The specified note already exists \ No newline at end of file diff --git a/header.sh b/header.sh index cd39b16..454afb9 100644 --- a/header.sh +++ b/header.sh @@ -9,14 +9,13 @@ cat << EOF # Copyright $YEAR, Xenese Labs/Sicron-Perion XNF #========================================================== +# Prevent freak accidents involving the root directory if [ -z "\$HOME" ]; then HOME=/home/"\$(whoami)"; fi PROD_STR="$PROD_STR" readonly VER_STR="$VER_STR" -readonly ROOT_DIR="\$HOME"/.config/xenlabs/sns +readonly ROOT_DIR="\$HOME"/.config/sns readonly NOTES_DIR="\$ROOT_DIR"/notes readonly TMP_DIR="\$ROOT_DIR"/tmp readonly CONFIG_FILE="\$ROOT_DIR/sns.conf" - - EOF diff --git a/sns.sh b/sns.sh index 8beb03f..ec6ad02 100755 --- a/sns.sh +++ b/sns.sh @@ -8,51 +8,53 @@ if [ -z "$HOME" ]; then HOME=/home/"$(whoami)"; fi PROD_STR="Simple Note System" readonly VER_STR="v2.0a8" -readonly ROOT_DIR="$HOME"/.config/xenlabs/sns +readonly ROOT_DIR="$HOME"/.config/sns readonly NOTES_DIR="$ROOT_DIR"/notes readonly TMP_DIR="$ROOT_DIR"/tmp readonly CONFIG_FILE="$ROOT_DIR/sns.conf" - - # Section: Functions -function create_sns_root { +function init_store { -if [ ! -r "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi +if [ ! -d "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi cat > "$CONFIG_FILE" << EOF -#========================================================== -# Simple Note System Config, v2.0a8 -# Copyright 2014, Xenese Labs/Sicron-Perion XNF -#========================================================== +# This file contains directives for the Simple Note System. -#File extension to use (for listing notes) -EXT=note +EXT=note # File extension to use (for listing notes) -#Preferred Editor -if [ -z "$EDITOR" ]; then - EDITOR=vim -fi +#EDITOR= # Preferred Editor: + # If you would like to specify a different editor for + # sns to use, you may do so here. -#Encryption -#WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST +ENCRYPTION="FALSE" # Main Encryption Toggle: + # WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST + # Change this to TRUE to enable encryption. -#ENCRYPTION="TRUE" -ENCRYPTION="FALSE" - -PUBKEY="" +PUBKEY="" # Public Key + # Encryption is done using GPG. You must enter your + # public key's identifier here. EOF chmod 600 "$CONFIG_FILE" +printf " - %s\n" "Rewrote Default Configuration" + if [ "$WILL_INIT" == "TRUE" ]; then - printf "%s %s\n" "Environment initialized in" "$ROOT_DIR" + printf " - %s %s\n" "Environment initialized in" "$ROOT_DIR" else - printf "%s\n" "Environment already initialized." + printf " - %s\n" "Store already initialized." fi } +function verify_store { + ETC_DIR="$(dirname \"$CONFIG_FILE\")" + STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR" "$ETC_DIR") + for DIR in ${STORE_DIRS[@]}; do + mkdir -p "$DIR" + done +} function pause { read -rp " Press [Enter] to continue." echo "" @@ -72,7 +74,7 @@ function help { echo " -h | --help : Display this message" echo " -p | --print : Print note to console" echo " -l | --list : List all notes in NOTEBOOK" - echo " -w | --wconf : Rewrite default configuration" + echo " -i | --init : Write default config and initalize SNS store" echo "" } function p_header(){ @@ -94,52 +96,63 @@ function decrypt(){ gpg -d "$NOTE" } function create(){ - if [ -e "$NOTE" ]; then - printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" - exit - else - mkdir -p "$NOTE_DIR" - fi + # Depends : p_header + # Requires: $NOTE, $NOTE_DIR, $NOTEBOOK, $SECTION, $NAME + # Optional: $ENCRYPTION, $SESSION_ID, $TMP_DIR encrypt + # Given a valid setup, create writes the standard note header as specified + # by p_header, to $NOTE. - if [ -z "$ENCRYPTION" ]; then - echo "TITLE: $NAME" > "$NOTE" - echo "DATE: $(date)" >> "$NOTE" - elif [ "$ENCRYPTION" == "TRUE" ]; then + # Refuse to overwrite a note + if [ -e "$NOTE" ]; then + printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" + exit 200 + # If the notebook doesn't exist, create it. + elif [ ! -d "$NOTE_DIR" ]; then + mkdir -p "$NOTE_DIR" + fi + + # Write the standard note header + if [ "$ENCRYPTION" == "TRUE" ]; then TMP_NOTE="$TMP_DIR"/"$SESSION_ID" p_header > "$TMP_NOTE" encrypt - fi - - if [ -e "$NOTE" ]; then + else + p_header > "$NOTE" + fi + # Make sure the note exists, and inform the user. + if [ -e "$NOTE" ]; then echo "Created note: $NOTEBOOK/$SECTION/$NAME." - fi + else + printf "%s\n" "Something went wrong." + fi } function delete(){ - if [ "$DELETE" == "TRUE" ]; then - if [ -e "$NOTE" ]; then - rm "$NOTE" - echo "" - echo "Deleted note: $NOTEBOOK/$SECTION/$NAME." - exit - else - echo "" - echo "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." - exit - fi - fi + #Requires: $NOTE, $NOTEBOOK, $SECTION, $NAME + # Given a valid $NOTE, delete removes $NOTE from sns. + if [ -e "$NOTE" ]; then + rm "$NOTE" + printf "\n%s\n" "Deleted note: $NOTEBOOK/$SECTION/$NAME." + else + printf "\n%s\n" "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." + fi } function edit(){ +# Requires: $EDITOR, $NOTE +# Optional: $ENCRYPTION, $TMP_DIR, $SESSION_ID, decrypt, encrypt + +# Verify an editor was specified if [ -z "$EDITOR" ]; then >&2 echo "Error no editor specified in environment." exit +# Verify the note exists elif [ ! -r "$NOTE" ]; then echo "ERROR: Note cannot be opened for editing." exit 40; fi - +# When encryption is enabled, decrypt $NOTE to a temp file if [ "$ENCRYPTION" == "TRUE" ]; then - cp "$NOTE" "$NOTE".bk - if [ ! -d "$ROOT_DIR"/tmp ]; then mkdir "$ROOT_DIR"/tmp; fi + cp "$NOTE" "$NOTE".bk #Insurance + if [ ! -d "$TMP_DIR" ]; then mkdir "$TMP_DIR"; fi TMP_NOTE="$TMP_DIR/$SESSION_ID" decrypt > "$TMP_NOTE" else TMP_NOTE="$NOTE"; fi @@ -184,15 +197,17 @@ function list(){ # Entry Point #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #============================================================================== - # Stage 1: Read Configuration + # Stage 1: Read Configuration / Verify Integrity #============================================================================== if [ -r "$CONFIG_FILE" ]; then source "$CONFIG_FILE" else - create_sns_root + init_store source "$CONFIG_FILE" fi + verify_store + if [ "$ENCRYPTION" == "TRUE" ]; then if [ -z "$PUBKEY" ]; then ERR_NO_KEY="TRUE" @@ -229,14 +244,14 @@ function list(){ else ARGS=( "$@" ) for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" + if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE"; OP="TRUE" + elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" + elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 else if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" @@ -252,12 +267,18 @@ function list(){ NAME="" fi fi + # w_conf and help are called here to avoid excess stage 3 code. #============================================================================== # Section: Actions / Stage 3 #============================================================================== + # Default behavior + # If no operation was specified, print help and exit on ERR_NO_OP + if [ "$OP" != "TRUE" ]; then + help; exit 20 + fi # All options not requiring at least a notebook to be specified have been dealt - # with; if one isn't specified, throw code 30. + # with; if one isn't specified, exit on ERR_NO_NOTEBOOK. if [ -z "$NOTEBOOK" ]; then printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" exit 30 @@ -267,7 +288,7 @@ function list(){ if [ "$LIST" == TRUE ]; then list exit 0 - elif [ -z "$NAME" ]; then + elif [ -z "$NAME" ]; printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" exit 30 fi @@ -280,7 +301,6 @@ function list(){ readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" else readonly NOTE="$NOTE_DIR/$NAME.$EXT" - echo "$NOTE" fi if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi diff --git a/sns.xcodeproj/project.pbxproj b/sns.xcodeproj/project.pbxproj index d55d3e0..0c77465 100644 --- a/sns.xcodeproj/project.pbxproj +++ b/sns.xcodeproj/project.pbxproj @@ -19,8 +19,8 @@ 5D22D6AD1AFC4F5A0036DC52 /* stage1.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage1.sns.sh; sourceTree = ""; }; 5D22D6AE1AFC4F5A0036DC52 /* stage2.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage2.sns.sh; sourceTree = ""; }; 5D22D6AF1AFC4F5A0036DC52 /* stage3.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stage3.sns.sh; sourceTree = ""; }; - 5D22D6B01AFC5B100036DC52 /* libencryption.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = libencryption.sh; sourceTree = ""; }; - 5D75D24F1C5F13DF001E7B33 /* verify_store.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = verify_store.sh; sourceTree = ""; }; + 5D22D6B01AFC5B100036DC52 /* libencryption.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = libencryption.sns.sh; sourceTree = ""; }; + 5D75D24F1C5F13DF001E7B33 /* verify_store.sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = verify_store.sns.sh; sourceTree = ""; }; 5D7E611F1AB74D33001D49B9 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = ""; }; 5D7E91FB1B27FB620030B30D /* header.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = header.sh; sourceTree = ""; }; 5DE839831AB9DACE006CB4F6 /* sns.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sns.sh; sourceTree = ""; }; @@ -49,8 +49,8 @@ 5D22D6A91AFC4F5A0036DC52 /* pause.sns.sh */, 5D22D6AA1AFC4F5A0036DC52 /* print.sns.sh */, 5D22D6AB1AFC4F5A0036DC52 /* init_store.sns.sh */, - 5D22D6B01AFC5B100036DC52 /* libencryption.sh */, - 5D75D24F1C5F13DF001E7B33 /* verify_store.sh */, + 5D22D6B01AFC5B100036DC52 /* libencryption.sns.sh */, + 5D75D24F1C5F13DF001E7B33 /* verify_store.sns.sh */, ); path = includes; sourceTree = ""; diff --git a/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate b/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate index 137df62d63cb18020d85eabbe75a96261554d626..c97975e4e9623f6bed218612f7107acedad50a09 100644 GIT binary patch literal 15437 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 AUjP6A literal 11909 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 "$CONFIG_FILE" << EOF -#========================================================== -# Simple Note System Config, v2.0a8 -# Copyright 2014, Xenese Labs/Sicron-Perion XNF -#========================================================== +# This file contains directives for the Simple Note System. -#File extension to use (for listing notes) -EXT=note +EXT=note # File extension to use (for listing notes) -#Preferred Editor -if [ -z "$EDITOR" ]; then - EDITOR=vim -fi +#EDITOR= # Preferred Editor: + # If you would like to specify a different editor for + # sns to use, you may do so here. -#Encryption -#WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST +ENCRYPTION="FALSE" # Main Encryption Toggle: + # WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST + # Change this to TRUE to enable encryption. -#ENCRYPTION="TRUE" -ENCRYPTION="FALSE" - -PUBKEY="" +PUBKEY="" # Public Key + # Encryption is done using GPG. You must enter your + # public key's identifier here. EOF chmod 600 "$CONFIG_FILE" +printf " - %s\n" "Rewrote Default Configuration" + if [ "$WILL_INIT" == "TRUE" ]; then - printf "%s %s\n" "Environment initialized in" "$ROOT_DIR" + printf " - %s %s\n" "Environment initialized in" "$ROOT_DIR" else - printf "%s\n" "Environment already initialized." + printf " - %s\n" "Store already initialized." fi } diff --git a/src/includes/libencryption.sh b/src/includes/libencryption.sns.sh similarity index 100% rename from src/includes/libencryption.sh rename to src/includes/libencryption.sns.sh diff --git a/src/includes/verify_store.sh b/src/includes/verify_store.sh deleted file mode 100644 index f4fc06f..0000000 --- a/src/includes/verify_store.sh +++ /dev/null @@ -1,6 +0,0 @@ -function verify_store { - STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR") - for DIR in ${STORE_DIRS[]}; do - mkdir -p "$DIR" - done -} \ No newline at end of file diff --git a/src/includes/verify_store.sns.sh b/src/includes/verify_store.sns.sh new file mode 100644 index 0000000..9604d8d --- /dev/null +++ b/src/includes/verify_store.sns.sh @@ -0,0 +1,7 @@ +function verify_store { + ETC_DIR="$(dirname \"$CONFIG_FILE\")" + STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR" "$ETC_DIR") + for DIR in ${STORE_DIRS[@]}; do + mkdir -p "$DIR" + done +} diff --git a/src/main/stage2.sns.sh b/src/main/stage2.sns.sh index 0fcc5fc..ed56a34 100644 --- a/src/main/stage2.sns.sh +++ b/src/main/stage2.sns.sh @@ -8,14 +8,14 @@ else ARGS=( "$@" ) for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE" + if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE"; OP="TRUE" + elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE"; OP="TRUE" + elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" + elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then create_sns_root; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 else if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" @@ -31,4 +31,5 @@ NAME="" fi fi + # w_conf and help are called here to avoid excess stage 3 code. diff --git a/src/main/stage3.sns.sh b/src/main/stage3.sns.sh index 67deb52..a0a1adf 100644 --- a/src/main/stage3.sns.sh +++ b/src/main/stage3.sns.sh @@ -1,8 +1,13 @@ #============================================================================== # Section: Actions / Stage 3 #============================================================================== + # Default behavior + # If no operation was specified, print help and exit on ERR_NO_OP + if [ "$OP" != "TRUE" ]; then + help; exit 20 + fi # All options not requiring at least a notebook to be specified have been dealt - # with; if one isn't specified, throw code 30. + # with; if one isn't specified, exit on ERR_NO_NOTEBOOK. if [ -z "$NOTEBOOK" ]; then printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" exit 30 From 1cce779aa7e46297fdf754d767e7e3b494c402d6 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Sun, 14 Feb 2016 22:54:01 -0600 Subject: [PATCH 05/14] Changed readme to match recent changes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41e571c..7984fd9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Simple Note System ================== The Simple Note System is a shell script enabling easy management of plain-text -notes. SNS depends on OpenSSL for encryption and uses the vim editor by default. +notes. SNS depends on GPG for encryption and uses the vim editor by default. usage: sns [-ce] NAME NOTEBOOK SECTION" sns [-d ] NAME NOTEBOOK SECTION" @@ -16,4 +16,4 @@ notes. SNS depends on OpenSSL for encryption and uses the vim editor by default. -h | --help : Display this message" -p | --print : Print note to console" -l | --list : List all notes in NOTEBOOK" - -w | --wconf : Rewrite default configuration" + -i | --init : Write default config and initalize SNS store" From 48b65a6bef2e20d3c9d064747e59ebc687b8b979 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Sun, 14 Feb 2016 22:58:47 -0600 Subject: [PATCH 06/14] Cleaned up unnecessary files --- nul | 0 null | 0 sns.sh | 313 ------------------------------------------------------- sns1.sh | 316 -------------------------------------------------------- 4 files changed, 629 deletions(-) delete mode 100644 nul delete mode 100644 null delete mode 100755 sns.sh delete mode 100644 sns1.sh diff --git a/nul b/nul deleted file mode 100644 index e69de29..0000000 diff --git a/null b/null deleted file mode 100644 index e69de29..0000000 diff --git a/sns.sh b/sns.sh deleted file mode 100755 index ec6ad02..0000000 --- a/sns.sh +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/bash -#========================================================== -# Simple Note System, v2.0a8 -# Copyright 2016, Xenese Labs/Sicron-Perion XNF -#========================================================== - -if [ -z "$HOME" ]; then HOME=/home/"$(whoami)"; fi - -PROD_STR="Simple Note System" -readonly VER_STR="v2.0a8" -readonly ROOT_DIR="$HOME"/.config/sns -readonly NOTES_DIR="$ROOT_DIR"/notes -readonly TMP_DIR="$ROOT_DIR"/tmp -readonly CONFIG_FILE="$ROOT_DIR/sns.conf" - -# Section: Functions -function init_store { - -if [ ! -d "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi -if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi - - -cat > "$CONFIG_FILE" << EOF -# This file contains directives for the Simple Note System. - -EXT=note # File extension to use (for listing notes) - -#EDITOR= # Preferred Editor: - # If you would like to specify a different editor for - # sns to use, you may do so here. - -ENCRYPTION="FALSE" # Main Encryption Toggle: - # WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST - # Change this to TRUE to enable encryption. - -PUBKEY="" # Public Key - # Encryption is done using GPG. You must enter your - # public key's identifier here. -EOF - -chmod 600 "$CONFIG_FILE" - -printf " - %s\n" "Rewrote Default Configuration" - -if [ "$WILL_INIT" == "TRUE" ]; then - printf " - %s %s\n" "Environment initialized in" "$ROOT_DIR" -else - printf " - %s\n" "Store already initialized." -fi -} -function verify_store { - ETC_DIR="$(dirname \"$CONFIG_FILE\")" - STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR" "$ETC_DIR") - for DIR in ${STORE_DIRS[@]}; do - mkdir -p "$DIR" - done -} -function pause { - read -rp " Press [Enter] to continue." - echo "" -} -function help { - echo "" - echo "usage: sns [-ce] NAME NOTEBOOK SECTION" - echo " sns [-d ] NAME NOTEBOOK SECTION" - echo " sns [-lp] NOTEBOOK" - echo " sns [-w ]" - echo " sns [-h ]" - - echo "" - echo " -c | --create : Create note" - echo " -d | --delete : Delete note" - echo " -e | --edit : Open note for editing" - echo " -h | --help : Display this message" - echo " -p | --print : Print note to console" - echo " -l | --list : List all notes in NOTEBOOK" - echo " -i | --init : Write default config and initalize SNS store" - echo "" -} -function p_header(){ - printf "TITLE: %s\nDATE: %s\n" "$NAME" "$(date)" -} -function encrypt(){ -# This function, given a recipient, $PUBKEY; a file to encrypt, $TMP_NOTE; and an -# output file, "$NOTE", will encrypt $TMP_NOTE to $NOTE against $PUBKEY's private -# GPG key. - - gpg -r "$PUBKEY" -o "$NOTE" -e "$TMP_NOTE" - -} - -function decrypt(){ -# This function, given a recipient, $PUBKEY; a file to decrypt, $TMP_NOTE; and an -# output file, "$NOTE", will decrpyt $TMP_NOTE to $NOTE against $PUBKEY's private -# GPG key. - gpg -d "$NOTE" -} -function create(){ - # Depends : p_header - # Requires: $NOTE, $NOTE_DIR, $NOTEBOOK, $SECTION, $NAME - # Optional: $ENCRYPTION, $SESSION_ID, $TMP_DIR encrypt - # Given a valid setup, create writes the standard note header as specified - # by p_header, to $NOTE. - - # Refuse to overwrite a note - if [ -e "$NOTE" ]; then - printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" - exit 200 - # If the notebook doesn't exist, create it. - elif [ ! -d "$NOTE_DIR" ]; then - mkdir -p "$NOTE_DIR" - fi - - # Write the standard note header - if [ "$ENCRYPTION" == "TRUE" ]; then - TMP_NOTE="$TMP_DIR"/"$SESSION_ID" - p_header > "$TMP_NOTE" - encrypt - else - p_header > "$NOTE" - fi - # Make sure the note exists, and inform the user. - if [ -e "$NOTE" ]; then - echo "Created note: $NOTEBOOK/$SECTION/$NAME." - else - printf "%s\n" "Something went wrong." - fi -} -function delete(){ - #Requires: $NOTE, $NOTEBOOK, $SECTION, $NAME - # Given a valid $NOTE, delete removes $NOTE from sns. - if [ -e "$NOTE" ]; then - rm "$NOTE" - printf "\n%s\n" "Deleted note: $NOTEBOOK/$SECTION/$NAME." - else - printf "\n%s\n" "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." - fi -} -function edit(){ -# Requires: $EDITOR, $NOTE -# Optional: $ENCRYPTION, $TMP_DIR, $SESSION_ID, decrypt, encrypt - -# Verify an editor was specified -if [ -z "$EDITOR" ]; then - >&2 echo "Error no editor specified in environment." - exit -# Verify the note exists -elif [ ! -r "$NOTE" ]; then - echo "ERROR: Note cannot be opened for editing." - exit 40; -fi -# When encryption is enabled, decrypt $NOTE to a temp file -if [ "$ENCRYPTION" == "TRUE" ]; then - cp "$NOTE" "$NOTE".bk #Insurance - if [ ! -d "$TMP_DIR" ]; then mkdir "$TMP_DIR"; fi - TMP_NOTE="$TMP_DIR/$SESSION_ID" - decrypt > "$TMP_NOTE" -else TMP_NOTE="$NOTE"; fi - - -if [ -z "$CREATE" ]; then printf "\nEDIT %s" "$(date)" >> "$TMP_NOTE"; fi - -"$EDITOR" "$TMP_NOTE" - -if [ "$ENCRYPTION" == "TRUE" ]; then - rm "$NOTE" - encrypt; - if [ -r "$NOTE" ]; then rm "$NOTE".bk; fi -fi -} -function print(){ - if [ -r "$NOTE" ]; then - if [ -z "$CREATE" ]; then - if [ "$ENCRYPTION" == "TRUE" ]; then - decrypt - else - cat "$NOTE" - fi - else - printf "\nERROR: Note cannot be found.\n" - fi - fi -} -function list(){ - if [ -d "$NOTES_DIR"/"$NOTEBOOK" ]; then - printf "+%s\n" "$NOTEBOOK" - find "$NOTES_DIR"/"$NOTEBOOK" -type f | while read -r NOTE; do - printf " -%s\n" "$(basename \"$NOTE\" | cut -d . -f 1 )" - done - fi -} -# End Section: Functions - - - - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - # Entry Point - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - #============================================================================== - # Stage 1: Read Configuration / Verify Integrity - #============================================================================== - if [ -r "$CONFIG_FILE" ]; then - source "$CONFIG_FILE" - else - init_store - source "$CONFIG_FILE" - fi - - verify_store - - if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$PUBKEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - fi - - command -v gpg >/dev/null 2>&1 ||\ - { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } - fi - - if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" - if [ ! -d "$ROOT_DIR"/tmp ]; then - mkdir -p "$ROOT_DIR"/tmp - fi - fi - - echo "$PROD_STR, $VER_STR" - - if [ -n "$ERR_NO_GPG" ]; then - >&2 echo " Error: Encryption was specified, but GPG is not installed." - exit 100 - elif [ -n "$ERR_NO_KEY" ]; then - >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " - exit 110 - fi - #============================================================================== - # Stage 2: Argument Parsing - #============================================================================== - NAME="" - NOTEBOOK="" - SECTION="" - if [ -z "$1" ]; then help; exit 20 - else - ARGS=( "$@" ) - for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" - elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 - else - if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" - elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" - elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" - fi - fi - done - if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then - # If a note title was specified, but no notebook, and the list option - # was specified, assume that the detected note title is actually the - # name of a notebook - NOTEBOOK="$NAME" - NAME="" - fi - fi - - # w_conf and help are called here to avoid excess stage 3 code. - #============================================================================== - # Section: Actions / Stage 3 - #============================================================================== - # Default behavior - # If no operation was specified, print help and exit on ERR_NO_OP - if [ "$OP" != "TRUE" ]; then - help; exit 20 - fi - # All options not requiring at least a notebook to be specified have been dealt - # with; if one isn't specified, exit on ERR_NO_NOTEBOOK. - if [ -z "$NOTEBOOK" ]; then - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi - # List is the only option requiring only a notebook. - # If list isn't the selected option and no note name was specified, throw code 30. - if [ "$LIST" == TRUE ]; then - list - exit 0 - elif [ -z "$NAME" ]; - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi - - NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" - - - if [ "$ENCRYPTION" == "TRUE" ]; then - SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename - readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" - else - readonly NOTE="$NOTE_DIR/$NAME.$EXT" - fi - - if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi - if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi - if [ "$CREATE" == "TRUE" ]; then create; fi - if [ "$EDIT" == "TRUE" ]; then edit; fi - - #============================================================================== - # End Section: Actions / Stage 3 - #============================================================================== diff --git a/sns1.sh b/sns1.sh deleted file mode 100644 index e1c251f..0000000 --- a/sns1.sh +++ /dev/null @@ -1,316 +0,0 @@ -#!/bin/bash -#========================================================== -# Simple Note System, v1.1 -# Copyright 2014, Xenese Labs/Sicron-Perion XNF -#========================================================== - -PROD_STR="Simple Note System" -VER_STR=v1.1 - -#============================================================================== -# Section: Helper Functions -#============================================================================== -function writeconf { -cat > $HOME/.sns << EOF -#========================================================== -# Simple Note System Config, v1.1 -# Copyright 2014, Xenese Labs/Sicron-Perion XNF -#========================================================== - -#Directory where notes will be stored -BASEDIR=$HOME/notes - -#File extension to use (for listing notes) -EXT=note - -#Preferred Editor -EDITOR=vim - -#Encryption -#WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST -ENCRYPTION="FALSE" -ENC_KEY="" -EOF - -chmod 600 $HOME/.sns -} - -function help { - echo "" - echo "usage: sns [-ce] NAME NOTEBOOK SECTION" - echo " sns [-d ] NAME NOTEBOOK SECTION" - echo " sns [-l ] NOTEBOOK" - echo " sns [-w ]" - - echo "" - echo " -c | --create : Create note" - echo " -d | --delete : Delete note" - echo " -e | --edit : Open note for editing" - echo " -p | --print : Print note to console" - echo " -l | --list : List all notes in NOTEBOOK" - echo " -w | --wconf : Write default configuration to ~/.sns (useful for Encryption)" - echo "" -} - -function pause { - read -p " Press [Enter] to continue." - echo "" -} - -#============================================================================== -# End Section: Helper Functions -#============================================================================== - -#============================================================================== -# Section: Configuration -#============================================================================== -if [ -r $HOME/.sns ]; then - source $HOME/.sns -else - BASEDIR=$HOME/notes - EDITOR=vim - EXT=note -fi - -if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$ENC_KEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - pause - fi - command -v openssl >/dev/null 2>&1 || { ERR_NO_SSL="TRUE"; ENCRYPTION="FALSE"; } -fi - -if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" - EXT="$EXT.enc" - if [ ! -d ~/.tmp ]; then - mkdir -p ~/.tmp - fi -fi - -echo "$PROD_STR, $VER_STR" -if [ -n "$ERR_NO_SSL" ]; then - echo >&2 " Warning: OpenSSL not installed. Encryption disabled." -fi -if [ -n "$ERR_NO_KEY" ]; then - echo " Warning: No encryption key was provided. Encryption disabled." -fi - -if [ -n "$ERR_NO_SSL" -o -n "$ERR_NO_KEY" ]; then - pause -fi - -#============================================================================== -# End Section: Read Configuration -#============================================================================== - - -#============================================================================== -# Section: Argument Parsing -#============================================================================== - -NAME="" -NOTEBOOK="" -SECTION="" - -if [ -z "$1" ]; then #If no input was given, print help - help - exit -else #Assume the user wants to do something. - ARGS=( "$@" ) - for ARG in ${ARGS[@]};do - if [ "$ARG" = "-c" -o "$ARG" = "--create" ]; then CREATE="TRUE" - elif [ "$ARG" = "-d" -o "$ARG" = "--delete" ]; then DELETE="TRUE" - elif [ "$ARG" = "-e" -o "$ARG" = "--edit" ]; then EDIT="TRUE" - elif [ "$ARG" = "-ce" -o "$ARG" = "-ec" ]; then EDIT="TRUE";CREATE="TRUE" - elif [ "$ARG" = "-p" -o "$ARG" = "--print" ]; then PRINT="TRUE" - elif [ "$ARG" = "-l" -o "$ARG" = "--list" ]; then LIST="TRUE" - elif [ "$ARG" = "-h" -o "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-w" -o "$ARG" == "--wconf" ]; then writeconf; exit - else - if [ -z "$NAME" -a -n $ARG ]; then - NAME=$ARG - echo "Name: $NAME" - elif [ -z "$NOTEBOOK" -a -n $ARG ]; then - NOTEBOOK=$ARG - echo "Notebook: $NOTEBOOK" - elif [ -z "$SECTION" -a -n $ARG ]; then - SECTION=$ARG - echo "Section: $SECTION" - fi - fi - done -fi - -#============================================================================== -# End Section: Argument Parsing -#============================================================================== - -#============================================================================== -# Section: Main -#============================================================================== - - NOTEDIR=$BASEDIR/$NOTEBOOK/$SECTION/ - NOTE=$NOTEDIR$NAME.$EXT - - if [ "$ENCRYPTION" == "TRUE" ]; then - NOTE=$NOTE.tmp - fi - - #========================================================================== - # Subection: List - #========================================================================== - if [ -n "$LIST" ]; then - NOTEBOOK="$NAME" #In case of a list command, arg parsing fails. - if [ -z "$NOTEBOOK" ]; then - echo " ERROR: Insufficient arguments" - help - exit - else - if [ -d "$BASEDIR"/"$NOTEBOOK" ]; then - - echo "" - printf "Notes in $(basename $NOTEBOOK):" - echo "" - NOTES=( $(find $BASEDIR/$NOTEBOOK -name "*.$EXT" -print0 | sed s:$BASEDIR/$NOTEBOOK/:" ":g | sed -e s:".$EXT"::g | tr "/" " ") ) - let i=0 - for NOTE in ${NOTES[@]}; do - if [ -d $BASEDIR/$NOTEBOOK/$NOTE ]; then - if [ "$LAST_SECTION" != "$NOTE" ]; then - printf " Section: $NOTE\n" - fi - LAST_SECTION=$NOTE - else - #if [ $(($i % 1)) -eq 0 ]; then - # printf "\n " - #fi - printf " $NOTE\n" - fi - let i++ - done - printf "\n" - else - echo "" - echo "ERROR: Notebook $NOTEBOOK does not exist." - echo "" - fi - fi - exit - fi - #====================================================================== - # Sanity Check - Actions below require a valid $NAME and $NOTEBOOK - #====================================================================== - if [ -z "$NAME" -o -z "$NOTEBOOK" ]; then - echo " ERROR: Insufficient arguments" - help - exit 10 - fi - #========================================================================== - # Subection: Delete - #========================================================================== - if [ "$DELETE" == "TRUE" ]; then - if [ -e $NOTE -o -e ${NOTE%.*} ]; then - if [ "$ENCRYPTION" == "TRUE" ]; then - rm ${NOTE%.*} - else - rm $NOTE - fi - - echo "" - echo "Deleted note: $NOTEBOOK/$SECTION$NAME." - exit - else - - echo "" - echo "ERROR: Note $NOTEBOOK/$SECTION$NAME does not exist." - exit - fi - fi - - #========================================================================== - # Subection: Create - #========================================================================== - if [ -z "$CREATE" -a -z "$EDIT" -a -z "$PRINT" ]; then #If no action specified, print help and exit - help - exit - else - - - if [ "$CREATE" == "TRUE" ]; then - if [ -e $NOTE -o -e ${NOTE%.*} ]; then - - echo "" - echo "ERROR: Note already exists" - echo "Hint: use -e to edit the note." - echo "" - exit - else - #Create any necessary folders - mkdir -p $NOTEDIR - - #Fill in title - echo "TITLE: $NAME" > $NOTE - #Fill the second line with the date - echo "DATE: $(date)" >> $NOTE - - if [ "$ENCRYPTION" == "TRUE" ]; then - if [ $EDIT == "FALSE" ]; then - openssl enc -aes-256-cbc -salt -in $NOTE -out ${NOTE%.*} -pass pass:$ENC_KEY - fi - fi - fi - fi - - #========================================================================== - # Subection: Edit - #========================================================================== - if [ "$EDIT" == "TRUE" ]; then - if [ -r "$NOTE" -o -r ${NOTE%.*} ]; then - if [ -z "$CREATE" ]; then - if [ "$ENCRYPTION" == "TRUE" ]; then - openssl enc -d -aes-256-cbc -in ${NOTE%.*} -pass pass:$ENC_KEY > $NOTE - fi - echo "" >> $NOTE - echo "EDIT $(date)" >> $NOTE - fi - $EDITOR $NOTE - if [ "$ENCRYPTION" == "TRUE" ]; then - openssl enc -aes-256-cbc -salt -in $NOTE -out ${NOTE%.*} -pass pass:$ENC_KEY - rm $NOTE - fi - - else - - echo "" - echo "ERROR: Note cannot be opened for editting." - echo "" - - fi - fi - -fi - #========================================================================== - # Subection: Print - #========================================================================== - if [ "$PRINT" == "TRUE" ]; then - if [ -r "$NOTE" -o -r ${NOTE%.*} ]; then - if [ -z "$CREATE" ]; then - if [ "$ENCRYPTION" == "TRUE" ]; then - openssl enc -d -aes-256-cbc -in ${NOTE%.*} -pass pass:$ENC_KEY - else - cat $NOTE - echo "" >> $NOTE - fi - else - - echo "" - echo "ERROR: Note cannot be found." - echo "" - - fi - fi - -fi - -exit From 54e2cdedd6d3d3fb38a33ee38a1bdda66a15dde6 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Sun, 14 Feb 2016 23:26:25 -0600 Subject: [PATCH 07/14] Made changes to help system --- sns.sh | 313 --------------------------------------------------------- 1 file changed, 313 deletions(-) delete mode 100755 sns.sh diff --git a/sns.sh b/sns.sh deleted file mode 100755 index ec6ad02..0000000 --- a/sns.sh +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/bash -#========================================================== -# Simple Note System, v2.0a8 -# Copyright 2016, Xenese Labs/Sicron-Perion XNF -#========================================================== - -if [ -z "$HOME" ]; then HOME=/home/"$(whoami)"; fi - -PROD_STR="Simple Note System" -readonly VER_STR="v2.0a8" -readonly ROOT_DIR="$HOME"/.config/sns -readonly NOTES_DIR="$ROOT_DIR"/notes -readonly TMP_DIR="$ROOT_DIR"/tmp -readonly CONFIG_FILE="$ROOT_DIR/sns.conf" - -# Section: Functions -function init_store { - -if [ ! -d "$ROOT_DIR" ]; then mkdir -p "$ROOT_DIR"; WILL_INIT="TRUE"; fi -if [ ! -d "$TMP_DIR" ]; then mkdir -p "$TMP_DIR" ; WILL_INIT="TRUE"; fi - - -cat > "$CONFIG_FILE" << EOF -# This file contains directives for the Simple Note System. - -EXT=note # File extension to use (for listing notes) - -#EDITOR= # Preferred Editor: - # If you would like to specify a different editor for - # sns to use, you may do so here. - -ENCRYPTION="FALSE" # Main Encryption Toggle: - # WARNING: ANY PREVIOUSLY UNENCRYPTED NOTES WILL BE LOST - # Change this to TRUE to enable encryption. - -PUBKEY="" # Public Key - # Encryption is done using GPG. You must enter your - # public key's identifier here. -EOF - -chmod 600 "$CONFIG_FILE" - -printf " - %s\n" "Rewrote Default Configuration" - -if [ "$WILL_INIT" == "TRUE" ]; then - printf " - %s %s\n" "Environment initialized in" "$ROOT_DIR" -else - printf " - %s\n" "Store already initialized." -fi -} -function verify_store { - ETC_DIR="$(dirname \"$CONFIG_FILE\")" - STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR" "$ETC_DIR") - for DIR in ${STORE_DIRS[@]}; do - mkdir -p "$DIR" - done -} -function pause { - read -rp " Press [Enter] to continue." - echo "" -} -function help { - echo "" - echo "usage: sns [-ce] NAME NOTEBOOK SECTION" - echo " sns [-d ] NAME NOTEBOOK SECTION" - echo " sns [-lp] NOTEBOOK" - echo " sns [-w ]" - echo " sns [-h ]" - - echo "" - echo " -c | --create : Create note" - echo " -d | --delete : Delete note" - echo " -e | --edit : Open note for editing" - echo " -h | --help : Display this message" - echo " -p | --print : Print note to console" - echo " -l | --list : List all notes in NOTEBOOK" - echo " -i | --init : Write default config and initalize SNS store" - echo "" -} -function p_header(){ - printf "TITLE: %s\nDATE: %s\n" "$NAME" "$(date)" -} -function encrypt(){ -# This function, given a recipient, $PUBKEY; a file to encrypt, $TMP_NOTE; and an -# output file, "$NOTE", will encrypt $TMP_NOTE to $NOTE against $PUBKEY's private -# GPG key. - - gpg -r "$PUBKEY" -o "$NOTE" -e "$TMP_NOTE" - -} - -function decrypt(){ -# This function, given a recipient, $PUBKEY; a file to decrypt, $TMP_NOTE; and an -# output file, "$NOTE", will decrpyt $TMP_NOTE to $NOTE against $PUBKEY's private -# GPG key. - gpg -d "$NOTE" -} -function create(){ - # Depends : p_header - # Requires: $NOTE, $NOTE_DIR, $NOTEBOOK, $SECTION, $NAME - # Optional: $ENCRYPTION, $SESSION_ID, $TMP_DIR encrypt - # Given a valid setup, create writes the standard note header as specified - # by p_header, to $NOTE. - - # Refuse to overwrite a note - if [ -e "$NOTE" ]; then - printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" - exit 200 - # If the notebook doesn't exist, create it. - elif [ ! -d "$NOTE_DIR" ]; then - mkdir -p "$NOTE_DIR" - fi - - # Write the standard note header - if [ "$ENCRYPTION" == "TRUE" ]; then - TMP_NOTE="$TMP_DIR"/"$SESSION_ID" - p_header > "$TMP_NOTE" - encrypt - else - p_header > "$NOTE" - fi - # Make sure the note exists, and inform the user. - if [ -e "$NOTE" ]; then - echo "Created note: $NOTEBOOK/$SECTION/$NAME." - else - printf "%s\n" "Something went wrong." - fi -} -function delete(){ - #Requires: $NOTE, $NOTEBOOK, $SECTION, $NAME - # Given a valid $NOTE, delete removes $NOTE from sns. - if [ -e "$NOTE" ]; then - rm "$NOTE" - printf "\n%s\n" "Deleted note: $NOTEBOOK/$SECTION/$NAME." - else - printf "\n%s\n" "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." - fi -} -function edit(){ -# Requires: $EDITOR, $NOTE -# Optional: $ENCRYPTION, $TMP_DIR, $SESSION_ID, decrypt, encrypt - -# Verify an editor was specified -if [ -z "$EDITOR" ]; then - >&2 echo "Error no editor specified in environment." - exit -# Verify the note exists -elif [ ! -r "$NOTE" ]; then - echo "ERROR: Note cannot be opened for editing." - exit 40; -fi -# When encryption is enabled, decrypt $NOTE to a temp file -if [ "$ENCRYPTION" == "TRUE" ]; then - cp "$NOTE" "$NOTE".bk #Insurance - if [ ! -d "$TMP_DIR" ]; then mkdir "$TMP_DIR"; fi - TMP_NOTE="$TMP_DIR/$SESSION_ID" - decrypt > "$TMP_NOTE" -else TMP_NOTE="$NOTE"; fi - - -if [ -z "$CREATE" ]; then printf "\nEDIT %s" "$(date)" >> "$TMP_NOTE"; fi - -"$EDITOR" "$TMP_NOTE" - -if [ "$ENCRYPTION" == "TRUE" ]; then - rm "$NOTE" - encrypt; - if [ -r "$NOTE" ]; then rm "$NOTE".bk; fi -fi -} -function print(){ - if [ -r "$NOTE" ]; then - if [ -z "$CREATE" ]; then - if [ "$ENCRYPTION" == "TRUE" ]; then - decrypt - else - cat "$NOTE" - fi - else - printf "\nERROR: Note cannot be found.\n" - fi - fi -} -function list(){ - if [ -d "$NOTES_DIR"/"$NOTEBOOK" ]; then - printf "+%s\n" "$NOTEBOOK" - find "$NOTES_DIR"/"$NOTEBOOK" -type f | while read -r NOTE; do - printf " -%s\n" "$(basename \"$NOTE\" | cut -d . -f 1 )" - done - fi -} -# End Section: Functions - - - - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - # Entry Point - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - #============================================================================== - # Stage 1: Read Configuration / Verify Integrity - #============================================================================== - if [ -r "$CONFIG_FILE" ]; then - source "$CONFIG_FILE" - else - init_store - source "$CONFIG_FILE" - fi - - verify_store - - if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$PUBKEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - fi - - command -v gpg >/dev/null 2>&1 ||\ - { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } - fi - - if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" - if [ ! -d "$ROOT_DIR"/tmp ]; then - mkdir -p "$ROOT_DIR"/tmp - fi - fi - - echo "$PROD_STR, $VER_STR" - - if [ -n "$ERR_NO_GPG" ]; then - >&2 echo " Error: Encryption was specified, but GPG is not installed." - exit 100 - elif [ -n "$ERR_NO_KEY" ]; then - >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " - exit 110 - fi - #============================================================================== - # Stage 2: Argument Parsing - #============================================================================== - NAME="" - NOTEBOOK="" - SECTION="" - if [ -z "$1" ]; then help; exit 20 - else - ARGS=( "$@" ) - for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" - elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 - else - if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" - elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" - elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" - fi - fi - done - if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then - # If a note title was specified, but no notebook, and the list option - # was specified, assume that the detected note title is actually the - # name of a notebook - NOTEBOOK="$NAME" - NAME="" - fi - fi - - # w_conf and help are called here to avoid excess stage 3 code. - #============================================================================== - # Section: Actions / Stage 3 - #============================================================================== - # Default behavior - # If no operation was specified, print help and exit on ERR_NO_OP - if [ "$OP" != "TRUE" ]; then - help; exit 20 - fi - # All options not requiring at least a notebook to be specified have been dealt - # with; if one isn't specified, exit on ERR_NO_NOTEBOOK. - if [ -z "$NOTEBOOK" ]; then - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi - # List is the only option requiring only a notebook. - # If list isn't the selected option and no note name was specified, throw code 30. - if [ "$LIST" == TRUE ]; then - list - exit 0 - elif [ -z "$NAME" ]; - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi - - NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" - - - if [ "$ENCRYPTION" == "TRUE" ]; then - SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename - readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" - else - readonly NOTE="$NOTE_DIR/$NAME.$EXT" - fi - - if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi - if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi - if [ "$CREATE" == "TRUE" ]; then create; fi - if [ "$EDIT" == "TRUE" ]; then edit; fi - - #============================================================================== - # End Section: Actions / Stage 3 - #============================================================================== From b2482ca1e4840a67c13dbce5bd811b50f5c8d606 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Sun, 14 Feb 2016 23:56:32 -0600 Subject: [PATCH 08/14] Improvded README --- README.md | 40 ++++++++++++------ .../UserInterfaceState.xcuserstate | Bin 15437 -> 15437 bytes src/main/stage2.sns.sh | 2 +- src/main/stage3.sns.sh | 4 +- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7984fd9..2cfb451 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,31 @@ Simple Note System ================== -The Simple Note System is a shell script enabling easy management of plain-text -notes. SNS depends on GPG for encryption and uses the vim editor by default. +The Simple Note System is a shell script partially inspired by [pass], in that +it stores notes as normal, plaintext, files in normal folders. It uses the +environment-specified editor, and can be configured to use GPG encryption. - usage: sns [-ce] NAME NOTEBOOK SECTION" - sns [-d ] NAME NOTEBOOK SECTION" - sns [-lp] NOTEBOOK" - sns [-w ]" - sns [-h ]" +SNS was originally conceived one morning during an update to a popular note-taking +app. The thought occurred that a note system need not reinvent the wheel with +its own GUI editor and proprietary file format, but instead could use the tools +already provided by the operating system. - -c | --create : Create note" - -d | --delete : Delete note" - -e | --edit : Open note for editing" - -h | --help : Display this message" - -p | --print : Print note to console" - -l | --list : List all notes in NOTEBOOK" - -i | --init : Write default config and initalize SNS store" +As it developed, OpenSSL encryption was dropped in favor of GPG, and the script +was almost entirely rewritten as SNSv2. + + simple note system + ================== + + usage: sns [-cedp] NAME NOTEBOOK SECTION + sns [-l] NOTEBOOK + sns [-hi] + -c | --create : Create note + -d | --delete : Delete note + -e | --edit : Open note for editing + -h | --help : Display this message + -p | --print : Print note to console + -l | --list : List all notes in NOTEBOOK + -i | --init : Write default config and initalize SNS store" + + +[pass]: http://passwordstore.org diff --git a/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate b/sns.xcodeproj/project.xcworkspace/xcuserdata/xilmwa.xcuserdatad/UserInterfaceState.xcuserstate index c97975e4e9623f6bed218612f7107acedad50a09..df0db656877e336bd9f922a0891aabdacbe362db 100644 GIT binary patch delta 27 icmX?GakgSZKOc+Ts?4>UC-bq%16d*uHqX`Fzy|=UN(*iP delta 27 jcmX?GakgSZKOc)o1HbF$$$V_`EF$#}S8SfEyMYe?nl}oV diff --git a/src/main/stage2.sns.sh b/src/main/stage2.sns.sh index ed56a34..10cbc02 100644 --- a/src/main/stage2.sns.sh +++ b/src/main/stage2.sns.sh @@ -15,7 +15,7 @@ elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 + elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 else if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" diff --git a/src/main/stage3.sns.sh b/src/main/stage3.sns.sh index a0a1adf..673b184 100644 --- a/src/main/stage3.sns.sh +++ b/src/main/stage3.sns.sh @@ -17,11 +17,11 @@ if [ "$LIST" == TRUE ]; then list exit 0 - elif [ -z "$NAME" ]; + elif [ -z "$NAME" ]; then printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" exit 30 fi - + NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" From a8a92ba0799a0f013ad86921ed28a3f323337045 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 00:03:01 -0600 Subject: [PATCH 09/14] Changed help function to match README --- src/includes/help.sns.sh | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/includes/help.sns.sh b/src/includes/help.sns.sh index 7cd4981..8f26e97 100644 --- a/src/includes/help.sns.sh +++ b/src/includes/help.sns.sh @@ -1,18 +1,14 @@ function help { - echo "" - echo "usage: sns [-ce] NAME NOTEBOOK SECTION" - echo " sns [-d ] NAME NOTEBOOK SECTION" - echo " sns [-lp] NOTEBOOK" - echo " sns [-w ]" - echo " sns [-h ]" + printf "\n%s" "usage: sns [-cedp] NAME NOTEBOOK SECTION" + printf "\n%s" " sns [-l] NOTEBOOK" + printf "\n%s" " sns [-hi ]" - echo "" - echo " -c | --create : Create note" - echo " -d | --delete : Delete note" - echo " -e | --edit : Open note for editing" - echo " -h | --help : Display this message" - echo " -p | --print : Print note to console" - echo " -l | --list : List all notes in NOTEBOOK" - echo " -i | --init : Write default config and initalize SNS store" - echo "" + printf "\n%s" " -c | --create : Create note" + printf "\n%s" " -d | --delete : Delete note" + printf "\n%s" " -e | --edit : Open note for editing" + printf "\n%s" " -h | --help : Display this message" + printf "\n%s" " -p | --print : Print note to console" + printf "\n%s" " -l | --list : List all notes in NOTEBOOK" + printf "\n%s" " -i | --init : Write default config and initalize SNS store" + printf "\n" } From 3664b3b4296a62701a2ec6116347d5130380537f Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 00:08:21 -0600 Subject: [PATCH 10/14] Fixed a bug where verify_store would create a " directory tree. --- src/includes/verify_store.sns.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/includes/verify_store.sns.sh b/src/includes/verify_store.sns.sh index 9604d8d..31a59b9 100644 --- a/src/includes/verify_store.sns.sh +++ b/src/includes/verify_store.sns.sh @@ -1,7 +1,7 @@ function verify_store { - ETC_DIR="$(dirname \"$CONFIG_FILE\")" + ETC_DIR=$(dirname "$CONFIG_FILE") STORE_DIRS=("$ROOT_DIR" "$NOTES_DIR" "$TMP_DIR" "$ETC_DIR") - for DIR in ${STORE_DIRS[@]}; do + for DIR in "${STORE_DIRS[@]}"; do mkdir -p "$DIR" done } From d11c2597c4047e04847e5ee8346749f12f4c15f0 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 00:20:50 -0600 Subject: [PATCH 11/14] Formatting changes --- build.sh | 1 + header.sh | 5 ++++- src/includes/init_store.sns.sh | 2 +- src/main/stage1.sns.sh | 4 +--- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build.sh b/build.sh index d23b4e5..3a306e3 100755 --- a/build.sh +++ b/build.sh @@ -24,4 +24,5 @@ cat ./src/main/stage1.sns.sh >> "$S" cat ./src/main/stage2.sns.sh >> "$S" cat ./src/main/stage3.sns.sh >> "$S" +chmod u+x "$S" exit diff --git a/header.sh b/header.sh index 454afb9..9ffc69b 100644 --- a/header.sh +++ b/header.sh @@ -12,10 +12,13 @@ cat << EOF # Prevent freak accidents involving the root directory if [ -z "\$HOME" ]; then HOME=/home/"\$(whoami)"; fi -PROD_STR="$PROD_STR" +readonly PROD_STR="$PROD_STR" readonly VER_STR="$VER_STR" readonly ROOT_DIR="\$HOME"/.config/sns readonly NOTES_DIR="\$ROOT_DIR"/notes readonly TMP_DIR="\$ROOT_DIR"/tmp readonly CONFIG_FILE="\$ROOT_DIR/sns.conf" + +printf "%s\n" "\$PROD_STR" +printf "%s\n" "------------------" EOF diff --git a/src/includes/init_store.sns.sh b/src/includes/init_store.sns.sh index c58654b..40a4f0d 100644 --- a/src/includes/init_store.sns.sh +++ b/src/includes/init_store.sns.sh @@ -24,7 +24,7 @@ EOF chmod 600 "$CONFIG_FILE" -printf " - %s\n" "Rewrote Default Configuration" +printf "\n - %s\n" "Rewrote Default Configuration" if [ "$WILL_INIT" == "TRUE" ]; then printf " - %s %s\n" "Environment initialized in" "$ROOT_DIR" diff --git a/src/main/stage1.sns.sh b/src/main/stage1.sns.sh index b2ddef2..dc3e962 100644 --- a/src/main/stage1.sns.sh +++ b/src/main/stage1.sns.sh @@ -4,6 +4,7 @@ #============================================================================== # Stage 1: Read Configuration / Verify Integrity #============================================================================== + if [ -r "$CONFIG_FILE" ]; then source "$CONFIG_FILE" else @@ -24,14 +25,11 @@ fi if [ "$ENCRYPTION" == "TRUE" ]; then - PROD_STR="Simple Note System (Encryption Enabled)" if [ ! -d "$ROOT_DIR"/tmp ]; then mkdir -p "$ROOT_DIR"/tmp fi fi - echo "$PROD_STR, $VER_STR" - if [ -n "$ERR_NO_GPG" ]; then >&2 echo " Error: Encryption was specified, but GPG is not installed." exit 100 From 2b77e325ae7305cfc2a072fea495e2dd3ea223b4 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 00:40:36 -0600 Subject: [PATCH 12/14] Changed old argument parser to more sensible case statement; began work to recognize any path as a valid note path. --- src/main/stage2.sns.sh | 90 ++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/src/main/stage2.sns.sh b/src/main/stage2.sns.sh index 10cbc02..3ddb324 100644 --- a/src/main/stage2.sns.sh +++ b/src/main/stage2.sns.sh @@ -1,35 +1,57 @@ - #============================================================================== - # Stage 2: Argument Parsing - #============================================================================== - NAME="" - NOTEBOOK="" - SECTION="" - if [ -z "$1" ]; then help; exit 20 - else - ARGS=( "$@" ) - for ARG in "${ARGS[@]}"; do - if [ "$ARG" = "-c" ] || [ "$ARG" = "--create" ]; then CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-d" ] || [ "$ARG" = "--delete" ]; then DELETE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-e" ] || [ "$ARG" = "--edit" ]; then EDIT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-ce" ] || [ "$ARG" = "-ec" ]; then EDIT="TRUE"; CREATE="TRUE"; OP="TRUE" - elif [ "$ARG" = "-p" ] || [ "$ARG" = "--print" ]; then PRINT="TRUE"; OP="TRUE" - elif [ "$ARG" = "-l" ] || [ "$ARG" = "--list" ]; then LIST="TRUE"; OP="TRUE" - elif [ "$ARG" = "-h" ] || [ "$ARG" == "--help" ]; then help; exit 0 - elif [ "$ARG" = "-i" ] || [ "$ARG" == "--init" ]; then init_store; exit 0 - else - if [ -z "$NAME" ] && [ -n "$ARG" ]; then NAME="$ARG" - elif [ -z "$NOTEBOOK" ] && [ -n "$ARG" ]; then NOTEBOOK="$ARG" - elif [ -z "$SECTION" ] && [ -n "$ARG" ]; then SECTION="$ARG" - fi - fi - done - if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then - # If a note title was specified, but no notebook, and the list option - # was specified, assume that the detected note title is actually the - # name of a notebook - NOTEBOOK="$NAME" - NAME="" - fi - fi +#============================================================================== +# Stage 2: Argument Parsing +#============================================================================== +NOTE="" +if [ -z "$1" ]; then help; exit 20 +else +for ARG in "$@"; do + case "$ARG" in + -c|--create) + CREATE="TRUE" + OP="TRUE" + ;; + -d|--delete) + DELETE="TRUE" + OP="TRUE" + ;; + -e|--edit) + EDIT="TRUE" + OP="TRUE" + ;; + -ce|-ec) + CREATE="TRUE" + EDIT="TRUE" + OP="TRUE" + ;; + -l|--list) + LIST="TRUE" + OP="TRUE" + ;; + -p|--print) + PRINT="TRUE" + OP="TRUE" + ;; + -h|--help) + help + exit 0 + ;; + -i|--init-store) + init_store + exit 0 + ;; + *) + NOTE="$ARG" + break; + ;; + esac +done +if [ -n "$NAME" ] && [ -z "$NOTEBOOK" ] && [ -n "$LIST" ]; then + # If a note title was specified, but no notebook, and the list option + # was specified, assume that the detected note title is actually the + # name of a notebook + NOTEBOOK="$NAME" + NAME="" +fi +fi - # w_conf and help are called here to avoid excess stage 3 code. +# w_conf and help are called here to avoid excess stage 3 code. From faab86dff29faa19a296974177c9f750eb6cc942 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 00:55:29 -0600 Subject: [PATCH 13/14] Continued work on loosening note definition; added framework for color in errors. --- errors.ref | 6 ++-- header.sh | 3 ++ src/main/stage1.sns.sh | 63 +++++++++++++++++------------------ src/main/stage3.sns.sh | 74 +++++++++++++++++++++--------------------- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/errors.ref b/errors.ref index 28754c8..eb46e38 100644 --- a/errors.ref +++ b/errors.ref @@ -3,12 +3,12 @@ Error Code Reference General------------------------------------------------------------------------- ERR_NO_ARGS 10 No arguments were specified -ERR_NO_OP 20 -ERR_NO_NOTEBOOK 30 A required argument was not provided +ERR_NO_OP 20 No operation was specified +ERR_NO_NOTE 30 A required argument was not provided Encryption---------------------------------------------------------------------- ERR_NO_GPG 100 Encryption is enabled, but GPG is not installed ERR_NO_KEY 110 Encryption is enabled, but no recipient was specified Create-------------------------------------------------------------------------- -ERR_NOTE_EXiSTS 200 The specified note already exists \ No newline at end of file +ERR_NOTE_EXiSTS 200 The specified note already exists diff --git a/header.sh b/header.sh index 9ffc69b..63d8c87 100644 --- a/header.sh +++ b/header.sh @@ -19,6 +19,9 @@ readonly NOTES_DIR="\$ROOT_DIR"/notes readonly TMP_DIR="\$ROOT_DIR"/tmp readonly CONFIG_FILE="\$ROOT_DIR/sns.conf" +readonly RED_COLOR='\033[1;31m' +readonly RESET_COLOR='\033[0m' + printf "%s\n" "\$PROD_STR" printf "%s\n" "------------------" EOF diff --git a/src/main/stage1.sns.sh b/src/main/stage1.sns.sh index dc3e962..77d5008 100644 --- a/src/main/stage1.sns.sh +++ b/src/main/stage1.sns.sh @@ -1,39 +1,36 @@ - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - # Entry Point - #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - #============================================================================== - # Stage 1: Read Configuration / Verify Integrity - #============================================================================== +#============================================================================== +# Stage 1: Read Configuration / Verify Integrity +#============================================================================== - if [ -r "$CONFIG_FILE" ]; then - source "$CONFIG_FILE" - else - init_store - source "$CONFIG_FILE" - fi +if [ -r "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" +else + init_store + source "$CONFIG_FILE" +fi - verify_store +verify_store - if [ "$ENCRYPTION" == "TRUE" ]; then - if [ -z "$PUBKEY" ]; then - ERR_NO_KEY="TRUE" - ENCRYPTION="FALSE" - fi +if [ "$ENCRYPTION" == "TRUE" ]; then + if [ -z "$PUBKEY" ]; then + ERR_NO_KEY="TRUE" + ENCRYPTION="FALSE" + fi - command -v gpg >/dev/null 2>&1 ||\ - { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } - fi + command -v gpg >/dev/null 2>&1 ||\ + { ERR_NO_GPG="TRUE"; ENCRYPTION="FALSE"; } +fi - if [ "$ENCRYPTION" == "TRUE" ]; then - if [ ! -d "$ROOT_DIR"/tmp ]; then - mkdir -p "$ROOT_DIR"/tmp - fi - fi +if [ "$ENCRYPTION" == "TRUE" ]; then + if [ ! -d "$ROOT_DIR"/tmp ]; then + mkdir -p "$ROOT_DIR"/tmp + fi +fi - if [ -n "$ERR_NO_GPG" ]; then - >&2 echo " Error: Encryption was specified, but GPG is not installed." - exit 100 - elif [ -n "$ERR_NO_KEY" ]; then - >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " - exit 110 - fi +if [ -n "$ERR_NO_GPG" ]; then + >&2 echo " Error: Encryption was specified, but GPG is not installed." + exit 100 +elif [ -n "$ERR_NO_KEY" ]; then + >&2 echo " Error: No GPG recipient was provided in $CONFIG_FILE. " + exit 110 +fi diff --git a/src/main/stage3.sns.sh b/src/main/stage3.sns.sh index 673b184..3f813f0 100644 --- a/src/main/stage3.sns.sh +++ b/src/main/stage3.sns.sh @@ -1,42 +1,42 @@ - #============================================================================== - # Section: Actions / Stage 3 - #============================================================================== - # Default behavior - # If no operation was specified, print help and exit on ERR_NO_OP - if [ "$OP" != "TRUE" ]; then - help; exit 20 - fi - # All options not requiring at least a notebook to be specified have been dealt - # with; if one isn't specified, exit on ERR_NO_NOTEBOOK. - if [ -z "$NOTEBOOK" ]; then - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi - # List is the only option requiring only a notebook. - # If list isn't the selected option and no note name was specified, throw code 30. - if [ "$LIST" == TRUE ]; then - list - exit 0 - elif [ -z "$NAME" ]; then - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" - exit 30 - fi +#============================================================================== +# Section: Actions / Stage 3 +#============================================================================== +# Default behavior +# If no operation was specified, print help and exit on ERR_NO_OP + if [ "$OP" != "TRUE" ]; then + help; exit 20 + fi +# All options not requiring a note to be specified have been dealt +# with; if one isn't specified, exit on ERR_NO_NOTE. +if [ -z "$NOTE" ]; then + printf " $RED_COLOR!$RESET_COLOR %s\n" "No note specified." + exit 30 +fi +# List is the only option requiring only a notebook. +# If list isn't the selected option and no note name was specified, throw code 30. +if [ "$LIST" == TRUE ]; then + list + exit 0 +elif [ -z "$NAME" ]; then + printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + exit 30 +fi - NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" +NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" - if [ "$ENCRYPTION" == "TRUE" ]; then - SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename - readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" - else - readonly NOTE="$NOTE_DIR/$NAME.$EXT" - fi +if [ "$ENCRYPTION" == "TRUE" ]; then + SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename + readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" +else + readonly NOTE="$NOTE_DIR/$NAME.$EXT" +fi - if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi - if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi - if [ "$CREATE" == "TRUE" ]; then create; fi - if [ "$EDIT" == "TRUE" ]; then edit; fi +if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi +if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi +if [ "$CREATE" == "TRUE" ]; then create; fi +if [ "$EDIT" == "TRUE" ]; then edit; fi - #============================================================================== - # End Section: Actions / Stage 3 - #============================================================================== +#============================================================================== +# End Section: Actions / Stage 3 +#============================================================================== From 037fd9c2fa81e25ac37a236287ea7e1bcdc36e35 Mon Sep 17 00:00:00 2001 From: Jon-William Lewis Date: Mon, 15 Feb 2016 01:18:44 -0600 Subject: [PATCH 14/14] Made changes to create and delete functions reflecting recent design decisions --- src/includes/create.sns.sh | 30 +++++++++++++++++------------- src/includes/delete.sns.sh | 11 ++++++----- src/main/stage3.sns.sh | 17 ++++------------- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/includes/create.sns.sh b/src/includes/create.sns.sh index a0549ed..228bad0 100644 --- a/src/includes/create.sns.sh +++ b/src/includes/create.sns.sh @@ -1,18 +1,21 @@ function create(){ # Depends : p_header - # Requires: $NOTE, $NOTE_DIR, $NOTEBOOK, $SECTION, $NAME + # Requires: $NOTE, $NOTE_DIR, # Optional: $ENCRYPTION, $SESSION_ID, $TMP_DIR encrypt # Given a valid setup, create writes the standard note header as specified # by p_header, to $NOTE. # Refuse to overwrite a note - if [ -e "$NOTE" ]; then - printf "\nERROR: Note already exists\nHint: use -e to edit the note.\n" - exit 200 - # If the notebook doesn't exist, create it. - elif [ ! -d "$NOTE_DIR" ]; then - mkdir -p "$NOTE_DIR" - fi + if [ -e "$NOTE_DIR/$NOTE" ]; then + printf " $RED_COLOR!$RESET_COLOR %s\n\t%s\n"\ + "Note already exists"\ + "Hint: use -e to edit the note." + exit 200 + fi + + # If the note's notebook/section does not exist, + # create the appropriate folders. + mkdir -p "$NOTE_DIR"/$(dirname "$NOTE") # Write the standard note header if [ "$ENCRYPTION" == "TRUE" ]; then @@ -20,12 +23,13 @@ function create(){ p_header > "$TMP_NOTE" encrypt else - p_header > "$NOTE" + p_header > "$NOTE_DIR/$NOTE" fi - # Make sure the note exists, and inform the user. - if [ -e "$NOTE" ]; then - echo "Created note: $NOTEBOOK/$SECTION/$NAME." + # Make sure the note exists, and inform the user of the result. + if [ -e "$NOTE_DIR/$NOTE" ]; then + printf " - %s\n" "Created note: ${NOTE%.*}" else - printf "%s\n" "Something went wrong." + printf " $RED_COLOR!$RESET_COLOR%s\n"\ + "Something went wrong, and the note was not created." fi } diff --git a/src/includes/delete.sns.sh b/src/includes/delete.sns.sh index 696d9d1..a8aefed 100644 --- a/src/includes/delete.sns.sh +++ b/src/includes/delete.sns.sh @@ -1,10 +1,11 @@ function delete(){ - #Requires: $NOTE, $NOTEBOOK, $SECTION, $NAME + # Requires: $NOTE, $NOTE_DIR # Given a valid $NOTE, delete removes $NOTE from sns. - if [ -e "$NOTE" ]; then - rm "$NOTE" - printf "\n%s\n" "Deleted note: $NOTEBOOK/$SECTION/$NAME." + + if [ -e "$NOTE_DIR/$NOTE" ]; then + rm "$NOTE_DIR/$NOTE" + printf " - %s\n" "Deleted note: ${NOTE%.*}." else - printf "\n%s\n" "ERROR: Note $NOTEBOOK/$SECTION/$NAME does not exist." + printf " $RED_COLOR!$RESET_COLOR %s\n" "Note ${NOTE%.*} does not exist." fi } diff --git a/src/main/stage3.sns.sh b/src/main/stage3.sns.sh index 3f813f0..ca3c262 100644 --- a/src/main/stage3.sns.sh +++ b/src/main/stage3.sns.sh @@ -9,29 +9,20 @@ # All options not requiring a note to be specified have been dealt # with; if one isn't specified, exit on ERR_NO_NOTE. if [ -z "$NOTE" ]; then - printf " $RED_COLOR!$RESET_COLOR %s\n" "No note specified." - exit 30 -fi -# List is the only option requiring only a notebook. -# If list isn't the selected option and no note name was specified, throw code 30. -if [ "$LIST" == TRUE ]; then - list - exit 0 -elif [ -z "$NAME" ]; then - printf "\n%s\n %s\n" "ERROR: Insufficient arguments:" "Notebook not specified" + printf " $RED_COLOR!$RESET_COLOR %s\n" "No note specified." exit 30 fi NOTE_DIR="$NOTES_DIR"/"$NOTEBOOK"/"$SECTION" - if [ "$ENCRYPTION" == "TRUE" ]; then SESSION_ID="$RANDOM" #SESSION_ID later becomes the temporary filename - readonly NOTE="$NOTE_DIR/$NAME.$EXT.gpg" + readonly NOTE="$NOTE.$EXT.gpg" else - readonly NOTE="$NOTE_DIR/$NAME.$EXT" + readonly NOTE="$NOTE.$EXT" fi +if [ "$LIST" == "TRUE" ]; then list; exit 0; fi if [ "$PRINT" == "TRUE" ]; then print; exit 0; fi if [ "$DELETE" == "TRUE" ]; then delete; exit 0; fi if [ "$CREATE" == "TRUE" ]; then create; fi