Remote file: manage URLs natively in Txp

n: smd_remote_file | v: 0.50 | f: /

Documentation for the Textpattern plugin smd_remote_file by Stef Dawson follows this short message from our sponsor ;-)

Plugin list button Plugin download button Compressed plugin download button


Offers remote and secure file management through Textpattern’s standard Files interface. This is very handy in two main situations:

  1. If you don’t have the bandwidth available to host media content. Third party sites such as offer the ability to upload fairly sizeable files and then freely hotlink to them (within quite generous bandwidth limits) so they can be shared and thus used within your Txp site
  2. If you want to lock down some files so they are not freely downloadable. While .htaccess can clamp down an entire directory or requires special rules for locking certain files, this plugin offers a more natural way to manage them by permitting access to only those people who have the authority to do so


  • Manage links to cloud-based files directly from the Txp Files tab, as if they were native
  • Multiple sources for the same remote file are supported, for load balancing / bandwidth saving
  • Manage files in non-web-accessible (i.e. secure) locations on your host server as if they were native files
  • Files can optionally be served to logged-in users using Hidden / Pending status
  • Integrates with smd_user_manager’s privs system
  • No modifications to Txp core / database required

Installation / uninstallation

Requires Textpattern 4.5.2+

Download the plugin from either, or the software page, paste the code into the Txp Admin->Plugins panel, install and enable the plugin. Visit the forum thread for more info or to report on the success or otherwise of the plugin.

To remove the plugin, simply delete it from the Admin->Plugins panel.


For the remote file capability, choose any third party file hoster that offers free downloads of your stuff. Create an account, upload files to it, and make sure you know how to get Direct Link URLs from their interface (it’s usually fairly obvious). You’ll need these to paste into Textpattern.

For secure files you need to nominate a directory either a) outside of your web host’s document root, or b) in a directory with an .htaccess file that forbids web access to any file. Configure the path to this location from the plugin preferences and then hop over to the Files panel to upload your files.

Plugin preferences

On the Extensions->Remote file panel are the following options to govern how the plugin behaves:

Allow downloads from
Determines which interface elements you see. Choose from:
The Internet to allow remote URLs
Secure location to allow files to be stored in your nominated non-web-acessible folder
Secure file path
Absolute file path to the place you want to store secure files. Ignore this option if you have elected not to use secure files.
Permitted download statuses
List of status numbers (not names) for which you are going to permit downloads. Choose from:
2 for Hidden files
3 for Pending files
Limit downloads to this priv level
The privilege level of users who can download hidden/pending files (providing you have enbled this feature using the Permitted download statuses pref). If you are using smd_user_manager this setting is ignored.

The Files tab: remote files

The plugin adds one input form field to the Files tab labelled URL. From your third party site(s) of choice, simply copy a web-friendly (i.e. url-encoded) hotlink and paste it into the URL box. You can usually tell if the link is url-encoded because it’ll probably have %20 in place of any spaces in the filename. The directory part is, however, not usually encoded: characters such as forward slashes and colons remain.

A typical file might look like this:

The link must be an absolute URL, beginning http://. Once you have pasted it in, hit Upload next to the box and a new special .link file will be created in Txp. It takes on the filename exactly as it appears in your URL (with .link added). So in the example above, a new file called Here is some will be made in your standard Textpattern files directory.

The new “file” will appear in the list just like any real file in Txp. You can edit it to add a title, description, category, set its status: everything you can do with a conventional file. Just don’t rename it!

Multiple personalities

Third party sites don’t give you something for nothing; they normally have a bandwidth cap, just like your web hoster might enforce. If you want to distribute your music or latest video, a few thousand hits per month will eat all your available bandwidth.

So spread the load around the Internet. Get accounts at various third party sites and upload exactly the same file (make sure the filenames are identical — including caSe SensITivItY). Then just paste the URLs into the upload box: smd_remote_file will only maintain one physical file within Txp but will hold details of your other copies for you. Alternatively, click to edit the .link file from the Files panel and paste the other URLs inside the Remote URLs text area; one URL per line. Using either the standard file_download_link tag or the new smd_file_download_link tag will randomly pick one of your download locations associated with each file every time the page loads, spreading your bandwidth usage.

The Files tab: secure files

The plugin adds two checkboxes alongside the create / upload boxes, both labelled Secure. When you create a Txp file from an already uploaded physical file, or upload a new file, just check the checkbox to store the file in your nominated secure location. A corresponding .safe file will be created in the regular files directory containing meta data about the file. At the moment this meta data just houses some placeholder text and if you click a .safe file to edit it you will see a box labelled Secure options into which you can write whatever you like. Just be aware that this area is reserved for future use.

