Forum Moderators: phranque

Message Too Old, No Replies

Hotlink protection without using HTTP_REFERER

Media file protection using dynamically-generated links (php/mod_rewrite)

         

twist

8:17 am on Mar 25, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This code is php specific but could be used with any server-side scritping language.

<a href="http://example.com/media/'. date( 'w' ) .'/bigvideofile/wmv">

links to photo at [example.com...]

Now I add this to htaccess,

# Check for day of week
RewriteCond %{TIME_WDAY} =0
# Then check request
RewriteCond %{REQUEST_URI} ^/media/([0-6]+)/([0-9a-z_]+)/(gif¦jpg¦swf¦wmv¦mp3)$
# Check for correct day of week in request
RewriteCond %1 ^.*0.*$
# Check to make sure other days are not included
RewriteCond %1!^([123456]+)$
# Direct to file
RewriteRule ^(.+)/(.+)/(.+)/(.+)$ $1/$3\.$4 [L]

Repeat the above code for days 1-6.

What the code does is pass the current day in the url using php and then apache only allows the link to work if the day in the url is the same day as the current day. So if someone hotlinks your file by copying your link it will only work for one day out of the week and the other 6 days they will get nothing.

This all leads to the problem of midnight. Visitors viewing your site during day change might lose the images also. I couldn't find a solution to this problem using htaccess but I am wondering about a possible solution using a CRON job and php.

If I use caching for my webpages then I was curious if simply deleting my cache files at day change would make sure that any page clicked on would have to rewrite the cache and update all the links for the new day.

Or

I suppose I could just set all my cached pages to expire at midnight or maybe just the parts of the pages that use images at least.

Any thoughts or suggestions or should I post this over at the php forums instead?

sitz

8:37 pm on Mar 25, 2005 (gmt 0)

10+ Year Member



