notebook 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #!/bin/bash
  2. #
  3. # ABOUT:
  4. #
  5. # A notebook app for me to write stuff and keep it, or post it, or whatever.
  6. #
  7. # No "cloud" integration or synching: like a physical notebook, the stuff is
  8. # stored locally, but you can copy the notebook to another computer with Linux.
  9. #
  10. # Backups are your own responsibility: notebook will not do it for you.
  11. #
  12. # Like a notebook, the only security that I can offer is by isolation: your
  13. # notebook is only as secret as you can keep it hidden. I do so because getting
  14. # involved in cryptography to protect involves a much deeper knowledge and
  15. # investment.
  16. #
  17. # DEVELOPMENT ROADMAP:
  18. #
  19. # It would be good to implement some sort of rudimentary versioning system,
  20. # although git could be used just as easily. Perhaps a single "rollback?"
  21. #
  22. # Some sort of encryption would be good, although now I can't think much more
  23. # than just pgp encrypting the entire database and unlocking it on the fly.
  24. #
  25. # DEPENDENCIES:
  26. #
  27. # Notebook depends on sqlite3 to work.
  28. # vim is the standard editor chosen, but you can change the $EDITOR variable.
  29. # When encryption is enabled, you must have gpg correctly configured.
  30. #
  31. # LICENSING:
  32. #
  33. # This program is Free Software released under the terms of the GNU GPLv3
  34. #
  35. #-- configuration variables --
  36. EDITOR="vim"
  37. RECIPIENT="vesonoki@riseup.net"
  38. #-- dependency detection --
  39. if [[ -z $(which sqlite3) ]]
  40. then
  41. echo "Error: sqlite3 not found."
  42. echo "This program requires sqlite3 to work."
  43. echo "Please install it and try again."
  44. exit 1
  45. fi
  46. if [[ -z $(which gpg) ]]
  47. then
  48. echo "Error: gpg not found"
  49. echo "This program requires gpg to work."
  50. echo "Please install it and try again."
  51. exit 1
  52. fi
  53. if [[ -z "$RECIPIENT" ]]
  54. then
  55. echo "Error: no gpg recipient stated."
  56. echo "Please choose a recipient to encrypt the database to."
  57. echo "Note that this recipient must also be in your gpg keyring"
  58. exit 1
  59. fi
  60. if [[ ! -f book.db.gpg ]]
  61. then
  62. echo "Creating database for first time use..."
  63. sqlite3 book.db "CREATE TABLE articles (
  64. id INTEGER PRIMARY KEY AUTOINCREMENT,
  65. title TEXT,
  66. content TEXT
  67. )"
  68. echo "Encrypting database..."
  69. encrypt
  70. fi
  71. # Like the good textbook-based programmer, I sanitize my database inputs!
  72. sanitize() {
  73. # $1 is the token
  74. echo "$1" | sed 's/"/\"/g'
  75. }
  76. helper() {
  77. cat <<EOF
  78. $(basename $0) - a notebook application for writing articles and stuff.
  79. USAGE: $(basename $0) [OPTION]
  80. Options are:
  81. -h, --help: shows this help message
  82. -n, --new: creates a new article
  83. -s, --search: searches the notebook for text
  84. -v, --view: views an article
  85. Authored by kzimmermann - https://notabug.org/kzimmermann
  86. EOF
  87. }
  88. newentry() {
  89. local title
  90. printf "Enter a title for the new entry: "
  91. read title
  92. title=$(sanitize "$title")
  93. "$EDITOR" -c 'set linebreak' -c 'set wrap' .tempfile
  94. cat .tempfile | sed 's/"/\&quot;/g' > .tempfile2
  95. decrypt
  96. sqlite3 book.db <<EOF
  97. INSERT INTO articles (title, content)
  98. VALUES ("$title", "$(cat .tempfile2)");
  99. EOF
  100. rm .tempfile .tempfile2
  101. encrypt
  102. }
  103. search() {
  104. local token
  105. printf "Enter a string to search the database: "
  106. read token
  107. decrypt
  108. echo "Found the following articles matching:"
  109. token=$(sanitize "$token")
  110. results=$(sqlite3 book.db <<EOF
  111. SELECT id, title FROM articles
  112. WHERE
  113. title LIKE "%$token%" OR
  114. content LIKE "%$token%"
  115. ;
  116. EOF
  117. )
  118. for item in "$results"
  119. do
  120. echo "$item" | sed 's/\&quot;/"/g'
  121. done
  122. encrypt
  123. }
  124. view() {
  125. local token
  126. local article
  127. printf "Enter an ID to view an article: "
  128. read token
  129. decrypt
  130. token=$(sanitize "$token")
  131. article=$(sqlite3 book.db <<EOF
  132. SELECT content FROM articles WHERE id="$token";
  133. EOF
  134. )
  135. if [[ -n "$article" ]]
  136. then
  137. # this ugly hack seems to be the only way to wrap words in less...
  138. echo "$article" | sed 's/\&quot;/"/g' |
  139. fold -s --width="$(tput cols)" | less
  140. else
  141. echo "No article found with that ID."
  142. fi
  143. encrypt
  144. }
  145. encrypt() {
  146. if [[ -z "$RECIPIENT" ]]
  147. then
  148. echo "No recipient found to encrypt the database to."
  149. exit 1
  150. fi
  151. gpg --encrypt -r "$RECIPIENT" book.db
  152. shred -u book.db
  153. rm .book_bak.db.gpg
  154. }
  155. decrypt() {
  156. # Are we running in encrypted mode?
  157. if [[ -f book.db.gpg ]]
  158. then
  159. gpg --decrypt book.db.gpg > book.db
  160. mv book.db.gpg .book_bak.db.gpg
  161. fi
  162. }
  163. if [[ -z "$1" ]]
  164. then
  165. helper
  166. exit 1
  167. fi
  168. while [[ -n "$1" ]]
  169. do
  170. case "$1" in
  171. "-h" | "--help" )
  172. helper
  173. exit 0
  174. ;;
  175. "-n" | "--new" )
  176. newentry
  177. exit 0
  178. ;;
  179. "-s" | "--search" )
  180. search
  181. exit 0
  182. ;;
  183. "-v" | "--view" )
  184. view
  185. exit 0
  186. ;;
  187. * )
  188. echo "Error: unknown option '$1'"
  189. helper
  190. exit 1
  191. ;;
  192. esac
  193. done