When editing either a .safe or regular file you may replace it with another using the upload box at the bottom of the File edit panel. It is automatically ticked if the file you are editing is secure, but you may uncheck it to convert the new uploaded file to a regular file, and vice versa. Note that even if the uploaded file has a different filename to the one already uploaded, Txp will maintain the original filename just as it does for regular files.

The Files tab: hidden/pending files

The plugin allows a third method of delivering files utilising the status bits. By default, Txp forbids downloads of any files that are not Live (status=4). But if you nominate a status of 2 (Hidden) or 3 (Pending) in the plugin preference Permitted download statuses you can then upload regular files to Txp’s interface and set their status to one of the other options.

A regular <txp:file_download_link> tag will skip non-live files, but you can add the status attribute to display the hidden content. Clicking on such a link will still, however fail to download the file unless you are logged in and one of the following conditions is met:

  • You are the author (uploader) of the file
  • Your privilege level matches that given by the Limit downloads to this priv level preference
  • smd_user_manager is installed and the priv area includes the privilege level of your account
  • smd_user_manager is installed and the priv area includes the privilege level of your account

This is an ideal scenario where wrapping the <txp:file_download_link> with some credentials checking plugin/tag (e.g. rvm_privileged, smd_um_has_privs, cbe_frontauth_protect, etc) can help to deliver content only to special members.

Tag: <txp:smd_file_download_link>

An exact drop-in replacement for the standard file_download_link tag tag, with a few extra attributes:

The ID of the file you want to link to. If left blank, it can be supplied from whatever is between the opening and closing tag
The filename of the file you want to link to. If left blank, it can be supplied from whatever is between the opening and closing tag. If both filename and ID are specified, ID takes precedence
(for remote URLs only) governs how to choose which remote URL to serve. Set it to 0 to randomly pick a URL from those uploaded for this file (the standard file_download_link tag will also do this). You can also specify a higher number to pick the URL from that particular slot. So choose="1" will always select the 1st file you uploaded and deliver that; choose="2" the second; and so on. If you specify a number bigger than the number of URLs stored against a file, it picks the first one you uploaded.
Whether to display the .link or .safe suffix in the link. Choose from:
0 to hide the suffix
1 to show the suffix (in other words, make the tag behave like the built-in file_download_link)
Default: 0
(for remote URLs only) hide the filename portion of the linkand replace it with a random string of characters. Specify the length of the string, e.g. obfuscate="8" would render a link that resembles This is handy to keep the filename partly secret, but it’s not foolproof. As soon as someone starts downloading the file the full remote URL is known.

Tag: <txp:smd_file_download_name>

An exact drop-in replacement for the standard file_download_name tag, but with one attribute:

Whether to display the .link or .safe on the end of file name. Choose from:
0 to hide the suffix
1 to display it (thus behaving like the built-in file_download_name)

Tag: <txp:smd_file_download_image>

When linking to external content (especially media files) it is often useful to make a mini image to go with it, such as a still from a movie or some artwork for an mp3 track. You can of course embed a <txp:image> tag in your download form, but that will give a static image for each file. This tag can be used to display images that vary with the filename of the remote, secure or regular file.

To use it, just upload an image (by default a jpg) via Txp’s Images panel and give it the exact same filename as the remote file it represents, plus its normal image file extension. i.e. if your remote file was Man and boy.mpg you would upload an image and name it Man and boy.mpg.jpg. Do this for each file and then use this tag to display them.

By default, if any image doesn’t exist, the tag outputs the image filename instead (if using the filename) or the id (if using the id). This behaviour can be overridden with the ifmissing option.

The ID of an image to display
The filename of an image to display. If both filename and ID are specified, ID takes precedence. Note that in this and id modes, the tag is essentially the same as <txp:image>. The exception is that you do not have to specify the image file extension, as it does that for you by default if you use JPGs and you can specify thumbnails instead using the thumbnail attribute
Saves you having to specify the file extension in the filename parameter. Enter it here without the dot.
Default: jpg
Display full size image or thumbnail. Choose from:
0 for the full size image
1 if you have created thumbnails and wish to use them
Default: 0
Governs what to do in the event an image is missing. Use ifmissing="" to output nothing in the event of a missing image. Other alternatives:
?ref to display either the image filename or its ID if it was used as an attribute.
?image:ID_or_name" to display the given Txp image (e.g. ifmissing="?image:32" or ifmissing="?image:NoPic.jpg")
some_text to display the given text, e.g. ifmissing="No image yet"
The HTML tag to wrap around the outside of the image. Specify it with no angle brackets, e.g. wraptag="p".
The CSS class name to apply to the image. If using wraptag the class is applied to the surrounding tag. If it is omitted the class is applied directly to the image.

