12

We were just talking about an idea that may be a little further out there. Would it be possible to patch URL support into graphicx.sty or is there a package that would support this on a wider scale (I could imagine it would be useful for pdfpages, listings and similar as well)?

It would need \write18 support obviously, but at least graphicx.sty needs it already for some operations so that shouldn't be a problem. I assume for the general case one would need to define a macro. For graphicx one could cheat a little by defining a .url extension that would have a curl/wget/? rule.

Ideally \includegraphics{http://domain/file.png} would work but I don't see how this would fit into graphicx current context without patching it massively. Alternatively I could see \includegraphics{\grab{http://domain/file.png}} or \includegraphics{http://domain/file.png.url}.

Has someone done this before and wants to share? Is this sane?

7
  • 1
    It would probably be possible. The questions is, would it be desirable?
    – You
    Dec 28, 2012 at 19:03
  • 1
    LuaTeX can do the remote operation itself, and ConTeXt Mark IV certainly can include remote content as a result. Would a LuaTeX-only solution be acceptable?
    – Joseph Wright
    Dec 28, 2012 at 20:47
  • 3
    I though about having this feature several times, apparently context can handle this very easily (see comments in tex.stackexchange.com/questions/5433/…). Also, a local cache would be desirable, otherwise it will be too slow. @You, I bet you that this is one of those things that once this is implemented everybody will be using it.
    – alfC
    Dec 28, 2012 at 20:56
  • I don't know. I just see end-users being surprised that they need an internet connection to typeset a document, that the original URL has 404ed, etc. I don't see the advantage over just wgetting and saving the file in the first place—why should TeX do that for you?
    – You
    Dec 28, 2012 at 21:00
  • 1
    Hacked together something that may be of interest: the download package.
    – You
    Dec 31, 2012 at 22:19

2 Answers 2

7

I am not really sure how you envision things to work, nor am I convinced that there is a need for this. It seems (to me) more reasonable to first download the image to the local folder (rather than re-downloading for every run), with a filename of your choice rather being automatically derived based on the URL, and then just to include that.

Here's a proof of concept for that, assuming curl is available and \write18 enabled:

\documentclass{article}
\usepackage{graphicx}
\newcommand*{\grabto}[2]{\IfFileExists{#2}{}{\immediate\write18{curl \detokenize{#1 -o #2}}}}

\grabto{http://i.stack.imgur.com/Bil0Q.png}{test.png}

\begin{document}
    \includegraphics{test.png}
\end{document}

(Image is from an answer to another question of yours.)

2
5

OK Inspired by Joseph Wright's idea of using lua for this i threw together an attempt at this in pure lua.

\newcommand{\grabto}[2]{#2\ifluatex%
\directlua 0 {
local uri   = "\luatexluaescapestring{#1}"
local fname = "\luatexluaescapestring{#2}"
local job   = "\luatexluaescapestring{\jobname}"
local file  = io.open(fname, 'r')
if file \string~= nil then 
  io.close(file)
else 
  % This detection isn't foolproof because this will happily write to a 0200 
  % file for example but latex can't read it and confusingly won't barf, but 
  % this case is pathologic and depending on posix is somewhat unpreferable
  file = io.open(fname, 'w')
  if file == nil then 
    print("(" .. job .. " file " .. fname .. " does exist already but cannot be read)")
  else 
    require("ltn12")
    local outputsink = ltn12.sink.file(file)
    require("socket.url")
    local parsed = socket.url.parse(uri, {scheme = 'file'})
    if parsed.scheme ==  'http' then
      require("socket.http")
      socket.http.request { url = uri, sink = outputsink, } 
    elseif parsed.scheme == 'ftp' then
      require("socket.ftp")
      socket.ftp.get { url = uri, sink = outputsink, } 
    else 
      % file scheme doesn't make sense because this branch indicates we 
      % at least couldn't read the file.
      tex.error("Don't know how to download this sorry")
      % This situation is a little annoying because we may have 
      % accidentally created a file and can't delete it in case our heuristics
      % failed
    end 
  end
end}%
\else%
% fallback
\fi}

This is the first lua I ever touched, so improvements are greatly appreciated. I believe it works for all cases i could come up with. As mentioned in the comment, I tried to come up with a resonable fallback if luatex isn't the compiler, but it get's nasty quick.

I also changed the interface, so it returns #2, because then I can write \includegraphics{\luagrabto{http://i.stack.imgur.com/Bil0Q.png}{test.png}} That works fine for the lua part and for the rudimentary fallback, but \includegraphic really is fussy in some parts and absolutely disliked me playing around with \hyper@normalize to make sure this doesn't blow up for weird urls.

Not the answer you're looking for? Browse other questions tagged or ask your own question.