[TOC]
This add-on lets you encrypt/secure download links, restrict access to the files and also display some useful statistics. It consists of module and fieldtype.
- Create highly secure download links
- Display pre-generated links or generate them 'on the fly'
- Serve files from local folder / URL / Amazon S3 or RackSpace CloudFiles secure containers
- Serve files using secure URLs from your own server or Amazon CloudFront
- Limit file access to certain members/member groups/IP
- Limit file access based on custom member profile field value
- Limit number of time file can be downloaded by same user
- Expire the download link after some time
- Display file/link donwload statistics
- Display member download statistics
This add-on is provided free of charge, however I would like to use the opportunity to ask you to support Ukraine in its fight for freedom and democracy. If you use this add-on in commercial projects, please consider donating to Hospitaliers, Come Back Alive or any other charity that helps Ukraine.
Place protected_links
directory with all files inside /system/user/addons
directory. Then go to 'Addons' section in your Control Panel and click Install next to Protected Links.
While you are able to generate links 'on the fly' in your templates, you can also generate them from module Control Panel. That way, you'll be able to add some custom access restrictions and then use links as fieldtype values or pass it to users manually.
To generate the link, go to Module section of your CP, select Protected Links and then Generate Link tab. There, fill in following fields:
- File storage type — local folder, URL, S3 bucket, S3 via CloudFront, or RackSpace container
- Container/bucket — fill only if file is stored in S3 or Rackspace cloud
- Endpoint — this is setting specific to S3. If your files are located in EU datacenter, select "Europe"
- URL or path — URL or local path of file (if you use S3/RackSpace mode, fill only the directory+file name)
- Save file as — you can enter a custom name to save file as (or leave the field blank to use file's actual name)
- Link title — title of link to be used with fieldtype
- Description — longer description for the link
- File type — you can select custom file type to be served to browser. For most cases, you'll need 'force download'
- Deny hotlink — setting this to 'yes' would allow file access only if the link has been clicked on your site - so people can not bookmark or share it. NOTE - this is not 100% reliable, as not all servers have HTTP_REFERER variable available.
- Display file contents inline in browser — setting this to 'yes' would force the file to be opened in browser window, not downloaded to client's computer. NOTE - this is guaranteed to work only with static files, no promises with pages generated by CMS.
- Allow guest access — choose whether to allow guest access or require logging in for member to download the file. NOTE: if you allow guest access this will not mean all guests will get the file. The other checks will also be done.
- Allow access to group — if you select one or several member groups all member of those groups will be allowed to access th file
- Link expiration date — you can set the link to expire after certain date
- Limit of downloads per member — you can limit the number of times on person can download th file. 0 or empty for no limits
- Use this link for field values — choose whether to use this link as possible value of custom field type. Otherwise you can pass on the link manually. (To get the link, click edit link after it has been created)
- Restrict access to the file depending on custom profile field value — you can optionally restrict access to the file based on the value stored in custom profile field
- Value of custom field that would grant access to file — 'trigger' value for the field set above
If you use local folder, make sure you specify full path to file - not relative to your webserver root. It is generally recommended to place the files outside of web root.
Normally, Protected Links passes files though your server to make sure the original location is not exposed. However, if you are CloudFront user, you can take advantage of their signed URLs and have the authenticated visitors redirected to CloudFront signed URL, which is created for his IP and is valid for 24 hours. In the settings, fill in CloudFront Key ID and Secret Key fields. Make sure you have distributions created (with 'Restrict Viewer Access' set to 'Yes' and 'Forward Query Strings' to 'No', other settings are up to you). If you create protected link for a location that does not have distribution, the file will be served though your server just like for 's3' storage. When creating protected link, you will be entering data for the file on S3, CloudFront URL will be created automatically.
After you installed the fieldtype, you can create new custom fields of type "Protected Link". The field is select dropdown containing pre-generated links.
If you add the "Protected Link" field to list of your fields, you then can select its value for each channel entry and then display it using your templates.
If your field is named, say, "dl_link", you can use following tags:
- {dl_link} — pre-formatted download link
- {dl_link:link} — only the actual link, to be used inside
<a href="">
tag - {dl_link:total_downloads} — total number of downloads for the given link
- {dl_link:filename} — file name
- {dl_link:title} — link title
- {dl_link:description} — link description
You can display the links you generated in Control Panel using their ID (and so outside channel entries loop). The link ID can be found on Links tab of module CP.
{exp:protected_links:display link_id='32'}
You can display all files that user is permitted to access/download using {exp:protected_links:files} tag.
<ul>
{exp:protected_links:files}
<li><a href="{link}">{title}</a> ({filename})</li>
{/exp:protected_links:files}
</ul>
Parameters:
- orderby — parameter to order by. Possible values: date, title, filename.
- sort — results sorting direction (asc|desc)
Variables:
- link — protected link
- filename — file name
- title — link title (mostly same as file name)
- description — link description
You can create "my downloads" section that would display all files user has downloaded previously using {exp:protected_links:my_downloads} tag.
<ul>
{exp:protected_links:my_downloads}
<li><a href="{link}">{title}</a> ({times_downloaded}) Last download" {download_date format="%Y-%m-%d"}</li>
{/exp:protected_links:my_downloads}
</ul>
Parameters:
- member_id — ID of member to show downloads list for. Defaults to logged in user.
Variables:
- count — rows counter
- total_results — number of files downloaded
- link — protected link
- filename — file name
- title — link title (mostly same as file name)
- description — link description
- times_downloaded — number of times file has been downloaded by this user
- download_date — date of last download for this file. EE date formatting rules apply.
You need to check yourself based on your own conditions whether to display this tag and give user access to file. It does not make any checks by itself.
{exp:protected_links:generate url="https://www.domain.com/path/to/file.zip" ip_lock="yes" guest_access="yes" title="Get the file!"}
Tag {exp:protected_links:generate}
Parameters:
- only_link="yes" — return only the encrypted download URL. Otherwise return pre-formatted links.
- url — URL or local path of file to serve (or S3/RS path). Required
- storage — storage type. Possible values: 'local', 'url', 's3', 'rackspace' (all lowercase). Defaults to 'url'
- container — S3/Rackspace container name. Do not set if it's not used
- endpoint="s3-eu-west-1.amazonaws.com" — set this only if you use S3 and your files are located in EU datacenter
- filename — if you want file to be saved under different file name, specify it here
- title — text of the link
- content-type — you can specify custom MIME content-type for served file. Default is application/force-downoad
- guest_access="yes" — you should set this to 'yes' if you are going to allow non-logged-in people see the link. Otherwise the download will be restricted to currently logged in member.
- deny_hotlink="yes" — setting this to 'yes' would allow file access only if the link has been clicked on your site - so people can not bookmark or share it.
- inline="yes" — setting this to 'yes' would force the file to open in browser window (and not be downloaded).
- ip_lock="yes" — use this to additionally allow downloads only from the current IP address
- ssl="yes" — set the link to be https-, not http-based
- limit — with this parameter you can limit how many times a person can download the file
- expire_in — you can set the link to expire in certain time after is has been generated. Use English text as value, example "1 hour", "2 days" etc.
- new_link="yes" — with this parameter set to 'yes', the module will generate new donwload link if the old one has expired. Otherwise (by default) it will try to use existing link generated with same parameters for the same member (if all links are expired then nothing is shown)
In the module's control panel, you'll see the tabs named 'Files', 'Links' and 'Members'. They are intended for displaying download statistics grouped by file, link and member respectively.
The File tab shows all the files you are offering for download. If you click file URL you'll see the detailed stats for each file. From there, you can also view detailed link stats or proceed to link editing.
The Link tab shows all the links you generated using CP. If does not show any frontend-generated links. You can edit the link or view detailed link stats.
The Members tab shows download statistics grouped my member - who downloaded what.
Downloads by admins are not recorded and so not displayed.
If you are storing the files on your web server, they still can be downloaded directly if people know the 'real' URL. If you're very strict about security, you should place the files outside of web root to secure the files location.
Create a folder named, say, 'files' next to your document root folder (usually 'public_html' or 'htdocs'). Place your files in that folder. The folder is not accessible via HTTP, so people can never access the files directly. Note that in this case you can use only 'local path' storage for Protected Links and provide the full path.
If you generate links in the template, then your code can look like this:
{exp:protected_links:generate url="/full/path/to/upload/directory/{files}{filename}.{extension}{/files}" storage="local"}</code>
Copyright 2023 Yuri Salimovskiy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.