emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [tip] Create and Insert a public Nextcloud/Owncloud link
@ 2022-10-08 14:29 Juan Manuel Macías
  2022-10-09  3:32 ` Max Nikulin
  0 siblings, 1 reply; 3+ messages in thread
From: Juan Manuel Macías @ 2022-10-08 14:29 UTC (permalink / raw)
  To: orgmode

Hi all,

One of the few things that I miss from a desktop environment like Gnome
Shell or KDE Plasma (currently I use EXWM), is the good integration
these environments had with Nextcloud, as I am a heavy user of
Nextcloud. Many times I need to create and share a public link to a file
in my local folder. In the Nextcloud forum I learned how it can be done
from the command line using curl, so starting from that, it wasn’t very
difficult to write this function in Elisp to insert a public link at
point. It can be inserted in two ways: literally or as an Org bracket
link, with description.

For the function to work we must have: a) a folder within our local
Nextcloud directory dedicated exclusively to public files; b) a line
with our personal data in the ~/.authinfo file. Assuming, for example,
that we use a third-party Nextcloud service like Disroot, the necessary
line in authinfo would be:

machine cloud.disroot.org login <my-user-name> password <my-password>

And let’s go with the function. Before I have defined these three
variables:

┌────
│ (defvar nextcloud-url "https://cloud.disroot.org")
│ (defvar nextcloud-public-folder "~/disroot/Public/")
│ (defvar nextcloud-public-folder-name "Public")
└────

And the function itself (caveat: the function is not asynchronous):

┌────
│ (defun insert-nextcloud-link ()
│   (interactive)
│   (let* ((file-name (read-file-name "File: "
│ 				    nextcloud-public-folder))
│ 	 (file (if (directory-name-p
│ 		    file-name)
│ 		   (replace-regexp-in-string
│ 		    (expand-file-name
│ 		     nextcloud-public-folder)
│ 		    ""
│ 		    file-name)
│ 		 (file-name-nondirectory file-name)))
│ 	 (desc
│ 	  (read-from-minibuffer
│ 	   "Link description (enter = no description): "))
│ 	 (auth
│ 	  (nth 0
│ 	       (auth-source-search
│ 		:host "cloud.disroot.org"
│ 		:requires '(user secret))))
│ 	 (my-username (plist-get auth :user))
│ 	 (my-passwd (funcall (plist-get auth :secret)))
│ 	 (result-raw (shell-command-to-string
│ 		      (concat "curl -u "
│ 			      "\""
│ 			      my-username
│ 			      ":"
│ 			      my-passwd
│ 			      "\""
│ 			      " -H \"OCS-APIRequest: true\" -X POST "
│ 			      nextcloud-url
│ 			      "/ocs/v1.php/apps/files_sharing/api/v1/shares -d path="
│ 			      "\""
│ 			      nextcloud-public-folder-name
│ 			      "/"
│ 			      file
│ 			      "\""
│ 			      " -d shareType=3"
│ 			      " -d permissions=1")))
│ 	 (result (with-temp-buffer
│ 		   (insert result-raw)
│ 		   (goto-char (point-min))
│ 		   (re-search-forward "<url>" nil t)
│ 		   (let ((desde (point)))
│ 		     (re-search-forward "<" nil t)
│ 		     (narrow-to-region desde (- (point) 1))
│ 		     (buffer-string)))))
│     (if (string= desc "")
│ 	(insert result)
│       (insert (format "[[%s][%s]]" result desc)))))
└────

Best regards,

Juan Manuel 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [tip] Create and Insert a public Nextcloud/Owncloud link
  2022-10-08 14:29 [tip] Create and Insert a public Nextcloud/Owncloud link Juan Manuel Macías
@ 2022-10-09  3:32 ` Max Nikulin
  2022-10-09 12:21   ` Juan Manuel Macías
  0 siblings, 1 reply; 3+ messages in thread
From: Max Nikulin @ 2022-10-09  3:32 UTC (permalink / raw)
  To: emacs-orgmode

On 08/10/2022 21:29, Juan Manuel Macías wrote:
> 
> Many times I need to create and share a public link to a file
> in my local folder. In the Nextcloud forum I learned how it can be done
> from the command line using curl,
..
> │ 	 (result-raw (shell-command-to-string
> │ 		      (concat "curl -u "
> │ 			      "\""
> │ 			      my-username
> │ 			      ":"
> │ 			      my-passwd
> │ 			      "\""

Juan Manuel, your function is a nice proof of concept, but posting such 
code you are responsible for users who may try to use it verbatim having 
less experience with elisp.

Use at least `shell-quote-argument' (though it docstring has a link to 
info "(elisp)Security Considerations"). Just adding quote characters is 
unsafe. You may avoid non-alphanumeric characters in passwords and file 
names for good reasons, but for other users a quote character may 
dramatically change the executed command.

