{"id":305867,"date":"2026-06-18T18:36:12","date_gmt":"2026-06-18T18:36:12","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/secure-media-vault\/"},"modified":"2026-06-18T18:45:18","modified_gmt":"2026-06-18T18:45:18","slug":"ptp-private-media","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/ptp-private-media\/","author":20951130,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.0","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"PTP Private Media","header_author":"Umang Prajapati","header_description":"Protect WordPress media files from direct public access with token-based secure delivery, fine-grained access control, and SEO indexing protection.","assets_banners_color":"","last_updated":"2026-06-18 18:45:18","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/phptutorialpoints.in\/","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/ptp-private-media\/","header_author_uri":"https:\/\/phptutorialpoints.in\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":35,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"umangapps48","date":"2026-06-18 18:45:18"}},"upgrade_notice":{"1.0.0":"<p>Initial release. After activation, re-save your Permalink Settings to ensure rewrite rules are flushed.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3577693,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3577693,"resolution":"256x256","location":"assets","locale":"","width":250,"height":250}},"assets_banners":[],"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Dashboard with protection statistics and quick actions.","2":"Media Library with Protection Status column.","3":"Attachment edit screen showing Protection Settings panel.","4":"Settings page with all configuration sections.","5":"Access Logs table showing granted and denied requests."}},"plugin_section":[],"plugin_tags":[267776,233,267775,58819,267777],"plugin_category":[],"plugin_contributors":[267778],"plugin_business_model":[],"class_list":["post-305867","plugin","type-plugin","status-publish","hentry","plugin_tags-file-access-control","plugin_tags-media-library","plugin_tags-media-protection","plugin_tags-secure-files","plugin_tags-token-url","plugin_contributors-umangapps48","plugin_committers-umangapps48"],"banners":[],"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/ptp-private-media\/assets\/icon-128x128.png?rev=3577693","icon_2x":"https:\/\/ps.w.org\/ptp-private-media\/assets\/icon-256x256.png?rev=3577693","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>PTP Private Media<\/strong> gives you full control over who can access your WordPress media files. Stop search engines, bots, and unauthorised visitors from downloading your protected images, PDFs, videos, or documents.<\/p>\n\n<p><strong>Author:<\/strong> <a href=\"https:\/\/phptutorialpoints.in\/\">Umang Prajapati<\/a> | <a href=\"https:\/\/profiles.wordpress.org\/umangapps48\/\">WordPress Profile<\/a> | <a href=\"https:\/\/github.com\/umang48\/secure-media-vault\">GitHub<\/a><\/p>\n\n<h4>Core Features<\/h4>\n\n<p><strong>\ud83d\udd10 Media Protection System<\/strong>\n* Prevent direct URL access to files in <code>\/wp-content\/uploads\/<\/code>\n* Files are served through a secure PHP handler, not exposed directly\n* Automatic <code>.htaccess<\/code> rules block direct file access on Apache servers\n* Guidance provided for Nginx configurations<\/p>\n\n<p><strong>\ud83d\udc65 Fine-Grained Access Control<\/strong>\nSet a protection level for every file in the Media Library:<\/p>\n\n<ul>\n<li><strong>Public<\/strong> \u2013 standard WordPress behaviour<\/li>\n<li><strong>Logged-in users only<\/strong> \u2013 any authenticated user<\/li>\n<li><strong>Specific roles<\/strong> \u2013 choose from all registered WordPress roles (Admin, Editor, Subscriber, etc.)<\/li>\n<li><strong>Password protected<\/strong> \u2013 custom password per file<\/li>\n<li><strong>Restrict to posts\/pages<\/strong> \u2013 only accessible when referred from specific content<\/li>\n<\/ul>\n\n<p><strong>\ud83d\udd17 Secure File Delivery<\/strong>\n* Replace original media URLs with HMAC-signed, time-limited token URLs\n* Format: <code>example.com\/ptp-restricted-media\/{file-id}\/{token}\/<\/code>\n* Configurable token expiry (default: 1 hour)\n* Hotlink protection prevents embedding on external domains\n* Optional IP-address binding for tokens<\/p>\n\n<p><strong>\ud83d\udeab SEO &amp; Indexing Protection<\/strong>\n* <code>X-Robots-Tag: noindex, nofollow<\/code> header on all protected file requests\n* Optional <code>Disallow<\/code> entries in <code>robots.txt<\/code> for the uploads directory\n* Disable and redirect WordPress media attachment pages\n* wp_robots API integration for attachment pages<\/p>\n\n<p><strong>\ud83d\udcc2 Media Library Integration<\/strong>\n* Protection Settings panel on every attachment edit screen\n* Protection status column (<code>Protected \/ Public \/ Password \/ Role<\/code>) in list view\n* Bulk Actions: protect multiple files, change access rules, make public<\/p>\n\n<p><strong>\u26a1 Performance<\/strong>\n* Chunked streaming with HTTP Range support for large video\/audio files\n* Configurable file-size threshold for streaming vs. single-pass delivery\n* Object cache support with cache invalidation on settings change\n* Scheduled cleanup of expired tokens and old access logs<\/p>\n\n<p><strong>\ud83d\udee1\ufe0f Security<\/strong>\n* HMAC-SHA256 signed tokens using WordPress secret keys\n* Nonce verification on all AJAX requests and form actions\n* All input sanitized and output escaped per WordPress standards\n* No direct file inclusion; <code>ABSPATH<\/code> check on every file\n* Clean uninstall via <code>uninstall.php<\/code><\/p>\n\n<h4>Nginx Support<\/h4>\n\n<p>While <code>.htaccess<\/code> rules are written automatically for Apache, the plugin provides the correct Nginx configuration block in the admin dashboard for manual setup.<\/p>\n\n<h4>WooCommerce Compatibility<\/h4>\n\n<p>The access control system is designed to work alongside WooCommerce. Future versions will include native purchase-based access checks.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>ptp-private-media<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> screen.<\/li>\n<li>Visit <strong>PTP Private Media \u2192 Settings<\/strong> to configure your default options.<\/li>\n<li>Open any media file in the <strong>Media Library<\/strong> and set its protection level.<\/li>\n<li>If using Nginx, add the server block rules shown in the <strong>Dashboard<\/strong>.<\/li>\n<li>Re-save your <strong>Permalink Settings<\/strong> (<code>Settings \u2192 Permalinks<\/code>) if secure URLs return 404.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"will%20this%20break%20my%20existing%20media%20urls%3F\"><h3>Will this break my existing media URLs?<\/h3><\/dt>\n<dd><p>Only files you explicitly protect will have their URLs replaced. Public files continue to behave normally.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20nginx%3F\"><h3>Does it work with Nginx?<\/h3><\/dt>\n<dd><p>The PHP-level access control works on any web server. On Nginx, add the configuration rules shown in the Dashboard to block direct file access at the server level.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20a%20token%20expires%3F\"><h3>What happens if a token expires?<\/h3><\/dt>\n<dd><p>The user will receive an \"Invalid or expired access token\" message. Generate a new secure URL from the Media Library.<\/p><\/dd>\n<dt id=\"can%20i%20use%20it%20with%20a%20cdn%3F\"><h3>Can I use it with a CDN?<\/h3><\/dt>\n<dd><p>CDN bypass is possible for public files. For protected files, disable CDN caching or ensure the CDN forwards requests to WordPress for validation.<\/p><\/dd>\n<dt id=\"does%20this%20affect%20site%20performance%3F\"><h3>Does this affect site performance?<\/h3><\/dt>\n<dd><p>Large files are streamed in 1 MB chunks with HTTP Range support, so memory usage stays low even for large videos.<\/p><\/dd>\n<dt id=\"will%20protected%20files%20still%20be%20indexed%20by%20google%3F\"><h3>Will protected files still be indexed by Google?<\/h3><\/dt>\n<dd><p>No. The plugin sends <code>X-Robots-Tag: noindex, nofollow<\/code> on every protected-file response and disables media attachment pages.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<li>Media protection with <code>.htaccess<\/code> rules and Nginx guidance.<\/li>\n<li>Per-file access control: public, logged-in, roles, password, posts.<\/li>\n<li>HMAC-SHA256 signed, time-limited token URLs.<\/li>\n<li>Hotlink protection and IP-binding option.<\/li>\n<li>SEO protection: X-Robots-Tag, robots.txt rules, attachment page redirect.<\/li>\n<li>Chunked file streaming with HTTP Range support.<\/li>\n<li>Bulk protect\/unprotect actions in the Media Library.<\/li>\n<li>Access logging with configurable retention.<\/li>\n<li>Clean uninstall removes all data.<\/li>\n<\/ul>","raw_excerpt":"Protect WordPress media files with token-based secure delivery, fine-grained access control, and SEO indexing protection.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/305867","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=305867"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/umangapps48"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=305867"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=305867"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=305867"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=305867"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=305867"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=305867"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}