Org B64: Base64-encode files into Org for easy sharing (Emacs package)
Below you find the latest version of (1) the package's README and (2) its main source file.
For the git repository and issues tracker, see the project's page on sr.ht.
For more packages, see Software.
README.org
Introduction
What?
With Org B64 you can easily Base64-encode files into an org file. This makes possible the easy embedding as plain text of binaries such as images, audio, and compressed files for later extraction or sharing with friends.
This is similar to what happens when you attach a file to an email: the file is encoded as “plain text” and added to the message, which is recognized by the recipient’s email program and shown as an attachment. When you save the attachment, what the email program does is decode that text and write it to your disk.
Likewise, Org B64 Base64-encodes one or more files of your choice and add them as “example” special Org blocks. It also adds a function that can be used to decode one or more of these blocks, save them to disk as files, and verify that they match what is expected (technically-speaking, it matches the saved files against their provided SHA256 hashes).
What for?
When would you want this? Some cases:
- To share with another Org mode user.
- When you can only store or send one file.
- When you prefer to store data as plain text.
- When some system you use restricts filetypes.
If you end up using this package and find it useful, please let me know, and I might add the example to the list of use cases.
Usage, and what it looks like
You can either bind keys or use M-x org-b64-add-files
whenever you want to add files to an org buffer.
Adding one file
When you run this command and choose one file, this is what happens:
Pressing C-c C-c over a #+call line will save the file in this folder: ~/org-b64/. #+call: org-b64-save-file(d="~/org-b64/", f="report.pdf", f64=report.pdf.b64) #+name: org-b64-save-file #+begin_src bash :var d="", f="", f64="", sha=sha256... #+end_src #+name: sha256 #+begin_example... #+end_example #+name: report.pdf.b64 #+begin_example... #+end_example
What are those?
- Inside the
org-b64-save-file
block there’s a Bash function. It’s called by the#+call
line. - Inside the
sha256
block you find the SHA256 hashes of the files. It’s used to verify the files’ integrity after you saved them. It helps prevent corruption, because a decoded and saved file should have the same SHA256 value as the file that was once encoded by you or by whomever sent you these files. - Inside the other blocks you find the base64-encoded files. These are the actual data.
At the moment, you can choose between Bash (default) and Emacs Lisp for org-b64-save-file block. The former requires that the recipient have Bash installed. The latter requires that the recipient’s Emacs have the f.el
library. It’s possible that future versions of this package may offer more options. Or perhaps it may simplify and unify it.
A note on speed
The two Bash versions of the decoding function (this one and the “expert” one) currently offer considerably faster decoding than the Emacs Lisp one. This is already noticeable with files of a few megabytes. While testing, I successfully added and extracted a 30MB media file with both Bash versions — but the Elisp one choked at this size.
If you know why the Lisp version is performing slower and how to improve it, please suggest.
Adding many files
When you run this command and choose one directory, this is what happens if that directory’s direct contents are three PDF files:
Pressing C-c C-c over a #+call line will save the file in this folder: ~/org-b64/. C-c C-v C-s evaluates the subtree. C-c C-v C-b evaluates the buffer. Use one to save many at once. If you then press undo (usually C-/), the results messages disappear, but you keep the effects. #+call: org-b64-save-file(d="~/org-b64/", f="report1.pdf", f64=report1.pdf.b64) #+call: org-b64-save-file(d="~/org-b64/", f="report2.pdf", f64=report2.pdf.b64) #+call: org-b64-save-file(d="~/org-b64/", f="report3.pdf", f64=report3.pdf.b64) #+name: org-b64-save-file #+begin_src bash :var d="", f="", f64="", sha=sha256... #+end_src #+name: sha256 #+begin_example... #+end_example #+name: report1.pdf.b64 #+begin_example... #+end_example #+name: report2.pdf.b64 #+begin_example... #+end_example #+name: report3.pdf.b64 #+begin_example... #+end_example
It’s the same idea, but with more files.
You can also use it non-interactively
This:
(org-b64-add-files nil "~/events/lastevent/pics/" "~/Desktop/event-pictures/")
will encode all files that are (non-recursively) found under the first directory in your disk and will insert at point in the current Org buffer, together with the default function (because of the nil
). The extraction function will point extraction to the second directory above, presumably because you want to suggest to your recipient that this one be used. If it doesn’t exist in the machine it is extracted to, it will be created.
Adding files in “expert mode”
There’s a separate command that you can use to add files: M-x org-b64-add-files-expert
.
It also defaults to Bash, which in fact is (currently) the only choice. The difference is that the function is much simplified and assumes that no explanation is needed: the recipients know what they’re doing, will look at the code before executing, will modify paths and names as desired, etc. Instead of the separate call lines, it creates a single code block that saves everything (but which the person can delete some lines of for selection, etc).
This version is simpler and looks cleaner — but has last safeguards. No detection whether a file already exists at the saving location (to avoid overwriting), for example.
You may want to choose this one either if:
- it’s for your own use and you know your way around code; you know what you’re doing, or
- you know that your recipients have Bash and know what they’re doing.
This is what it looks like when you run that command and choose the same directory. Unlike the previous ones, here I expand the org-b64-save-files
block to show its simplicity.
~/org-b64/ #+name: org-b64-save-files #+header: :var f00=report1.pdf.b64 :var f01=report2.pdf.b64 :var f02=report3.pdf.b64 #+begin_src bash :results table :var sha=sha256 mkdir -p ~/org-b64/ && cd "$_" || exit <<< "$f00" base64 -d > "report1.pdf" <<< "$f01" base64 -d > "report2.pdf" <<< "$f02" base64 -d > "report3.pdf" <<< "$sha" sha256sum -c | tr -d : #+end_src #+name: sha256 #+begin_example... #+end_example #+name: report1.pdf.b64 #+begin_example... #+end_example #+name: report2.pdf.b64 #+begin_example... #+end_example #+name: report3.pdf.b64 #+begin_example... #+end_example
In “expert” mode, there’s a single src block that saves them all. Here, the results of SHA256 verification show up on a table after execution. Like this:
#+results: org-b64-save-files | report1.pdf | OK | | report2.pdf | OK | | report3.pdf | OK |
If a saved file doesn’t match the expected for some reason, you should see something like this:
#+results: org-b64-save-files | report1.pdf | FAILED | | report2.pdf | OK | | report3.pdf | OK |
Installation
See my page Software for the most up-to-date instructions on how to download and install any of my Emacs packages.
Having downloaded and installed the package and its dependencies, adapt the configurations below to your init.el
file.
(use-package org-b64 :commands (org-b64-add-files org-b64-add-files-expert) :bind (:map org-mode-map ("C-c 6" . org-b64-add-files) ("C-c 4" . org-b64-add-files-expert)))
These keys are only suggestions. Use what suits you best.
Alternatively, if you don’t have ‘use-package’:
(require 'org-b64)
and bind keys accordingly.
Security
Org B64 has not yet been thoroughly tested by others. I did my best to make it robust against data losses, but GPL’s warnings apply: you use it at your own risk.
Since it deals with reading and writing files (which, in case of bugs, could cause loss of data), test it well and exercise some caution. If you experience problems, please do report so that critical bugs can be fixed.
Limitations
The current version has limitations. Here are some that I noticed:
- It is certain to break with “misbehaved” filenames. The current version assumes you will add nice directories and files that have no spaces, quotes, newlines, or semicolons in it. To say nothing of parentheses. This may be improved in the future.
- You may find memory problems when adding too many files or files that are too large. This is because Org tries to syntax highlight and/or hide the encoded data. I don’t know what the actual limit is, and it will depend on your machine. Disabling
font-lock-mode
while processing a large file may help a bit.
Contributing
See my page Software for information about how to contribute to any of my Emacs packages.
License
This project follows the REUSE Specification (FAQ), which in turn is built upon SPDX.
Therefore, license and copyright information can be found in:
- each file's comment header, or
- an adjacent file of the same name with the additional extension
.license
, or - the
.reuse/dep5
file
The full text of the licenses can be found in the LICENSES
subdirectory.
org-b64.el
Structure
;;; org-b64.el --- Base64-encode files into Org for easy sharing -*- lexical-binding: t -*- ;;; Commentary: ;;;; For all the details, please do see the README ;;; Acknowledgments: ;;; Code: ;;;; Libraries ;;;; Package metadata ;;;; Customizable variables ;;;; Other variables ;;;; Functions ;;;;; Borrowed ;;;;; Auxiliary ;;;;; Core ;;;; Wrapping up ;;; org-b64.el ends here
Contents
;;; org-b64.el --- Base64-encode files into Org for easy sharing -*- lexical-binding: t -*- ;; SPDX-FileCopyrightText: © flandrew <https://keyoxide.org/191F5B3E212EF1E515C19918AF32B9A5C1CCCB2D> ;; SPDX-License-Identifier: GPL-3.0-or-later ;;--------------------------------------------------------------------------- ;; Author: flandrew ;; Created: 2021-06-09 ;; Version: 0.3.6-git ;; Homepage: <https://flandrew.srht.site/listful/software.html> ;; Keywords: files, outlines ;; Package-Requires: ((emacs "25.1")) ;;--------------------------------------------------------------------------- ;; This file is part of Org B64, which is NOT part of GNU Emacs. ;; This program is free software: you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by the Free ;; Software Foundation, either version 3 of the License, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, but WITHOUT ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;; FITNESS FOR A PARTICULAR PURPOSE. For more details, see the full license at ;; either LICENSES/GPL-3.0-or-later.txt or <https://www.gnu.org/licenses/>. ;;; Commentary: ;; ;; With Org B64 you can easily Base64-encode files into an org file. This ;; makes possible the easy embedding as plain text of binaries such as images, ;; audio, and compressed files for later extraction or sharing with friends. ;; ;;;; For all the details, please do see the README ;; ;; Open it easily with any of the below: ;; (find-file-read-only "README.org") <--- C-x C-e here¹, or ;; (find-file-read-only-other-frame "README.org") <--- C-x C-e here¹, or ;; (find-file-read-only-other-window "README.org") <--- C-x C-e here¹ ;; ;; or read it online: ;; <https://flandrew.srht.site/listful/sw-emacs-org-b64.html> ;; ;; ¹ or the key that ‘eval-last-sexp’ is bound to, if not C-x C-e. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Acknowledgments: ;; ;; Function ‘org-b64--f-read-bytes’ was copied verbatim from f.el's ;; ‘f-read-bytes’, so that there would be no external dependencies for ;; *creating* org-b64 blocks. ;; ;; About f.el: ;; SPDX-FileCopyrightText: © 2013 Johan Andersson ;; SPDX-License-Identifier: GPL-3.0-or-later ;; Author: Johan Andersson ;; Homepage: <https://github.com/rejeep/f.el> ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Code: ;;;; Libraries (require 'subr-x) ; ‘string-join’ (require 'seq) ; ‘seq-position’ (require 'org) ; ‘org-previous-block’, ‘org-cycle’ (require 'org-macs) ; ‘org-with-wide-buffer’ (require 'lisp-mnt) ; ‘lm-summary’, ‘lm-version’, ‘lm-homepage’ ;;;; Package metadata (defconst org-b64--name "Org B64") (defconst org-b64--dot-el (format "%s.el" (file-name-sans-extension (eval-and-compile (or load-file-name buffer-file-name))))) (defconst org-b64--readme-org (expand-file-name "README.org" (file-name-directory org-b64--dot-el))) (defconst org-b64--summary (lm-summary org-b64--dot-el)) (defconst org-b64--version (lm-version org-b64--dot-el)) (defconst org-b64--homepage (lm-homepage org-b64--dot-el)) ;;;; Customizable variables (defgroup org-b64 nil (format "%s." org-b64--summary) :group 'files :group 'org :link '(emacs-library-link :tag "Lisp file" "org-b64.el") :link `(file-link :tag "README.org" ,org-b64--readme-org) :link `(url-link :tag "Homepage" ,org-b64--homepage)) (defcustom org-b64-hide-blocks-on-startup t "When on (non-nil), add a ‘#+startup’ line to make blocks show up folded." :type 'boolean :group 'org-b64) (defcustom org-b64-add-instruction-p t "Whether to ever add instruction on how to batch-save." :type 'boolean :group 'org-b64) (defcustom org-b64-min-files-to-add-instruction 3 "Minimum number of files needed to add instruction on how to batch-save. Only considered when ‘org-b64-add-instruction-p’ is non-nil." :type 'integer :group 'org-b64) (defcustom org-b64-rec-path "~/org-b64/" "The suggested path for files to be decoded+saved later. This is what your recipients will see, and where it will be saved, if they don’t change it." :type 'directory :group 'org-b64) (defcustom org-b64-save-file-function :bash "Choice of function to use for the decoding block. Bash: requires that the recipients have Bash in their system. Elisp: requires that the recipients have the f.el library in their Emacs." :type '(choice (const :tag "Bash" :bash) (const :tag "Elisp" :elisp)) :group 'org-b64) ;;;; Other variables (defvar org-b64-save-file--elisp-b64d " KGFuZCAob3JnLXN0cmluZy1udy1wIGQpCiAgICAgKG9yZy1zdHJpbmctbnctcCBmKQogICAgIChv cmctc3RyaW5nLW53LXAgKHN1YnN0cmluZyBmNjQgMCAzKSkgOyBtdWNoIGZhc3RlcgogICAgIChp ZiAobm90IChyZXF1aXJlICdmIG5pbCB0KSkKICAgICAgICAgKG1lc3NhZ2UgIldlIG5lZWQgdGhl IGYuZWwgbGlicmFyeSIpCiAgICAgICAobGV0ICgoZmlsZSAoY29uY2F0IGQgZikpCiAgICAgICAg ICAgICAoZXJyLW1zZyAiYnV0IGRvZXMgbm90IHNlZW0gdG8gbWF0Y2ggdGhlIG9yaWdpbmFsLiBW ZXJpZnkuIikpCiAgICAgICAgICh3aGVuIChpZiAoZmlsZS1yZWd1bGFyLXAgZmlsZSkKICAgICAg ICAgICAgICAgICAgICh5ZXMtb3Itbm8tcCAoY29uY2F0ICJGaWxlICIgZiAiIGV4aXN0cy4gT3Zl cndyaXRlPyIpKQogICAgICAgICAgICAgICAgIHQpCiAgICAgICAgICAgKG1rZGlyIGQgIi1wIikK ICAgICAgICAgICAoZi13cml0ZS1ieXRlcyAoYmFzZTY0LWRlY29kZS1zdHJpbmcgZjY0KSBmaWxl KQogICAgICAgICAgIChpZiAobGV0ICgoY2FzZS1mb2xkLXNlYXJjaCAnaWdub3JlLWNhc2UpCiAg ICAgICAgICAgICAgICAgICAgIChyZSAocmVnZXhwLXF1b3RlIChzZWN1cmUtaGFzaCAnc2hhMjU2 IChmLXJlYWQgZmlsZSkpKSkpCiAgICAgICAgICAgICAgICAgKHN0cmluZy1tYXRjaC1wIHJlIHNo YSkpCiAgICAgICAgICAgICAgIChtZXNzYWdlICJGaWxlICVzIGhhcyBiZWVuIHNhdmVkIGNvcnJl Y3RseS4iIGYpCiAgICAgICAgICAgICAobWVzc2FnZSAiRmlsZSAlcyBoYXMgYmVlbiBzYXZlZCwg JXMiIGYgZXJyLW1zZykpKSkpKQo=" "Elisp function block to be inserted. It will later be used to decode and write files when the user wants it. Parameters ‘d’, ‘f’ and ‘f64’ will be passed by the ‘#+call:’ line. It’s base-64’d here for convenience: it preserves indentation. Please do decode and verify it with (org-b64--verify-save-file-function :elisp).") (defvar org-b64-save-file--bash-b64d " KFtbIC16ICIkZCIgXV0gfHwgW1sgLXogIiRmIiBdXSB8fCBbWyAteiAiJGY2NCIgXV0pICYmIGV4 aXQKZGlyPSIkKHNlZCAic3xefnwkSE9NRXwiIDw8PCAiJGQiKSI7IGZkPSIkZGlyLyRmIgpta2Rp ciAtcCAiJGRpciIgJiYgY2QgIiRkaXIiIHx8IGV4aXQKW1sgLWYgIiRmZCIgXV0gJiYgeyBlY2hv ICJGaWxlICRmIGV4aXN0cyBhbmQgd2FzIE5PVCBvdmVyd3JpdHRlbiI7IGV4aXQgO30gfHwKICAg IHsgYmFzZTY0IC1kID4gIiRmZCIgPDw8ICIkZjY0IiAmJiBlY2hvIC1uICJGaWxlICRmIGhhcyBi ZWVuIHNhdmVkICIKICAgICAgcz0iJChzaGEyNTZzdW0gIiRmIikiCiAgICAgIFxncmVwIC1xICIk e3MvLyAqL30gICokZiIgPDw8ICIkc2hhIiAmJgogICAgICAgICAgZWNobyAiY29ycmVjdGx5LiIg fHwKICAgICAgICAgIGVjaG8gImJ1dCBkb2VzIG5vdCBzZWVtIHRvIG1hdGNoIHRoZSBvcmlnaW5h bC4gRXJyb3I/IFZlcmlmeS4iIDt9Cg==" "Bash function block to be inserted. It will later be used to decode and write files when the user wants it. Parameters ‘d’, ‘f’ and ‘f64’ will be passed by the ‘#+call:’ line. It’s base-64’d here for convenience: it avoids multiple escapings. Please do decode and verify it with (org-b64--verify-save-file-function :bash).") ;;;; Functions ;;;;; Borrowed ;; Copied verbatim from the f.el library. Added "org-b64-" prefix. (defun org-b64--f-read-bytes (path) "Read binary data from PATH. Return the binary data as unibyte string." (with-temp-buffer (set-buffer-multibyte nil) (setq buffer-file-coding-system 'binary) (insert-file-contents-literally path) (buffer-substring-no-properties (point-min) (point-max)))) ;;;;; Auxiliary (defun org-b64--verify-save-file-function (opt) "Decodes a save-file-function function for verification and editing. Options OPT for FUN are: ‘:bash’ and ‘:elisp’." (let* ((mode (pcase opt (:bash 'shell-script-mode) (:elisp 'emacs-lisp-mode))) (bfb (pcase opt (:bash 'org-b64-save-file--bash-b64d) (:elisp 'org-b64-save-file--elisp-b64d))) (buf (get-buffer-create (concat "*" (symbol-name bfb) "*"))) (dec (base64-decode-string (symbol-value bfb)))) (switch-to-buffer buf) (funcall mode) (insert dec))) (defun org-b64--only-files (directory &optional full) "Given a DIRECTORY, return list with its regular files. Non-recursive. If FULL is non-nil, return absolute filenames instead of relative." (remove 'nil (mapcar (lambda (elt) (when (file-regular-p elt) elt)) (directory-files directory full)))) (defun org-b64--listify-and-expand-filenames (path) "Given a PATH, return a list of all valid regular files. If PATH is a file, make a list with it. If a directory, make a list of all regular files in it, non-recursively. If it doesn’t exist, return error. An empty string is the same as ‘default-directory’, so it returns a list of all files in it." (or (file-exists-p path) (user-error "File or directory %s doesn’t exist" path)) (cond ((file-directory-p path) (org-b64--only-files path t)) ((file-regular-p path) (list (expand-file-name path))) (t (error "Not a file or directory: %s" path)))) (defun org-b64--select-src-files (path) "Given a PATH, return a list with selected files." (org-b64--listify-and-expand-filenames (or path (read-file-name "File or directory to base64-encode: " default-directory) (user-error "No file or directory was selected")))) (defun org-b64--hide-last-block () "Collapse the last block inserted. You can toggle a block’s visibility with \\[org-cycle]." (org-previous-block 1) (org-cycle) (next-logical-line)) (defun org-b64--stringer (src-files str-format separator) "Make strings for block headers and contents. You need SRC-FILES, a STR-FORMAT and a SEPARATOR." (string-join (mapcar (lambda (f) (let ((fname (file-name-nondirectory f))) (format str-format (seq-position src-files f) fname))) src-files) separator)) (defun org-b64--make-hideblocks-line () "Add a line to hide blocks’ contents, so that they show up nicely folded." (when org-b64-hide-blocks-on-startup (insert "#+startup: hideblocks\n\n"))) (defun org-b64--make-bash-expert-block (src-files rec-path) "Given a list of full-path SRC-FILES, create Bash \"expert\" block. REC-PATH is the path suggested for the recipient." (insert "\n#+name: org-b64-save-files" "\n#+header: " (org-b64--stringer src-files ":var f%.2d=%s.b64" " ") "\n#+begin_src bash :results table :var sha=sha256" "\nmkdir -p " rec-path " && cd \"$_\" || exit\n" (org-b64--stringer src-files "<<< \"$f%.2d\" base64 -d > \"%s\"" "\n") "\n<<< \"$sha\" sha256sum -c | tr -d :" "\n#+end_src\n") (org-b64--hide-last-block)) (defun org-b64--make-sha256-list-block (src-files) "Given a list of full-path SRC-FILES, create a block with their sha256." (insert "\n#+name: sha256" "\n#+begin_example\n" (string-join (mapcar (lambda (f) (shell-command-to-string (concat "sha256sum \"" f "\" | " "sed 's| .*/| |'"))) src-files)) "#+end_example\n") (org-b64--hide-last-block)) (defun org-b64--make-encoded-blocks (src-files) "Given a list of full-path SRC-FILES, create base64-encoded blocks." (dolist (file src-files) (insert "\n#+name: " (file-name-nondirectory file) ".b64" "\n#+begin_example\n" (base64-encode-string (org-b64--f-read-bytes file)) "\n#+end_example\n") (org-b64--hide-last-block))) (defun org-b64--make-instructions (src-files rec-path) "Given a list of full-path SRC-FILES, create instructions text. REC-PATH is the path suggested for the recipient." (insert "Pressing =C-c C-c= over a =#+call= line will save the file " "in this folder: [[" rec-path "]].\n") (and org-b64-add-instruction-p (>= (length src-files) org-b64-min-files-to-add-instruction) (insert "=C-c C-v C-s= evaluates the subtree. " "=C-c C-v C-b= evaluates the buffer. " "Use one to save many at once.\n" "If you then press undo (usually =C-/=), the results messages " "disappear, but you keep the effects.\n")) (insert "\n")) (defun org-b64--make-call-lines (src-files rec-path) "Given a list of full-path SRC-FILES, create #+call: lines. REC-PATH is the path suggested for the recipient." (dolist (file src-files) (let ((fname (file-name-nondirectory file))) (insert "#+call: org-b64-save-file(" "d=\"" rec-path "\", " "f=\"" fname "\", " "f64=" fname ".b64)\n")))) (defun org-b64--make-src-block (dec-fun) "Given a chosen decoding function (DEC-FUN), create src block." (insert "\n#+name: org-b64-save-file\n" "#+header: :var d=\"\" :var f=\"\" :var f64=\"\" :var sha=sha256\n" ;; remove the ":" "#+begin_src " (substring (symbol-name dec-fun) 1) "\n" (base64-decode-string (pcase dec-fun (:bash org-b64-save-file--bash-b64d) (:elisp org-b64-save-file--elisp-b64d) (_ (error "Function missing")))) "#+end_src\n") (org-b64--hide-last-block)) ;;;;; Core ;;;###autoload (defun org-b64-add-files (&optional dec-fun src-path rec-path) "Base64-encode files and insert into the current org buffer. Read a source path from the minibuffer; then create org-babel blocks which, when executed, save the corresponding files in the recipient’s computer. The saved files’ SHA256 hashes are verified against the provided ones. To save a file, press \\[org-ctrl-c-ctrl-c] on the block. DEC-FUN is the decoding function to be used. When nil, it defaults to ‘org-b64-save-file-function’. Note that this refers to the function that will be inserted and shown to the recipient. With one \\[universal-argument], it uses the other function (Elisp if the default is Bash, and vice-versa). SRC-PATH is a file or directory to encode. If you provide a directory, all regular files in it (non-recursive) will be encoded individually. If nil, you’ll be prompted to choose. REC-PATH is the suggested path for files to be decoded+saved later. This is what your recipient will see, and where it would be saved, if they don’t change it. If nil, it uses the value from ‘org-b64-rec-path’." (interactive "P") (setq dec-fun (pcase dec-fun ('() org-b64-save-file-function) ('(4) (if (equal :bash org-b64-save-file-function) :elisp :bash)) (_ dec-fun)) rec-path (file-name-as-directory (or rec-path org-b64-rec-path))) (let ((src-files (org-b64--select-src-files src-path))) ;; 0. Instructions :: how the recipient can save it. ;; 1. The #+call :: calls function with encoded data’s name as argument. ;; 2. The #+src bash|elisp :: function used to decode and write the file. ;; 3. An #+example block :: sha256 list ;; 4. More #+example blocks :: base-64’d data (org-with-wide-buffer (org-b64--make-hideblocks-line) (org-b64--make-instructions src-files rec-path) (org-b64--make-call-lines src-files rec-path) (org-b64--make-src-block dec-fun) (org-b64--make-sha256-list-block src-files) (org-b64--make-encoded-blocks src-files)))) ;;;###autoload (defun org-b64-add-files-expert (&optional _ src-path rec-path) "Make Base64 blocks from files. No warnings, no frills. Less safeguards, but cleaner. *Use responsibly*. It assumes that no explanation is needed; that the recipients know what they’re doing; that they will look at the code before executing; that they will modify paths and names as desired; etc. To use this function, you need Bash. The recipient, too, needs Bash to decode. See ‘org-b64-add-files’ for explanation on SRC-PATH and REC-PATH." (interactive) (setq rec-path (file-name-as-directory (or rec-path org-b64-rec-path))) (let ((src-files (org-b64--select-src-files src-path))) ;; 1. The #+src bash block :: decode and save files ;; 2. An #+example block :: sha256 list ;; 3. More #+example blocks :: base-64’d data (org-with-wide-buffer (org-b64--make-hideblocks-line) (insert "[[" rec-path "]]\n") ; link to destination directory (org-b64--make-bash-expert-block src-files rec-path) (org-b64--make-sha256-list-block src-files) (org-b64--make-encoded-blocks src-files)))) ;;;; Wrapping up (provide 'org-b64) ;; Local Variables: ;; coding: utf-8 ;; indent-tabs-mode: nil ;; sentence-end-double-space: nil ;; outline-regexp: ";;;;* " ;; End: ;;; org-b64.el ends here