How it works

For the curious, the plugin just creates a placeholder text file with the name of your file plus the special suffix .link or .safe to distinguish it from a standard file. The contents of the file determine which URLs to consider when downloading, or the special options that apply to this secure file (to be decided in a future version).

For remote files, shuffling the order of URLs alters the effect of the choose attribute. Just make sure you have one URL per line that must begin with http and must have the same base filename as the corresponding .link file.

Incidentally, the real file size is fetched every time the local file is edited because otherwise Txp overwrites it with the size of the placeholder text file. In the case of remote files, it reads the file size of the first URL. This has potential ramifications when downloading because the plugin checks that the remote file size matches the one in the Txp interface before serving the file. If one of your uploaded files is a different size it will refuse to download.

The reason for this is to try to maintain download count integrity. Instead of dishing out a standard 404 message, some servers will redirect to an image or HTML file to tell you that a file is missing. This returns a status code of ’200 OK’ to indicate that the download of the replacement content went ok, but in this case we do not want to increment the counter; the file’s still missing after all! Under rare circumstances you might find that the provider returns content exactly the same length as the file itself and the count would then be wrongly incremented. Practically, your file is going to be larger than their replacement so it won’t matter, but if it causes problems, shuffle the order of the URLs so a provider you trust not to use such tactics is first in the list.

Note that the ‘download’ link next to each file on the Files tab of the admin interface always chooses a random file from those uploaded with that name.


Example 1: standard download

In your files form:

 <txp:smd_file_download_name /> [<txp:file_download_size
     format="auto" decimals="2" />]

Example 2: specific download

<txp:smd_file_download_link choose="2"
     show_suffix="1" />

Will always select the 2nd URL from those uploaded for each file. Shows the .link on the end of each remote file.

Example 3: using an image to download file

 <txp:smd_file_download_image ifmissing="Sorry, no image found"
     wraptag="span" class="dload" />

Displays an image with the same name (plus .jpg) as the remote file. The image is clickable to allow the file to be downloaded but if the image is not found, the text “Sorry, no image found” will be displayed instead (the text is also clickable). Wraps the img or text in <span> tags with a class of dload.

Example 4: hidden downloads


Author and credits

Written by Stef Dawson. For other software by me, or to make a donation, see the software page.

I cannot possibly claim all the credit for this hunk of code. The plugin would not have existed if it weren’t for the amazing mind of Ruud van Melick. He suggested a very clever solution to my remote file predicament. I built on that, extended it, refined it, pluginised it and gave it to you. Many thanks to Ruud for the awesome support he offers the community, and also to Wet for his assistance with helping me understand the core.


  • 12 Nov 2007 | 0.10 | Initial release
  • 04 Dec 2007 | 0.20 | Added download counter and some better status messages
  • 04 Dec 2007 | 0.30 | Removed .link when using smd_file_download_link ; added show_link attribute ; improved error handling code ; download count only increases if file sizes match
  • 05 Dec 2007 | 0.31 | File is checked for error condition prior to download in line with core changeset r2720 (thanks Mary) – can be removed when 4.0.6 is released
  • 12 Dec 2007 | 0.32 | Enhanced ifmissing to include image support; changed the ?file attribute to ?ref (it’s a better name)
  • 03 Feb 2008 | 0.40 | Requires TXP 4.0.6 ; removed error check from v0.31 ; added/improved replace remote file ; reduced timeout for accessing remote URL to try and prevent ugly warnings
  • 02 Apr 2008 | 0.41 | Added smd_file_download_name (thanks aswihart)
  • 09 Apr 2008 | 0.42 | Fixed minor edge case bug in smd_file_download_link
  • 10 Jun 2008 | 0.43 | Fixed spurious characters in the single tag version of smd_file_download_link (thanks iblastoff)
  • 11 Oct 2012 | 0.50 | Major rewrite ; added secure file support ; added hidden/pending file downloads (thanks Shaun) ; fixed token javascript error ; added obfuscate attribute ; renamed show_link as show_suffix ; renamed thumb as thumbnail

Source code

If you’d rather spend time with the bytes, you’ll need to step into the view source page.

Legacy software

If, for some inexplicable reason, you need last century's version of a plugin, it can probably be found on the plugin archive page.

Experimental software

If you’re feeling brave, or fancy skateboarding into volcanos, you can test out some of my beta code. It can be found on the plugin beta page.