How about this (capitalizing on the most excellent idea documented in this thread [webmasterworld.com]:

RewriteEngine on
RewriteCond %{REQUEST_URI} ^/media/([0-6])/([^/]+)/(gif¦jpg¦swf¦wmv¦mp3)$
RewriteCond %1<->%{TIME_WDAY}!^(.*)<->\1$
RewriteRule ^(.+)/(.+)/(.+)/(.+)$ $1/$3\.$4 [L]

Note that this code is NOT FULLY PORTABLE. It requires a POSIX 1003.2 regular expression implementation on the server. OS's known to support this:

  • Solaris 7 - Solaris 9
  • Linux with glibc 2.2.5 and later

    OS's known NOT to support this:

  • HPUX 11
  • OS X (through 10.3.8, anyway. We'll see if that changes in the future

    If you use an OS which supports the 1003.2 spec (and assuming I'm understanding the requirements properly), the above rule should handle *all* variants. You could, of course, issue the redirect for the specific day using TIME_DAY instead of TIME_WDAY. If you keep TIME_WDAY, note that I removed the '+' in the [0-6] section, since the TIME_WDAY will only return a single digit, and tweaked the [a-zA-Z] section a tad.

    Does this help?

  • jdMorgan

    1:29 am on Mar 26, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    RewriteCond can back-reference the RewriteRule pattern, so you can actually eliminate the first RewriteCond in this case. Here's that simplification, plus another:

    RewriteEngine on
    RewriteCond $1<->%{TIME_WDAY}!^(.*)<->\1$
    RewriteRule ^media/([0-6])/([^/]+)/(gif¦jpg¦swf¦wmv¦mp3)$ media/$2.$3 [L]

    This "compare" trick also works with FreeBSD, which supports POSIX 1003.2 atomic back-references.

    Jim

    sitz

    3:26 am on Mar 26, 2005 (gmt 0)

    10+ Year Member



    Wow. That makes total sense, and never would have occurred to me. So, for the edification of anyone else who reads this thread and *doesn't* get why you can reference a RewriteRule's parenthesized elements as backreferences, the answer is simple enough: mod_rewrite parses RewriteRule's *first*; if the left-side of a RewriteRule matches, *then* any RewriteCond lines pertaining to that RewriteRule are run. This saves on processing time; no sense in executing the RewriteCond lines if the RewriteRule isn't going to do anything. And since the RewriteRule is executed first, the backreferences are available. Wild. =)

    jdMorgan

    3:40 am on Mar 26, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Hey, since I have to live in rented server space, I try to beat every single cycle out of .htaccess -- It's nowhere near as good as compiled code in httpd.conf, but every little bit helps. :)

    Since we're temporarily off-topic, I'll just add that for best performance RewriteConds should be ordered in least-likely-to-match to most-likely-to-match-order, and that any filesystem checks such as "-f" or "-d" should be done last, if possible. Try to avoid going to disk if at all possible.

    One other thing to avoid is using {REMOTE_HOST), since this requires your server to send a reverse-DNS lookup request to the internet and get a response before anything else can proceed.

    twist, are ya there? Did the "compare trick" work for you?

    Jim

    twist

    3:57 am on Mar 26, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    My kid is sick today and I don't have time to do anything really but type this quick message on my laptop.

    I couldn't get the backreference to work before and i'm going to test it out again when I get the chance but if backreferencing works then how about this for an idea.

    Have your scripting language get the TIME.

    Create one variable with minus 12 hours worth of seconds of the TIME (or any time period you choose)

    Create another variable that adds 12 hours worth to the TIME

    Create a link like so,

    [example.com...]

    Now the question is can you do a string compare using the backreference for greater than or less then? I just don't have time to try anything now.

    If it did work though, it means your links would only be good for 12 hours and you wouldn't have to worry about end of day or end of year changeover's.

    Even if it won't work I appreciate all the help you guys have given me and i'll see if it works as soon as I get a chance.

    twist

    6:56 am on Mar 27, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    RewriteEngine on
    RewriteCond $1<->%{TIME_WDAY} !^(.*)<->\1$
    RewriteRule ^media/([0-6])/([^/]+)/(gif¦jpg¦swf¦wmv¦mp3)$ media/$2.$3 [L]

    -> RewriteCond $1<->%{TIME_WDAY} ^(.*)<->\1$

    I need to remove the ! in order for it to compare. Otherwise it is saying it's ok as long as the 2 don't match. When I remove the ! I can't get them to match.

    Am just going about this in the wrong way?

    twist

    8:30 am on Mar 27, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I've asked on my hosts newsgroup and hope to hear an answer but as far as I can tell my setup (FreeBSD 4.8-STABLE) just doesn't support the back-reference.

    Unless I am doing something really wrong, here are some things I have tried that won't work,

    RewriteCond $1<->$1 ^(.*)<->\1$
    RewriteCond $1<->%{TIME_WDAY} ^(.*)<->\1$
    RewriteCond %1<->%{TIME_WDAY} ^(.*)<->\1$
    RewriteCond $1<>%{TIME_WDAY} ^(.*)<>\1$

    and about 30 more combinations with no luck.

    I am referencing the rewriterule though, that was a great tip.

    sitz

    2:16 pm on Mar 27, 2005 (gmt 0)

    10+ Year Member



    You can check to see whether your OS supports backreferences in regexes by executing this from the commandline:

    echo 'foofoo' ¦ grep -E '^(foo)\1$'

    If you see 'foofoo', you're ok. Of course, while the OS supports it, it's *possible* (I think? maybe? someone check me on that.) that your Apache build does not. I'd set the RewriteLog crank up the RewriteLogLevel to 9; that will tell you where the problem is.

    jdMorgan

    3:08 pm on Mar 27, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Also, please verify that you intentionally removed the "!" character from the code that sitz posted:

    RewriteCond %1<->%{TIME_WDAY} [b]!^([/b].*)<->\1$

    Jim

    twist

    5:01 pm on Mar 27, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    RewriteEngine on
    RewriteCond %{REQUEST_URI} ^/media/([0-6])/([^/]+)/(gif¦jpg¦swf¦wmv¦mp3)$
    RewriteCond %1<->%{TIME_WDAY} !^(.*)<->\1$
    RewriteRule ^(.+)/(.+)/(.+)/(.+)$ $1/$3\.$4 [L]

    The code works fine as long as I leave the "!" in it. The problem is the code works fine with the "!" no matter what I put on either side.

    RewriteCond %1<->%3 !^(.*)<->\1$ #works
    RewriteCond %1<->%9 !^nothing<->everthing$ #works also

    It's only when I remove the "!" that the code stops working, but don't I have to remove it to prove they match?

    I'd set the RewriteLog crank up the RewriteLogLevel to 9

    Before I try to figure out how to do this, can it typically be done on a shared hosting account?

    The other day jim gave me this method to duplicate an echo,

    RewriteRule ^test_time\.html$ /time_test.html?year=%{TIME_YEAR}&month=%{TIME_MONTH}&day=%{TIME_DAY} [R=301,L]

    Is there anyway I can use this to test my output for this current situation?

    twist

    9:02 pm on Mar 27, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I hope to get the back-reference to work but until then,

    For people who can't use backreferences this is a modified version (thanks to tips from this thread) of what I was using before. It works, but it's quite bloated. I guess this might not be a problem if you can add it to an httpd.conf file. Either way, here is how it works.

    It creates a link that is good for the previous hour, current hour and next hour. So a link works for 3 hours out of a day. This works for wmv,mp3,swf,jpg,gif and so on. So if someone links directly to a file on your server the link will only work for 3 hours. It isn't based on referrer information.

    I am using php for server-side script


    // Get hour of day
    $hod = date( 'H' );

    // If hour is equal to 00, make previous hour 23
    if( $hod == 00 ) { $hod_prev = 23; }

    // Else minus one from hour and add extra 0 if needed. 02 ok, 2 wont work.
    else { $hod_prev = sprintf( "%02d", ( $hod - 1 ) ); }

    // If hour is 23, make next hour 00
    if( $hod == 23 ) { $hod_next = '00'; }

    // Else add one to hour and add 0 if needed
    else { $hod_next = sprintf( "%02d", ( $hod + 1 ) ); }

    // Create link, use chr(rand(97,122)) to create random letter to seperate days
    // Could also potentially confuse hotlinkers trying to mimick your script
    $link = 'media/' . $hod.chr(rand(97,122)) . $hod_prev . chr(rand(97,122)) . $hod_next . '/';

    Example link,
    <?php echo '<a href="' .$link. '/mp3/TenMegSong">name</a>'?>

    Add this to your .htaccess


    RewriteEngine on

    # Compare with current hour
    RewriteCond %{TIME_HOUR}/$1 ^00/.*00.*$
    # If match, show image
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]

    # Repeat for every hour
    RewriteCond %{TIME_HOUR}/$1 ^01/.*01.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^02/.*02.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^03/.*03.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^04/.*04.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^05/.*05.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^06/.*06.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^07/.*07.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^08/.*08.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^09/.*09.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^10/.*10.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^11/.*11.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^12/.*12.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^13/.*13.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^14/.*14.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^15/.*15.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^16/.*16.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^17/.*17.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^18/.*18.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^19/.*19.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^20/.*20.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^21/.*21.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^22/.*22.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]
    RewriteCond %{TIME_HOUR}/$1 ^23/.*23.*$
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ realpath/$3\.$2 [L]

    #If you wanted to be extra secure you could change,
    #([0-9a-z]{8}) to ([0-9]{2}[a-z][0-9]{2}[a-z][0-9]{2})

    I hope this isn't a terrible idea, the bloat and all, comments/suggestions?

    jdMorgan

    4:34 am on Mar 28, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Suggestion to compress your existing .htaccess code:
    [1]
    # Compare current hour with time in requested link
    RewriteCond %{TIME_HOUR}/$1 ^(00/.*00¦01/.*01¦02/.*02¦03/.*03¦04/.*04¦05/.*05¦06/.*06¦07/.*07) [OR]
    RewriteCond %{TIME_HOUR}/$1 ^(08/.*08¦09/.*09¦10/.*10¦11/.*11¦12/.*12¦13/.*13¦14/.*14¦15/.*15) [OR]
    RewriteCond %{TIME_HOUR}/$1 ^(16/.*16¦17/.*17¦18/.*18¦19/.*19¦20/.*20¦21/.*21¦22/.*22¦23/.*23)
    # If match, rewrite to real filepath
    RewriteRule ^media/([0-9a-z]{8})/(gif¦jpg¦swf)/(.+)$ /realpath/$3\.$2 [L]
    [/1]

    You could actually compress it to two lines, but I wanted to avoid line-wrapping problems in this post.

    There's another thing you might want to experiment with. You can do the "3-hour allowance" part in .htaccess instead of the script. You would then present only the two current-hour digits in the link created by php. Note also that the hour in a recently-produced link will always be the same as the current hour, or one or two hours lower than the current hour. So this code, for example, allows the link hour to be 23, 00, or 01 if the current hour is 01.

    Showing the code above with this modification:

    [1]
    RewriteCond %{TIME_HOUR}/$1 ^(00/(2[23]¦00)¦01/(23¦0[01])¦02/0[012]¦03/0[123]¦04/0[234]¦05/0[345]¦06/0[456]¦07/0[567])$ [OR]
    RewriteCond %{TIME_HOUR}/$1 ^(08/0[678]¦09/0[789]¦10/(0[89]¦10)¦11/(09¦1[01])¦12/1[012]¦13/1[123]¦14/1[234]¦15/1[345])$ [OR]
    RewriteCond %{TIME_HOUR}/$1 ^(16/1[456]¦17/1[567]¦18/1[678]¦19/1[789]¦20/(1[89]¦20)¦21/(19¦2[01])¦22/2[012]¦23/2[123])$
    RewriteRule ^media/([012][0-9])[a-z]{2}/(gif¦jpg¦swf)/(.+)$ /realpath/$3\.$2 [L]
    [/1]

    This also allows you to eliminate the ".*" from your patterns and to use precisely-anchored patterns, which will greatly improve efficiency.

    Now, the problem with this is that these links will still work for three hours a day, so I'd suggest at least adding the current day of the month, in the same way that the current hour was added. (Now that we can do 24 hours in three lines, doing 31 days in four lines won't seem so bad. Plus, you only need to allow for the link-day to be current day or day-1, 2, or 3 if the current hour is 0, 1, or 2. Otherwise, you're looking for an exact match.

    Another problem is that someone might still discover your direct links, or that your old direct links are still active and could be linked to. So to prevent direct access using the real path, you can use:


    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /real_path_to_files
    RewriteRule - [F]

    This will not affect the rewritten links above, because it only examines the URL requested in the HTTP request.

    Change all broken pipe "¦" characters in the code above to solid pipe characters (usually Shift-\) before use.

    Apologies in advance for any typos -- this code made my eyes blurry.

    Jim

    [edit] Yes, there was a typo. Fixed now. [/edit]

    twist

    11:48 pm on Mar 29, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Ok, before tackling the rest, I need to understand what is going on with this,

    Another problem is that someone might still discover your direct links, or that your old direct links are still active and could be linked to. So to prevent direct access using the real path, you can use:
    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /real_path_to_files
    RewriteRule - [F]

    When I use this, I am still able to directly view my files. I have tried all sorts of variations but none seem to stop me from viewing the files directly. Anything that does work, fails on the next passthrough, for example,

    RewriteRule .*\..* - [F]

    Here are some of the variations I have tried, replacing "¦" of course,

    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /foldername/.*
    RewriteRule - [F]

    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /foldername.*
    RewriteRule - [F]

    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /foldername/.*\.gif
    RewriteRule - [F]

    Using the Web Developer extension for firefox if I view response headers it returns this,

    Date: Tue, 29 Mar 2005 23:45:30 GMT
    Server: Apache/1.3.29
    Last-Modified: Sun, 20 Mar 2005 06:14:06 GMT
    Etag: "5a6829-1485-423d14ae"
    Accept-Ranges: bytes
    Content-Length: 5253
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Content-Type: image/gif

    I don't know if this helps or not.

    In the off chance that blocking direct access by filename cant work I was curious about placing them below the header but can't seem to come up with good set of search words that brings any relevant results. I understand it must be done in php but can't find a turtorial anywhere. I'll probably post in the php forum and hope for an answer.

    [edited by: jdMorgan at 1:18 am (utc) on Mar. 30, 2005]
    [edit reason] Fixed [/ quote] orphans. [/edit]

    jdMorgan

    1:19 am on Mar 30, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Sorry, I warned you my eyes got blurry typing that stuff...

    Here's the correct form for the direct-access block:


    RewriteCond %{THE_REQUEST} ^(GET¦HEAD)\ /real_path_to_files
    RewriteRule .* - [F]

    Jim

    twist

    10:48 pm on Mar 30, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Here's the correct form for the direct-access block:

    Thanks, worked perfectly.

    I started by writing the code using the hour and day of month but started realizing that it would be quite a lengthy piece of code. I switched over to the "Day of Week" over "Day of Month" to save space. It still would only mean your link would work for 3 hours a day 1 day a week. I can live with that.

    The reason I wanted to add an extra hour after the current is because I am using caching on some pages. So if a page is cached at 4:59 the cached page will last half-hour and it would carry over into the next hour. If a person didn't use caching or wanted to use more time on the cached script they could simply add hours or take away the extra one. I have kept the next hour in.

    Here is the code for the first 2 days of the week, i'll combine them later but was hoping if people could kinda scan over the code and catch any mistakes before combining multiple hours onto single lines and posting the full code. Any more ideas on how to shorten the code would also be a welcome thing.

    # Only first 2 days of week
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/([60])/00/(2[23]¦0[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/([60])/01/(23¦0[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/02/(0[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/03/(0[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/04/(0[2345])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/05/(0[3456])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/06/(0[4567])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/07/(0[5678])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/08/(0[6789])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/09/(0[789]¦10)$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/10/(0[89]¦1[01])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/11/(09¦1[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/12/(1[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/13/(1[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/14/(1[2345])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/15/(1[3456])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/16/(1[4567])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/17/(1[5678])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/18/(1[6789])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/19/(1[789]¦20)$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/20/(1[89]¦2[01])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/21/(1[9]¦2[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/22/(2[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/0/23/(2[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^0/[01]/24/(2[234]¦00)$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/([01])/00/(2[23]¦0[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/([01])/01/(23¦0[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/02/(0[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/03/(0[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/04/(0[2345])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/05/(0[3456])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/06/(0[4567])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/07/(0[5678])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/08/(0[6789])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/09/(0[789]¦10)$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/10/(0[89]¦1[01])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/11/(09¦1[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/12/(1[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/13/(1[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/14/(1[2345])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/15/(1[3456])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/16/(1[4567])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/17/(1[5678])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/18/(1[6789])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/19/(1[789]¦20)$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/20/(1[89]¦2[01])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/21/(1[9]¦2[012])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/22/(2[0123])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/1/23/(2[1234])$ [OR]
    RewriteCond %{TIME_WDAY}/$1/%{TIME_HOUR}/$2 ^1/[12]/24/(2[234]¦00)$ [OR]

    # Path Media/DayOfWeek/HourOfDay/Filename/Extension
    RewrtieRule ^media/([0-6])/([012][0-9])/(.+)/(gif¦jpg¦swf¦mp3¦mpg)$ /realpath/$3\.$4

    jdMorgan

    3:42 am on Mar 31, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    Hmmm... Server page caching or not, the link on the page --either in the server cache or the browser cache-- will always be older than the current time, so the offset is always backward in time, and that was my point. Maybe I'm missing something, but no matter... You have the time to test and I don't, and I'm more interested in discussing/helping at a theoretical level anyway -- you can tweak to suit your actual application as needed.

    BTW, I commend the effort you're putting into this... :)

    You can avoid having a huge ruleset by testing the current month, day, and hour separately, not combined as you show.

    Also, be aware that the patterns [3456] and [3-6] are equivalent, except that the latter is one character shorter. You can use either form, but since this code will run for each and every image request, I suggest you keep the code as small as possible. That's why I keep trying to post optimized rules.

    Leaving the code with a three-hour window for hour rollover and caching, and assuming the URL form is

    example.com/media/month/day_of_month/hour_of_day/filetype/filename

    we get:

    [1]
    # *** Serve image file only if link month and day match current month and day, and link hour is current or 1 or 2 hours old.
    # *** Images may be marked as cacheable for up to one hour using this system.
    #
    # Check month - Allow old month in link for first 3 hours (00-02) of first day of month
    RewriteCond %{TIME_MON}/$1/%{TIME_DAY}/%{TIME_HOUR} ^(01/12¦02/01¦03/02¦04/03¦05/04¦06/05¦07/06¦08/07¦09/08¦10/09¦11/10¦12/11)/01/0[012]$ [OR]
    #
    # Check month - Always allow current month in link
    RewriteCond %{TIME_MON}/$1 ^(01/01¦02/02¦03/03¦04/04¦05/05¦06/06¦07/07¦08/08¦09/09¦10/10¦11/11¦12/12)$
    #
    # Check day - Allow old day in link for first 3 hours of day (00-02)
    #
    # If March, allow for 28 or 29 days in previous month
    RewriteCond %{TIME_MON)/%{TIME_DAY}/$2/%{TIME_HOUR} ^(03/01/2[89]/0[012])$ [OR]
    #
    # If Apr, May, Jun, Sep, or Nov, allow for 30 days in previous month
    RewriteCond %{TIME_MON)/%{TIME_DAY}/$2/%{TIME_HOUR} ^((0[567]¦1[02])/01/30/0[012])$ [OR]
    #
    # Default is to expect previous day to be 31
    RewriteCond %{TIME_DAY}/$2/%{TIME_HOUR} ^(01/31¦02/01¦03/02¦04/03¦05/04¦06/05¦07/06¦08/07¦09/08¦10/09)/0[012]$ [OR]
    RewriteCond %{TIME_DAY}/$2/%{TIME_HOUR} ^(11/10¦12/11¦13/12¦14/13¦15/14¦16/15¦17/16¦18/17¦19/18¦20/19)/0[012]$ [OR]
    RewriteCond %{TIME_DAY}/$2/%{TIME_HOUR} ^(21/20¦22/21¦23/22¦24/23¦25/24¦26/25¦27/26¦28/27¦29/28¦30/29¦31/30)/0[012]$ [OR]
    # Check day - Always allow current day in link
    RewriteCond %{TIME_DAY}/$2 ^(01/01¦02/02¦03/03¦04/04¦05/05¦06/06¦07/07¦08/08¦09/09¦10/10)$ [OR]
    RewriteCond %{TIME_DAY}/$2 ^(11/11¦12/12¦13/13¦14/14¦15/15¦16/16¦17/17¦18/18¦19/19¦20/20)$ [OR]
    RewriteCond %{TIME_DAY}/$2 ^(21/21¦22/22¦23/23¦24/24¦25/25¦26/26¦27/27¦28/28¦29/29¦30/30¦31/31)$
    #
    # Check hour - Allow current hour or previous 2 hours in link
    RewriteCond %{TIME_HOUR}/$3 ^00/(2[23]¦00)¦01/(23¦0[01])¦02/0[012]¦03/0[123]¦04/0[234]¦05/0[345]¦06/0[456]¦07/0[567]$ [OR]
    RewriteCond %{TIME_HOUR}/$3 ^08/0[678]¦09/0[789]¦10/(0[89]¦10)¦11/(09¦1[01])¦12/1[012]¦13/1[123]¦14/1[234]¦15/1[345]$ [OR]
    RewriteCond %{TIME_HOUR}/$3 ^16/1[456]¦17/1[567]¦18/1[678]¦19/1[789]¦20/(1[89]¦20)¦21/(19¦2[01])¦22/2[012]¦23/2[123]$
    # Rewrite to real filename
    RewriteRule ^media/(0[1-9]¦1[012])/(0[1-9]¦[12][0-9]¦3[01])/([01][0-9]¦2[0-3])/(gif¦jpg¦swf)/(.+)$ /realpath/$5.$4 [L]
    #
    # Else pick one of these:
    # Return Forbidden response
    RewriteCond ^media/.+(gif¦jpg¦swf) - [F]
    # Show alternate image
    # RewriteCond ^media/.+(gif¦jpg¦swf) /alternate_image.$1 [L]
    [/1]

    This code basically works, but I didn't check *all* of the boundary conditions.

    The only 'hole' should be leap years, where links from Feb 28th and 29th are treated as valid for the first hours of March 1st.

    Again, change all broken pipe "¦" characters in the code above to solid pipes before use, and...
    I banged this out on the keyboard pretty fast, so there may typos in it, just like before.

    Jim

    twist

    4:46 am on Mar 31, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I haven't read all your modifications yet but here is what I have been working on since I read your original post. In the hope to keep it short I switched from month and day of month to just "day of week". It still means that my link is only good for 3 hours 1 day a week. I think that is a fine trade-off for the shorter code. Besides, if a person really wants to hotlink your mp3's or whatever there just going to write their own script to match your time anyway. It should put a damper on casual hotlinkers though I would hope.

    Anyway, here is what I got together since your original post,


    RewriteCond %{TIME_HOUR}{TIME_WDAY}$1 ^$0[012](06¦10¦21¦32¦43¦54¦65)$ [OR]
    RewriteCond %{TIME_WDAY}$1 ^$00¦11¦22¦33¦44¦55¦66$
    RewriteCond %{TIME_HOUR}$2 ^00(2[23]¦00)¦01(23¦0[01])¦020[012]¦030[123]¦040[234]¦050[345]¦060[456]¦070[567]$ [OR]
    RewriteCond %{TIME_HOUR}$2 ^080[678]¦090[789]¦10(0[89]¦10)¦11(09¦1[01])¦121[012]¦131[123]¦141[234]¦151[345]$ [OR]
    RewriteCond %{TIME_HOUR}$2 ^161[456]¦171[567]¦181[678]¦191[789]¦20(1[89]¦20)¦21(19¦2[01])¦222[012]¦232[123]$
    RewriteRule ^media/([0-6])/([012][0-9])/(gif¦jpg¦swf)/(.+)$ /content/$4\.$3 [L]

    I have tested it and it is working great so far, I am on a shared server so I have no access to changing the time, but as luck will have it my server is at 11:41pm at the moment.

    Your a genius by the way. I can't believe how short the code has become.

    jdMorgan

    5:08 am on Mar 31, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I had a previous career as a digital logic designer, so big logic equations are familiar to me.

    I felt bad about sticking you with a big ole chunk of untested code, so I tested it when I got a few minutes. I just temporarily changed all the {TIME_WHATEVER} variables to {ENV:MY_TIME_WHATEVER} variables. This allowed me to force the 'current time' variables to any values I wanted to test using the [E] flag of RewriteRule.

    In doing so, I found several bugs and more typos. Because people often copy code off this forum without reading all the surrounding discussion, I wanted to get rid of that bad code before too many people copied it (anti-hotlinking is a very popular subject). Otherwise, we'd spend several years here helping people fix it, over and over again... :(

    Anyway, if you want to try the new method checking month, day, and hour, you're welcome to it. It's about as compressed as I can get and still fit on the page here (I wanted to avoid side-scrolling).

    Kinda fun! :)

    Jim

    twist

    6:20 am on Mar 31, 2005 (gmt 0)

    WebmasterWorld Senior Member 10+ Year Member



    I shouldn't post until I have done a lot more rereading of your code since you modified it but could this be a possible issue?

    If the TIME_HOUR is 00 and TIME_DAY is 30, the code should allow you to address the previous 2 hours of the day before.

    So {time_day}29/{time_hour}23 should work as a link when it is 30/00 correct?

    If so, won't 30/23 also work at 30/00 since those hours are allowed at 00?

    p.s. I must imagine a lot of people might be interested in this code for files that can't be protected by referrer. You should get any bugs kinked out and repost it in a new thread and add it to the library. I've looked all over the Internet for weeks looking for something like what you've come up with and have found nothing.