When TRAMP support is not necessary, arguments should be passed to 
external binary as a list without intermediate shell command. I know, 
Emacs does not have a convenience function with such calling convention 
similar to `shell-command-to-string'.

I am almost sure that Emacs has a package to send HTTP POST requests 
directly from elisp. Unsure it has convenient enough API (reasonable 
default timeouts, etc.), but it should be safer for working with 
peculiar file names and passwords stuffed with characters having special 
meaning in shell. I admit that the code would be more verbose. It may 
save you time for recovering you system from damage caused by unexpected 
interpretation of a shell command.




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [tip] Create and Insert a public Nextcloud/Owncloud link
  2022-10-09  3:32 ` Max Nikulin
@ 2022-10-09 12:21   ` Juan Manuel Macías
  0 siblings, 0 replies; 3+ messages in thread
From: Juan Manuel Macías @ 2022-10-09 12:21 UTC (permalink / raw)
  To: Max Nikulin; +Cc: emacs-orgmode

Max Nikulin writes:

>> Many times I need to create and share a public link to a file
>> in my local folder. In the Nextcloud forum I learned how it can be done
>> from the command line using curl,
> ..
>> │ 	 (result-raw (shell-command-to-string
>> │ 		      (concat "curl -u "
>> │ 			      "\""
>> │ 			      my-username
>> │ 			      ":"
>> │ 			      my-passwd
>> │ 			      "\""
>
> Juan Manuel, your function is a nice proof of concept, but posting
> such code you are responsible for users who may try to use it verbatim
> having less experience with elisp.
>
> Use at least `shell-quote-argument' (though it docstring has a link to
> info "(elisp)Security Considerations"). Just adding quote characters
> is unsafe. You may avoid non-alphanumeric characters in passwords and
> file names for good reasons, but for other users a quote character may
> dramatically change the executed command.
>
> When TRAMP support is not necessary, arguments should be passed to
> external binary as a list without intermediate shell command. I know,
> Emacs does not have a convenience function with such calling
> convention similar to `shell-command-to-string'.
>
> I am almost sure that Emacs has a package to send HTTP POST requests
> directly from elisp. Unsure it has convenient enough API (reasonable
> default timeouts, etc.), but it should be safer for working with
> peculiar file names and passwords stuffed with characters having
> special meaning in shell. I admit that the code would be more verbose.
> It may save you time for recovering you system from damage caused by
> unexpected interpretation of a shell command.

Maxim, you are right that the use of shell-quote-argument is preferable
in cases like these to avoid unexpected problems with filenames,
passwords, and so on. I try to use it almost always. If I don't use it
more often, it's either because I'm lazy (because of my way of naming
the files, I don't expect this type of problems) or because I think it's
unnecessary, although not 100% free of danger[1], as in this case. I'm not
saying my behavior is exemplary, I'm just saying what I tend to do. I
should probably always use shell-quote-argument. In this case, the
affected part of my function would perhaps look better like this:

(shell-command-to-string
 (mapconcat #'shell-quote-argument
            `("curl"
              "-u"
              ,(format
                "%s:%s"
                my-user
                my-password)
              "-H"
              "OCS-APIRequest:true"
              "-X"
              "POST"
              ,(format 
                "%s/ocs/v1.php/apps/files_sharing/api/v1/shares"
                nextcloud-url)
              "-d"
              ,(format
                "path=%s/%s"
                nextcloud-public-folder-name
                file)
              "-d"
              "shareType=3"
              "-d"
              "permissions=1")
            " "))

[1] I think that a problem in this context would not go beyond the fact
that the function simply did not work as expected.

Perhaps it would have been better to use call-process-shell-command,
instead of shell-command-to-string, and extract the resulting string
from the output buffer.

On the other hand, I agree with you that whenever possible it is better
to use an Elisp solution than a shell command.

Best regards,

Juan Manuel 

-- 
--
------------------------------------------------------
Juan Manuel Macías 

https://juanmanuelmacias.com

https://lunotipia.juanmanuelmacias.com

https://gnutas.juanmanuelmacias.com




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-10-09 12:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-08 14:29 [tip] Create and Insert a public Nextcloud/Owncloud link Juan Manuel Macías
2022-10-09  3:32 ` Max Nikulin
2022-10-09 12:21   ` Juan Manuel Macías

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).