I tried to link to a swf located in a module folder but kept getting a "file not found" error. After a couple of hours of painful debugging I tracked it to a line in the URL checking part of the swf function in swftools.module:

// If $file isn't already a valid url...
if (!valid_url($file, TRUE)) {
...

So this code only considers absolute URLs as valid. Removing the restriction to absolute URLs like this:

// If $file isn't already a valid url...
if (!valid_url($file)) {
...

then everything works as it should. I can only conclude that this is by design for some unknown reason, but since it seems to be such a painfully unnecessary restriction, I consider this to be a bug.

Thanks,

Scott

Comments

Stuart Greenfield’s picture

Status: Active » Postponed

It's a while since I looked at this part of the code in detail, but from memory I did try it without the restriction of being an absolute url for a while, but it then caused other issues.

If I remember rightly the routines that try to build file paths and so on failed because the path might point to files outside of the main files directory. There were also some hiccups if the user was using a remote media path.

The work-around is to use a full url to reference the file that you want. In practice, SWF Tools builds full url's anyway, so this doesn't really matter. When SWF Tool encounters a full url it skips the file checks completely.

As part of SWF Tools 7 I'm going to revisit a lot of SWF Tools to try and simplify it.

For now I'm going to set as postponed and I'll come back to this later.

okeedoak’s picture

subscribing

Stuart Greenfield’s picture

Status: Postponed » Needs review

I've rewritten a big chunk of the code to do with file paths.

SWF Tools will now first look to see if it has a valid url. If it has, then it uses that.

Next, it looks to see if it has a path that points to the file system, if it does, it uses that.

Next, if it was just given a filename, it either resolves that the external media directory (if that is enabled), otherwise it resolves to the local file directory.

So when you pass something to swf() the behaviour should be easier to follow. The old code was messy and I've been meaning to work on it for a while.

Will commit the change on CVS and it will be in the next development package when it generates.

japanitrat’s picture

Seems it is still an issue for 3.x

Stuart Greenfield’s picture

Version: 6.x-2.5 » 6.x-3.x-dev
Status: Needs review » Active

How are you calling the function (please post an example, including the actual path you are calling with)?

What result are you expecting and what result are you getting?

Re-reading the original post it describes trying to access a file in a module folder, so I am wondering if SWF Tools is wrongly expanding the path. It might be to do with the way it interprets non-absolute url's, but that in turn is do with trying to support files that might be local, or might be remote! Too many variations for one module :-)

If you can post examples I might be able to see better what the code is doing, and what could be done to accommodate this case.

japanitrat’s picture

ok here is what i got:

  $module_path = drupal_get_path('module', 'xy');
  $swf_path = $module_path . '/test.swf';
  
  swf(
    $swf_path,
    array(
      'params' => array(
        'width' => '100%',
        'height' => '100%',
      )
    )
  );

i refer to some module swf file by using drupal's root. doesn't work (object/params tag there, but no source file referenced)

  // ...
  $swf_path = base_path() . $module_path . '/test.swf';
  // ...

absolute web root path, still not working

  // ...
  $swf_path = 'http://'.$_SERVER['HTTP_HOST'] . base_path() . $module_path . '/test.swf';
  // ...

absolute path with protocol and host, now it works.

Stuart Greenfield’s picture

Ok - now I can see what is going on, and you have found is a case that the filepath handler gets wrong! I think this can be fixed, and I don't think the fix will break other content. I'm going to describe it below to clarify my own thinking...

When you pass a url to SWF Tools it has to work out whether it should be expanded to point to a local file, a remote file, or it is already a proper url. That's the reason the valid_url($file, TRUE) is used first - we specifically check if the caller gave us a full url so we can do nothing.

The next case is you supply just a filename (or a partial path), which in your first example would be "sites/all/modules/xy/test.swf"

In this case SWF Tools looks to see if you are using remote media. If you are then it would expands the path to that (so you'd get http://remote.com/sites/all/modules/xy/test.swf)

But, and here's the problem, if you're not using remote media SWF Tools assumes the file is going to be in sites/default/files.

So SWF Tools will call file_create_path('sites/all/modules/xy/test.swf'). But that path doesn't exist inside sites/default/files so it returns false.

The handling routine recurses to get the full path, so it now processes a blank, and when you call file_create_path('') it returns 'sites/default/files'.

It recurses AGAIN, and now we get /webroot/sites/default/files/site/default/files

The fix, I think, is after doing valid_url($file, TRUE) is to check if we have valid_url($file) && $file starts with '/', in which case we assume the user gave as proper path.

Try adding the following change:

  // If already a valid absolute url simply return it
  if (valid_url($file, TRUE)) {
    $ret['src'] = $file;
    return $ret;
  }
  
  // If a valid url, and starts with /, then assume to be a local path relative to web root
  if (valid_url($file) && strpos($file, '/') === 0) {
    $ret['src'] = $file;
    return $ret;
  }
Stuart Greenfield’s picture

Hmmm, just had a thought.

When we use file_create_path() we call file_check_location() to make sure the user isn't trying to exploit the path to access places they shouldn't.

In the code above we are trusting that the supplied path is good, but it might not be.

So I think some improvement is needed here, but the concept is right.

edit
More thinking - we only ever output the result of this process on to a webpage, so although a malicious user could try passing us a bad path, it is only then used on the webpage, so they can't break out of the web content anyway. So in that case we don't actually need to check because they can't do anything. We'd only need to worry if this path was used to somehow serve or display a file via a different mechanism?
/edit

Stuart Greenfield’s picture

Status: Active » Needs review

Setting to needs review.

On reflection I think the fix is good, and the code is logically. I don't think we have a security issue here as when we output a complete link it's only ever put on the webpage, and therefore attempts to traverse with ../../.. will fail.

So, a full path resolves to a full path, a local path starting with / is kept as a local path starting with /, and a partial path is resolved to eithe the file system, or the remote media directory, depending in the site configuration.

That seems reasonable!

japanitrat’s picture

what exactly is to review? some kind of patch, or latest dev?

Stuart Greenfield’s picture

There's now a BETA package.

I'm using "Needs review" to track the issues that I've fixed, but in this instance there are no patches as there would be far too many!

taxicab’s picture

Here's problem to help add some fodder to the issue:

I've set up a site using local host on the 'local' side of router. To allow people to see the temp work (before uploading to the public site), I've poked a hole into port 80. The 'local' address is 192.168.1.64, but on the internet side it goes through '99.9.17.0'.

So the SWFtools formatting is incorrect. If I have wrong forum, please advise to which I should post.

Example source:
'div class="content clear-block"'
'div class="swftools-wrapper swftools-swf"''div class="swftools"'
object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="940" height="400" id="swf12703461971"
param name="movie" value="http://192.168.1.64/mickeystengel/system/files/MickeyStengel.swf"
param name="allowScriptAccess" value="always"

This works fine on the intranet side, but NOT from the internet side (ie 99.9.17.0).
Interestingly, all the pics come through.

Help?

TIA

Stuart Greenfield’s picture

How are you generating the markup for the movie? The input filter? Or a call to swf() from PHP?

You have a full url in th result but SWF Tools should now generate relative urls unless you give it a full url in the first place. If the path is not qualified wtih http://192.168.1.64, but was just /mickeystengel/system/files/MickeyStengel.swf then it ought to work irrespective of how you accessed the page.

mathieuhelie’s picture

Is there any way to get directory paths back into file names again?

example [swf file="PATH/myfile.flv" stream="rtmp://stream.example.com/streamserver"]

The PATH part gets eaten any way I try.

ThirstySix’s picture

How to set dynamic height,
/.....
swf($filepath, array('params' => array('width' => '550', 'height' => '350')));
/......

Thanks