Hi, etully,

Thanks a lot for looking into this further. I tried using the text/plain header again - which is what I think you are asking me to try - but it didn't solve the problem.

My assumption was that when testing the PHP script in a browser, I should have seen a message like "what do you want to do with this Flash Video File?" instead of the "What do you want to do with this PHP file?" Is that what I should expect to see?

I would love to figure this out because, as it stands now, I have no idea how else I can secure the FLV file locations from unauthorized download. As I mentioned before, I can get it to work somewhat by using the Video object instead of the FLVPlayback component in Flash, but it still doesn't progressively load into the Flash which is what needs to happen for usability purposes.

Any other ideas? In lieu of solving the PHP/Flash problem, what else could I do to prevent the FLV files from being downloaded by unregistered users?

Sorry to add more chaos to your universe... :queasy:

Joe

    I tried using the text/plain header again - which is what I think you are asking me to try

    No... There are other significant differences between the two headers. In addition to the text/plain content type, these also appear when you call a true FLV file:

    ETag: "80c0e8-5e01c4-533b5640"
    Accept-Ranges: bytes
    Content-Length: 6160836
    Content-Type: text/plain; charset=ISO-8859-1
    Length: 6,160,836 (5.9M) [text/plain]
    

    You should use the header command to generate those... and it should work.

    It should work because once you make the headers the same - then the two downloads will be precisely the same. Exactly precisely the same. When they are the same, the client can't possibly know whether the source was a true FLV file or a PHP script handing out a PHP file.

      Hi, etully,

      I tried using all the headers you specified - plus a set from my own "get headers" experiments - all without success: the FLVPlayback still won't load an FLV served up with my PHP script.

      Any other ideas?

      Thanks,

      Joe

        Hi, etully,

        I just installed and tried wget in the way you suggested.

        I noticed that a wget for resource.php reports the correct MIME type, but is definitely not retrieving the actual FLV file because the Length is reported as 262, whereas the test.flv Length is 5,967,743.

        wget for test.flv

        HTTP/1.1 200 OK
        Date: Wed, 25 Jul 2007 18:58:50 GMT
        Server: Apache/2.0.55 (Win32) PHP/4.4.6
        Last-Modified: Wed, 27 Jun 2007 02:09:29 GMT
        ETag: "7648-5b0f7f-bc76e8c3"
        Accept-Ranges: bytes
        Content-Length: 5967743
        Keep-Alive: timeout=15, max=100
        Connection: Keep-Alive
        Content-Type: video/x-flv
        Length: 5,967,743 (5.7M) [video/x-flv]

        wget for resource.php

        HTTP/1.1 200 OK
        Date: Wed, 25 Jul 2007 18:59:07 GMT
        Server: Apache/2.0.55 (Win32) PHP/4.4.6
        X-Powered-By: PHP/4.4.6
        Content-Length: 262
        Keep-Alive: timeout=15, max=100
        Connection: Keep-Alive
        Content-Type: video/x-flv
        Length: 262 [video/x-flv]

        Anyway, in my PHP script I set every header returned by the wget request for the the test.flv file.

        header('Date: Wed, 25 Jul 2007 18:58:50 GMT');
        header('Server: Apache/2.0.55 (Win32) PHP/4.4.6');
        header('Last-Modified: Wed, 27 Jun 2007 02:09:29 GMT');
        header('ETag: "7648-5b0f7f-bc76e8c3"');
        header('Accept-Ranges: bytes');
        header('Content-Length: 5967743');
        header('Keep-Alive: timeout=15, max=100');
        header('Connection: Keep-Alive');
        header('Content-Type: video/x-flv');
        header('Length: 5,967,743 (5.7M) [video/x-flv]');
        readfile("resources\test.flv");

        But it still doesn't work. Any other ideas?

        J

          Ok. This is my last suggestion. It's based on the fact that the output size was only 262. I'm going to guess that readfile() isn't doing what it's supposed to be doing. (Maybe that was the problem all along?)

          Replace the readfile command with this:

              $filename = "test.flv";
              $fd = fopen($filename, "r");
              while(!feof($fd)) {
                   echo fread($fd, 4096);
                  flush();
              }
              fclose ($fd);
          

          You may need to try a few different values instead of the 4096. If the 4096 doesn't work, try a million - or even 6 million. I'm not too clear on what effect that has. You might even try replacing it with filesize($filename)

          When you try this, point wget at the resource.php script and see if you can get that Length: to reflect the correct size of the FLV file. If that doesn't work let me know and I'll run the test on my server. If it works on my Linux server, then I'm going to have to ask you to abandon your Windows server. 🙂

            etully, I think we may be getting somewhere with this... I tried the code you supplied, tinkered with it slightly after some trial and error, and ended up with:

            $filename = "resources/test.flv";
            header('Content-Type: video/x-flv');
            header('Length: ' . filesize($filename));
            $fd = fopen($filename, "r");
            while(!feof($fd)) {
            	echo fread($fd, filesize($filename));
            	flush();
            	}
            fclose ($fd);

            When I request resource.php with wget, it still downloads a file called "resource.php" but now that file is 5 MB in size (instead of 262 bytes) and I have confirmed that it is, in fact, the original Flash Video file. 🙂 (If I rename it with a .flv extension, it will play in my desktop FLV player.)

            I suspect that if we can get this PHP script to serve up the FLV with the right file name - or even just with an .flv extension - it ought to load into my FLVPlayback component properly.

            What do you think?

            J

              If you want the file to be saved by the user, add this header :

              header('Content-Disposition: attachment; filename="file.flv"');

              (where file.flv is the filename you want to user to see)...

              Also, if you want to use etully's solution to send a line and then flush it, you should use fgets() that simply read a file line by line, no matter how many bites... see http://www.php.net/fgets

                pasiphilo wrote:

                When I request resource.php with wget, it still downloads a file called "resource.php" but now that file is 5 MB in size (instead of 262 bytes)

                And what happens when you point your Flash player at this PHP script to load the "flv"?

                pasiphilo wrote:

                I suspect that if we can get this PHP script to serve up the FLV with the right file name - or even just with an .flv extension - it ought to load into my FLVPlayback component properly.

                Why do you need to mess with the filename? The flash player just wants to see a stream of bits come down the line - most programs don't care what the file name is because they know that often, they are getting piped through an intermediary just like you're doing now.

                Try using your Flash player to connect to your server and request the PHP script. It should work.

                  If you want the file to be saved by the user, add this header :

                  I actually need the file to get loaded into my Flash app as opposed to being downloaded by the user. I did try the Content-Disposition header as a means of forcing the correct filename, but that didn't work for the Flash app.

                  And what happens when you point your Flash player at this PHP script to load the "flv"

                  Believe me, that was the very next thing I tried, but that part still doesn't work.

                  Why do you need to mess with the filename? The flash player just wants to see a stream of bits come down the line

                  The FLV isn't actually streaming (since I'm not using a streaming server) but loading progressively into the Flash app. I'm 90% sure that the FLVPlayback component will not load anything without a .flv extension whether streamed or not, however.

                  Is there no way to serve up the FLV from PHP with the correct file extension?

                    Is there no way to serve up the FLV from PHP with the correct file extension?

                    You sir, are in luck. As mentioned earlier in this very thread, you can have FLV files parsed for PHP.

                    Do this:

                    1. create a directory called resources (you've already done that)
                    2. put the FLV in there but change the extension to something like XXX or whatever
                    3. put the PHP serving file in the resources directory too
                    4. change the extension of the PHP file to FLV
                    5. create a file called .htaccess (note the dot at the beginning of the name)
                    6. The entire contents of the file are:
                      AddType application/x-httpd-php .flv
                    7. put the .htaccess file inside the resources directory
                    8. double check the PHP script to make sure that it includes the FLV file by the new name (.xxx)
                    9. point your Flash player at the PHP script that has the new FLV extension

                    This will solve your problem IF you are correct that the Flash player is determined to get the file with an FLV extension.

                    By the way, this is just one way to make your web server serve up a file with a different name than what the user thinks they're asking for. There is another way called a rewrite rule but for this situation, I think the .htaccess solution is more elegant.

                      etully... IT WORKS! 😃

                      That extension switcheroo trick cinched it. You are awesome!

                      Here is the working solution, consolidated into one post for anyone else who ever has this problem...

                      The files in the "resources/" folder:

                      resources/
                      -- .htaccess
                      -- test.xxx (a renamed FLV file)
                      -- resource.flv (a renamed PHP script)

                      The .htaccess file:

                      AddType application/x-httpd-php .flv

                      The PHP script (renamed to "resource.flv"):

                      $filename = "test.xxx";
                      header('Content-Type: video/x-flv');
                      header('Length: ' . filesize($filename));
                      header('Content-Disposition: attachment; filename="'.$filename.'"');
                      $fd = fopen($filename, "r");
                      while(!feof($fd)) {
                      	echo fread($fd, filesize($filename));
                      	flush();
                      	}
                      fclose ($fd);

                      The salient ActionScript:

                      //my FLVPlayback compontent instance is named "video"
                      video.load("http://www.myserver.com/resources/resource.flv");

                      That should cover it.

                      Thanks again for all your help! I hereby promote you to "Señor" Curmudgeon. 😉

                      J

                        Cool!!

                        I'm a little disappointed in Flash that it needs the FLV extension. Maybe it's just the player you are using but if it's a requirement of Flash, they should know that people often have reasons to name files something other than .flv (your situation is a textbook example).

                        Note, for your own edification, that by putting the .htaccess file in the resources directory, you are telling your web server that you only want FLV's parsed for PHP when they are inside this directory. You could have put the .htaccess file one directory up (in your root) but then every FLV file that you ever put on your web site would be parsed for PHP which would slow your web server down because you're forcing it to look for PHP code in files where none exists.

                        Also be aware that now that we know the cause of the problem it's possible that you could use the readfile() command instead of the fopen code. It's also possible that the Content-Type doesn't actually need to be "video/x-flv". I understand that you have the system working and don't want to break it but do realize that those parts might not be strictly necessary.

                        I hereby promote you to "Señor" Curmudgeon

                        One of our experts here (Weedpacket) used Señor Curmudgeon and my title is a little nod to his wisdom and experience. Thank you for the vote of confidence but I will remain Juñor for quite some time.

                          I'm a little disappointed in Flash that it needs the FLV extension.

                          This is the error I was getting from Flash before trying the file extension trick, when it thought it was getting a .php file:

                          1005: Invalid xml: URL: "http://www.myserver.com/resource.php" No root node found; 
                          if file is an flv it must have .flv extension

                          Your warnings about the .htaccess file and the extraneous headers are well heeded; I'll be fine tuning further as I integrate this solution into the final application.

                          Thanks again,

                          J

                            Hi, etully,

                            I just hit a (hopefully minor) snag, something I should have accounted for before now: My full-blown app needs to send an id in the querystring to the resource.flv, like so:

                            resource.php?id=12345

                            I'm finding that when calling resource.flv (PHP) from the Flash like above, the querystring gets appended to the filename extension returned, so instead of feeding "resource.flv" into the Flash, the script returns "resource.flv@id=12345" instead, meaning it no longer has that much-needed .flv file extension. (Flash seems to interpret ".flv@id=12345" as the whole file extension, in other words.)

                            You mentioned a "rewrite rule" a couple of posts back that might serve as an alternative for rewriting the file name. Could we try that?

                              Add this to the bottom of your .htaccess file:

                              RewriteEngine on
                              RewriteCond %{REQUEST_URI} .*translate.*
                              RewriteRule .*translate-(.*)\.flv resource.flv?$1
                              

                              Now, when you call your FLV file, give it a name like this:

                              translate-id=12345.flv
                              

                              This way, Flash is requesting "X" and when the web server hears the request, it looks for "Y" instead and sends the data back to Flash.

                              The PHP script thinks that the user actually requested "resource.flv?id=12345" but Flash thinks that it asked for translate-id=12345.flv

                              The rewrite rule looks for TRANSLATE - (something) . FLV

                              and converts it to: RESOURCE.FLV?(somthing)

                              So whatever the "something" is gets tacked onto the end after the question mark.

                              The only caveat is that you can no longer use any files in the resources directory with the word "translate" in their title because when you try to call them they would get converted!

                                It's kind of bad form to use re-write rules and "AddType application/x-httpd-php" at the same time. That can make for a real headache when someone else has to figure out what you did when you are no longer involved with the project.

                                The "correct" way to handle this should be to take out the "AddType" directive in .htaccess and make the rewrite condition change the name from translate-id=12345.flv to resource.php?x=12345

                                (and change the name of resource.flv back to resource.php of course. And change the name of test.xxx back to test.flv. And change the PHP script so that it's once again calling an FLV file instead of an XXX file.)

                                Everything should work fine if you don't make these changes... but you always need to consider that if you get hit by a bus, someone else is going to have to figure out what kind of crazy maze you built.

                                  Hey, etully,

                                  I had already decided to try reverting all the renaming, etc, as I figured out that it was no longer needed with the rewrite rules. I'm all for keeping things sane.

                                  Now for the crazy part: While implementing these latest fixes, I stumbled upon - quite by accident - a much simpler and incredibly stupid fix (hack) for this whole serving-an-FLV-to-FLVPlayback-with-PHP issue.

                                  Remember our initial attempts involving the PHP script that used readfile() to send an FLV back, the method that fed a file with a .php extension back to Flash? Well, I found that if I simply use that same script, but adjust the call to it like so:

                                  resource.php?id=12345[B]&f=.flv[/B]

                                  That trailing ".flv" in the last name/value pair is persisted when it goes back to the Flash, so the FLVPlayback component is satisfied that it received a FLV file.

                                  :queasy:

                                  You want to know how I figured that out? After implementing your latest rewrite rule fix, I blindly tested on my local box (Windows) and was surprised to find that it worked - surprised because I don't have the mod_rewrite installed on my Windows box. After that, I realized that the ".flv" in your "translate-id=12345.flv" call was the key.

                                  It seems to work both locally (Windows) and remotely (Linux) on all my target browsers (in case that involves browser functionality), but I'll be 100% certain when I'm done.

                                  How crazy is that?

                                  J

                                    Well, I'm not really in love with that solution.

                                    Don't get me wrong - it will work - but it just makes me a little nervous. Something about it isn't elegant.

                                    I guess it's that you're using the get string for something it wasn't designed to be used for. The rewrite tool was specifically designed for this exact situation.

                                    I don't know what to tell you - I'm a curmudgeon.

                                    It's clever though - I'll give you that. I wouldn't have thought of it.

                                      When developing, you want things to go as quick as possible, if you can avoid something to speed things up, avoid it !

                                      In your case, don't use mod_rewrite and use pasiphilo's solution... I don't understand how you can find that non elegant... will people see the URL ? No !

                                      This way, you'll get a direct request to the PHP script, so a (tiny) bit more speed 😉

                                      If you don't want unused get variables, you could do something like this :
                                      resource.php?id=12345.flv

                                      And then substr the string to remove the .flv (substr($_GET['id'], 0, -4))...