{"id":381615,"date":"2026-10-13T06:21:48","date_gmt":"2026-10-13T06:21:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/mediaknight\/"},"modified":"2026-10-13T06:21:21","modified_gmt":"2026-10-13T06:21:21","slug":"mediaknight","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/mediaknight\/","author":23566369,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.2","stable_tag":"1.0.2","tested":"7.1.3","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"MediaKnight","header_author":"Vivango","header_description":"Protect Media Library files against public downloads. Grant access to logged-in users.","assets_banners_color":"","last_updated":"2026-10-13 06:21:21","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":60,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.2":{"tag":"1.0.2","author":"vivango","date":"2026-10-13 06:21:21","revision":3743006}},"upgrade_notice":{"1.0.1":"<p>Moves protected files from uploads\/mlp-protected\/ to uploads\/mediaknight\/ and migrates settings; files stay blocked for visitors. Back up first. On Nginx, apply the newly generated snippet and run Check server protection again.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3743006,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3743006,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3743006,"resolution":"1","location":"assets","locale":"","width":1440,"height":1663},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3743006,"resolution":"2","location":"assets","locale":"","width":1440,"height":1000},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3743006,"resolution":"3","location":"assets","locale":"","width":1280,"height":925},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3743006,"resolution":"4","location":"assets","locale":"","width":1280,"height":1250},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3743006,"resolution":"5","location":"assets","locale":"","width":1280,"height":900}},"screenshots":{"1":"Settings &gt; MediaKnight: the server protection check confirms that direct links are blocked on your hosting, with the Nginx setup option and optional blocked-file branding.","2":"The one-click Protect action and protection status in the normal Media Library list.","3":"The attachment editor: choose logged-in access for a single file.","4":"What a logged-out visitor sees on a protected file's link: a privacy-safe blocked-file page in their browser language.","5":"A logged-in client downloads the protected file normally from a client portal page."}},"plugin_section":[],"plugin_tags":[1912,233,22336,222907,183913],"plugin_category":[],"plugin_contributors":[286327],"plugin_business_model":[],"class_list":["post-381615","plugin","type-plugin","status-publish","hentry","plugin_tags-access-control","plugin_tags-media-library","plugin_tags-private-files","plugin_tags-protect-pdf","plugin_tags-protect-uploads","plugin_contributors-vivango","plugin_committers-vivango"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/mediaknight\/assets\/icon-128x128.png?rev=3743006","icon_2x":"https:\/\/ps.w.org\/mediaknight\/assets\/icon-256x256.png?rev=3743006","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/mediaknight\/assets\/screenshot-1.png?rev=3743006","caption":"Settings &gt; MediaKnight: the server protection check confirms that direct links are blocked on your hosting, with the Nginx setup option and optional blocked-file branding."},{"src":"https:\/\/ps.w.org\/mediaknight\/assets\/screenshot-2.png?rev=3743006","caption":"The one-click Protect action and protection status in the normal Media Library list."},{"src":"https:\/\/ps.w.org\/mediaknight\/assets\/screenshot-3.png?rev=3743006","caption":"The attachment editor: choose logged-in access for a single file."},{"src":"https:\/\/ps.w.org\/mediaknight\/assets\/screenshot-4.png?rev=3743006","caption":"What a logged-out visitor sees on a protected file's link: a privacy-safe blocked-file page in their browser language."},{"src":"https:\/\/ps.w.org\/mediaknight\/assets\/screenshot-5.png?rev=3743006","caption":"A logged-in client downloads the protected file normally from a client portal page."}],"raw_content":"<!--section=description-->\n<p><strong>Your private page is not protecting your files.<\/strong><\/p>\n\n<p>A WordPress page can be members-only, but the PDFs and images on it still live in the Media Library with a public uploads address. Anyone who has that direct link can open the file, share it further, and leaked links can end up in search results.<\/p>\n\n<p>MediaKnight closes that gap. Protect a file and it moves out of the public uploads path, so the old direct link stops working for visitors. Logged-in users still open it through a WordPress access check, and protected downloads are sent with noindex headers.<\/p>\n\n<p>You keep working in the normal Media Library: click Protect, done.<\/p>\n\n<h4>Who uses it<\/h4>\n\n<ul>\n<li><strong>Client portals:<\/strong> contracts, reports and deliverables only for clients who log in.<\/li>\n<li><strong>Course and membership material:<\/strong> workbooks, slides and downloads for logged-in students or members. MediaKnight works with WordPress logins; it does not integrate with a specific LMS or membership plugin.<\/li>\n<li><strong>Internal documents:<\/strong> handbooks, procedures and HR files for your team's WordPress accounts.<\/li>\n<li><strong>Invoices and quotes:<\/strong> PDFs your customers open after logging in, not via a forwarded link.<\/li>\n<li><strong>Photographers:<\/strong> show proofs to clients who log in, without the image files being openable by anyone with the URL.<\/li>\n<\/ul>\n\n<h4>What the free plugin does<\/h4>\n\n<p>The free plugin works on its own, with no account, payment, trial expiry or file quota.<\/p>\n\n<ul>\n<li>Protect and unprotect files from the Media Library list and the attachment editor.<\/li>\n<li>Logged-in access to protected files, and continued enforcement of previously saved role restrictions.<\/li>\n<li>Protects registered image sizes, originals and editing backups, not just the main file.<\/li>\n<li>Check server protection: an anonymous test that confirms the direct link is really blocked on your hosting.<\/li>\n<li>Apache works out of the box when .htaccess rules are allowed; on Nginx your host adds a short snippet the plugin generates.<\/li>\n<li>A privacy-safe blocked-file page in the visitor's supported browser language, with English fallback and optional local MediaKnight branding.<\/li>\n<li>Controlled downloads with noindex headers and HTTP Range support for large files.<\/li>\n<li>Interface translations come from translate.wordpress.org language packs; no translation files are bundled with the plugin.<\/li>\n<li>Safe recovery and revocation of existing signed links from a separate extension or earlier installation.<\/li>\n<\/ul>\n\n<h4>MediaKnight Pro (optional)<\/h4>\n\n<p>Everything described above is free and stays free: no account, quota or expiry. MediaKnight Pro is a separate add-on for sites that need more control: choose which WordPress roles can open each file, protect files in bulk, protect new uploads automatically, and share temporary, revocable links with optional click limits.<\/p>\n\n<p>Try Pro for free \u2014 features and pricing: https:\/\/plugins.vivango.com\/mediaknight\/#plans<\/p>\n\n<p>If Pro ends, your saved protection rules stay in place and files remain protected by the free plugin. Existing role restrictions are not broadened to all logged-in users.<\/p>\n\n<p>Pro is distributed outside WordPress.org. The free plugin contains no Pro licensing client or locked Pro implementation and does not download\/install that extension. The optional Freemius connection and its data sharing are explained below.<\/p>\n\n<h4>Technical details<\/h4>\n\n<ul>\n<li>Protected files and their registered variants move to <code>wp-content\/uploads\/mediaknight\/<\/code> (the mediaknight folder inside your uploads directory); attachment metadata is updated and the attachment stays in the Media Library.<\/li>\n<li>The files MediaKnight creates are kept in that folder: protected media, its access rule (.htaccess), an empty index.php, a lock file and, only if your host has enabled it, the Apache collector's working files. Outside that folder, the plugin only adds one marked block to the .htaccess file of the uploads directory on Apache.<\/li>\n<li>Self-repair: MediaKnight checks its own helper files on normal WordPress requests and recreates them if they are missing. It never overwrites a file it did not create. If a helper cannot be restored, it keeps access closed: its download route returns an error instead of a file, new protection stops and a notice appears on the MediaKnight and Media Library screens.<\/li>\n<li>Downloads go through WordPress access checks, with HTTP Range streaming. Server requirements for Apache and Nginx, and the cache exclusions, are listed under Installation.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Install MediaKnight or upload its ZIP via Plugins &gt; Add New &gt; Upload Plugin. The repository root is not the plugin ZIP.<\/li>\n<li>Activate per site. In the optional welcome, choose to try Pro or keep using free. Your choice is remembered and starts no registration. Pro is a separate plugin and requires explicit trial confirmation; in Freemius packages it is obtained through the optional Freemius connection. Network activation is not supported in v1.<\/li>\n<li>Open Settings &gt; MediaKnight and run Check server protection.<\/li>\n<li>Apache needs writable uploads and AllowOverride permitting access rules and Options -Indexes. Existing unrelated .htaccess content is preserved.<\/li>\n<li>Nginx users: ask the hosting provider to apply the generated snippet in the existing server block, validate with nginx -t and reload. Then repeat the check. See docs\/NGINX.md. A proxy\/CDN serving uploads must also enforce protection.<\/li>\n<li>Exclude the MediaKnight admin-post error routes, ?mlp_denied=1, ?mlp_missing=1, ?mlp_download=... and \/mlp-download\/ from page, proxy and CDN caches. Purge any previously public copies.<\/li>\n<li>In Media Library choose Protect, or edit an attachment to choose logged-in access. File-management actions require manage_options and edit_post for that attachment.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"why%20is%20my%20file%20still%20public%20when%20the%20page%20is%20private%3F\"><h3>Why is my file still public when the page is private?<\/h3><\/dt>\n<dd><p>WordPress serves Media Library files directly from the uploads folder. A login on the page does not apply to the file's own URL. MediaKnight moves a protected file out of that public path, so the direct link stops working for visitors while logged-in users can still open it.<\/p><\/dd>\n<dt id=\"does%20it%20work%20on%20nginx%3F\"><h3>Does it work on Nginx?<\/h3><\/dt>\n<dd><p>Yes, with a server rule. Nginx does not read .htaccess files. MediaKnight generates a site-specific snippet; your host adds it to the existing server block, validates with nginx -t and reloads. Then run Check server protection again. Without that rule, protection is not active on Nginx.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20old%20direct%20links%3F\"><h3>What happens to old direct links?<\/h3><\/dt>\n<dd><p>After you protect a file, its old direct link no longer works for visitors. The blocked-file page does not show the file name or internal path; a refused download or direct protected path keeps status 403. Use the shown download URL or insert an image again. Existing hard-coded URLs in posts are not rewritten. Administrators get no exception to the chosen access rule.<\/p><\/dd>\n<dt id=\"does%20the%20free%20version%20expire%3F\"><h3>Does the free version expire?<\/h3><\/dt>\n<dd><p>No. Manual protection, access rules, server checks and downloads remain free. There is no license server or account requirement for these functions.<\/p><\/dd>\n<dt id=\"how%20is%20the%20file%20protected%3F\"><h3>How is the file protected?<\/h3><\/dt>\n<dd><p>The plugin moves the file and its registered WordPress variants into <code>wp-content\/uploads\/mediaknight\/<\/code>, updating attachment metadata. The originals leave the public path. Download URLs go through WordPress access checks. The attachment stays in the Media Library. Copies created outside registered metadata are not tracked.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20someone%20deletes%20the%20mediaknight%20folder%3F\"><h3>What happens if someone deletes the mediaknight folder?<\/h3><\/dt>\n<dd><p>MediaKnight recreates its own helper files automatically, but it cannot recreate your protected media: those files are stored only in <code>wp-content\/uploads\/mediaknight\/<\/code>, so deleting the folder deletes them. MediaKnight then reports the missing files on the MediaKnight and Media Library screens; it never moves, replaces or invents files to fill the gap. Keep regular backups that include this folder and restore it from your backup if needed. Cleanup, optimization, cache and security plugins must not delete or \"clean\" this folder or its .htaccess file; exclude it in their settings.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20deactivate%20or%20uninstall%3F\"><h3>What happens when I deactivate or uninstall?<\/h3><\/dt>\n<dd><p>Deactivation keeps protected files blocked; reactivate the base plugin to resume downloads. Uninstall restores media to their original directory and removes plugin settings, metadata and generated Apache rules. Restored files become public. Media files are never deleted by uninstall. On conflicts or interrupted moves, uninstall stops for recovery; see docs\/DEVELOPMENT.md. Remove manual Nginx rules only after successful restoration.<\/p><\/dd>\n<dt id=\"can%20i%20change%20selected%20roles%20without%20pro%3F\"><h3>Can I change selected roles without Pro?<\/h3><\/dt>\n<dd><p>Role selection is supplied by the separate Pro extension. Existing saved role rules remain enforced without Pro. Keep the existing restriction when saving an attachment to preserve both access and existing links. Switching to logged-in access or public explicitly broadens access.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20pro%20is%20removed%20or%20its%20trial%20ends%3F\"><h3>What happens if Pro is removed or its trial ends?<\/h3><\/dt>\n<dd><p>The free protection and access rules keep working. Existing signed links keep their original expiry, click limit and access rules, and can be revoked in the base plugin. If automatic protection was enabled and its extension is inactive, new uploads are stopped to prevent accidental publication. Settings offers an explicit action to disable automatic protection; existing files remain protected.<\/p><\/dd>\n<dt id=\"what%20are%20the%20limits%3F\"><h3>What are the limits?<\/h3><\/dt>\n<dd><p>Local WordPress uploads only. No offload, S3\/R2, watermarking, file sales, membership\/form integration or document portal in v1. Hosting execution limits apply to large downloads. Multipart ranges are rejected. Active file types are served as downloads. Previously downloaded\/cached copies cannot be recalled. Protection must be enforced on every host serving uploads. A failed anonymous loopback\/TLS check blocks new protection until hosting is fixed.<\/p><\/dd>\n<dt id=\"what%20data%20does%20the%20free%20plugin%20store%20or%20send%3F\"><h3>What data does the free plugin store or send?<\/h3><\/dt>\n<dd><p>It stores attachment protection settings and site settings locally. Existing signed-link records contain expiration and click counters. Approximate rate limiting uses a salted hash of the connecting IP in a transient expiring after 120 seconds; the plugin does not store raw IP addresses. Expired database entries may remain until WordPress cleanup. The server check requests a harmless temporary file on your own configured uploads URL without login cookies. Free activation and ordinary free protection do not initialize the optional Freemius connection. Optional public error-page branding uses only bundled assets. WordPress authentication and hosting access logs are separate. The MediaKnight uninstall routine makes no network request. The optional savings meter is off by default. Only after you switch it on, it records per day, locally in its own database tables, which external domains tried to load files from your site. This data is not sent anywhere.<\/p><\/dd>\n<dt id=\"optional%20external%20service%3A%20freemius\"><h3>Optional external service: Freemius<\/h3><\/dt>\n<dd><p>Packages with the Freemius SDK offer a voluntary Pro connection in Settings &gt; MediaKnight. Nothing is sent to Freemius unless you explicitly continue, the server protection check succeeds and you then opt in on the Freemius connection screen (you can also skip). Only after that opt-in, or after starting a trial or activating a license, the SDK contacts api.freemius.com for connection, trial, purchase, licensing and premium updates.<\/p>\n\n<p>The connection screen lists the permissions requested. Per Freemius' data practices this covers the opted-in administrator's name and email address, the site URL, plugin version and state (active, inactive, uninstalled), WordPress and PHP versions and site language; the data is re-synced at most daily when it changes. The list of installed plugins\/themes is a separate optional permission: our configuration sets it off by default, and the connection screen shows a switch so you decide. Our configuration also sets the SDK newsletter permission off; the SDK's standard connection text may still mention update\/offer emails, so only opt in if you agree with the text shown. Connected sites receive periodic licensing\/update checks. MediaKnight does not attach media files, protected URLs or visitor records to this integration. Free protection does not require connecting or paying. Freemius provides its own account\/disconnection controls after connection.<\/p>\n\n<p>If you buy or trial Pro under the Freemius route, checkout runs on checkout.freemius.com. Freemius acts as the authorized reseller and merchant of record for that sale (payment processing, VAT\/sales tax and invoice); name, email and billing details you enter there go directly to Freemius. For opt-in usage and licensing data, Freemius acts on behalf of the plugin owner as data processor, as described in its data practices.<\/p>\n\n<p>Service: https:\/\/freemius.com\/\nTerms: https:\/\/freemius.com\/terms\/\nPrivacy: https:\/\/freemius.com\/privacy\/\nData practices: https:\/\/freemius.com\/privacy\/data-practices\/<\/p><\/dd>\n<dt id=\"where%20can%20i%20get%20help%20or%20give%20feedback%3F\"><h3>Where can I get help or give feedback?<\/h3><\/dt>\n<dd><p>Use this plugin's WordPress.org support forum. Include the relevant error message and server type when useful, but never post passwords, license credentials, private file URLs or customer documents. The separate Pro extension also offers a voluntary feedback form and optional departure question.<\/p><\/dd>\n<dt id=\"important%20limits\"><h3>Important limits<\/h3><\/dt>\n<dd><p>MediaKnight limits access to files in your uploads folder. It cannot control copies already held by a CDN or cache, or server rules it cannot write (on Nginx your host must apply them). Run Check server protection again after server changes. Keep your own backups. MediaKnight is not a complete security solution and is provided without a guarantee that files can never be accessed without authorisation. Highly sensitive files do not belong in a publicly reachable uploads folder, even with MediaKnight.<\/p><\/dd>\n<dt id=\"does%20this%20guarantee%20that%20my%20website%20meets%20privacy%20laws%3F\"><h3>Does this guarantee that my website meets privacy laws?<\/h3><\/dt>\n<dd><p>No. This plugin controls access to supported media files. It does not certify legal compliance or prevent an authorized recipient from copying a downloaded file.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Updated Freemius SDK to the latest version<\/li>\n<li>Internal documentation is excluded from release packages.<\/li>\n<li>Plugin identifiers use MediaKnight names. Legacy settings and metadata are copied and verified before the old keys are removed; unresolved conflicts retain both values for recovery.<\/li>\n<li>The inline media panel supports collapsing and uses the saved above\/below-description position.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>MediaKnight now keeps its files in <code>wp-content\/uploads\/mediaknight\/<\/code>. Files protected by an earlier build in <code>uploads\/mlp-protected\/<\/code> are moved there automatically, in small batches while an administrator uses wp-admin: each file is copied and checked before the old copy is removed, an interrupted move resumes, and the old location stays blocked during the move.<\/li>\n<li>Settings, per-file protection data and the plugin's database tables are migrated to new MediaKnight names. Existing values are not overwritten, and the former names stay readable for MediaKnight Pro 1.0.3. If a migration step fails, files stay blocked for visitors and the step is tried again on a later request.<\/li>\n<li>Self-repair of MediaKnight's own helper files; if repair is not possible, access stays closed and a notice appears on MediaKnight and Media Library screens.<\/li>\n<li>The index.php helper in protected storage is now an empty file.<\/li>\n<li>Translations now come from translate.wordpress.org; the plugin no longer bundles translation files.<\/li>\n<li>MediaKnight notices are limited to MediaKnight and Media Library screens.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<p>Initial permanent free edition: manual file protection, logged-in access, enforcement of saved rules, localized privacy-safe blocked-file pages, Apache\/Nginx checks, controlled downloads and safe recovery. Pro is a separately installed extension.<\/p>","raw_excerpt":"Private media for WordPress: protect PDFs and images from direct URL access so only logged-in users can open them. Apache rules + Nginx snippet.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/381615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=381615"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/vivango"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=381615"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=381615"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=381615"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=381615"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=381615"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=381615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}