Support » Plugins » Hacks » How to initialize WP_Filesystem object?

  • Resolved fhsm


    I’m trying to use the the wordpress file system abstraction class in a plugin. I can’t figure out what I’m supposed to pass in to WP_Filesystem to correctly initialize it.

    WordPress(Apache) has write privilege for my uploads dir so it should be able to use direct file system access; however, I’ve found that in my plugin the wp_filesystem is trying to use the FTP ‘driver’. If I add define('FS_METHOD', 'direct'); before calling WP_Filesystem(); and force the direct fs access driver I’m able to use WP_Filesystem as expected.

    I’ve tried WP_Filesystem(array(), 'path/to/my/uploads/dir'); which doesn’t work even though I can write to that path from php in my plugin. Clearly I’m not understanding how get_filesystem_method works when called by WP_Filesystem.

    I don’t want to use FS_METHOD define to force wp_filesystem to the correct driver (for my particular server) as a long term solution. (TL;DR)So what should I be passing for $args and $context to WP_Filesystem to allow the auto detection by get_filesystem_method to work?

Viewing 3 replies - 1 through 3 (of 3 total)
  • dd32


    Meta Developer

    What method does plugin upgrades choose?

    Apache having read/write access to the directory is not enough to cause the direct class to be initialized, This is due to the class checking file ownership as well as RW attributes.

    The cause for ownership testing is mainly related to Shared Hosting. On some shared hosts, infact, many shared hosts, Apache will have write access to the users folders. This in itself is not a problem, but when combined with the host using mod_php or fcgi without suPHP/suExec, this results in ALL users on the server being able to write to other directories. Limiting it to only creating the files if the ownership matches allows us to somewhat, mitigate some of these poor security hosts, If the file is owned by apache, then other users can surely Write to the file, If it’s owned by the user, say, dd32, and we apply RW/Owner, R/Group, R/World (644) this results in other users on the server not being able to modify the .php files. Directly modifying the files has been the root cause of many hoster/server-wide exploitation attacks in the last few years.

    Now, As for what you need to pass WP_Filesystem() to get it to return a Direct context on a server which nativly supports it in wordpress: Nothing, It’ll automatically select it, and in your case, it sounds like WordPress has decided using the Direct class is not an option.

    You may want to have a read of this function:

    and you may also want to look at the selection method: get_filesystem_method() – specifically, the filter there, ‘filesystem_method’

    If you wish to force it, then my suggestion would be something such as this, But i fear it may still cause issues if something else is using WP_Filesystem on the same page load.

    function _return_direct() { return 'direct'; }
    add_filter('filesystem_method', '_return_direct');
    remove_filter('filesystem_method', '_return_direct');
    Thread Starter fhsm


    Thanks for the reply. I’ve actually spent a good deal of time looking at the code you’ve linked (I linked in the op).

    What advantage does the function you provided have over just setting FS_METHOD constant to ‘direct’?

    The WP_Filesystem accepts args & context and passes them on to get_filesystem_method. It looks like $args get passed to the ‘driver’ classes for things like login, pw etc but $context is used as a file system path to test ownership etc as you mentioned.

    My www root is owned by & in the root group; however, I’ve chgrp-ed & chown-ed uploads/ & blogs.dir/ to apache. As a result on my server plugin’s aren’t upgradable with direct access (b/c WP is in a different group, different UID and lacks FS permissions). When I do the override with FS_METHOD the resulting files in uploads/ & blogs.dir/ both have the expected ownership, group & permissions. All of which leaves me to believe something is going wrong with the detection.

    If get_filesystem_method() does its write-testing in WP_CONTENT_DIR I’d expect it to fail, so it seems like this is a good use for $context… if I could figure out how to use it.

    Thread Starter fhsm


    I’ve really RTFC on this one and think the WP_Filesystem object shouldn’t be beyond my comprehension. So at frustration overload and decided to pull apart the core code, when I did so I found something a bit odd. In file.php on line 842 getmyuid() is called if ( getmyuid() == @fileowner($temp_file_name) ).

    If you have a look at bozo_z_clown at yahoo dot com‘s comment on (s)he will draw your attention to how strange this functions behavior is. The docs (“Gets PHP script owner’s UID”) should put more attention on script owner’s UID. It’s not the UID of the running process, it’s actually the UID of the file that the process is interpreting at present. In other words if the running process might loads N files (require/include etc) in responding to a single hit the value of getmyuid() could be N different ints depending on where it’s called.

    To my mind the more useful function is posix_getuid which returns the actual running process and results in the expected (perhaps correct?) behavior on my server when swapped for getuid at line 842.

    This feels like a bug to me. I’m not sure if the intended security benefits are really recognized, if it’s that big of a problem (the file system should restrict application code not the other way around), and if this isn’t a case of tossing the baby with the bathwater.

    Turns out I’m not the only person who thinks this is a bug, bug, bug. Thanks to joelhardi, after 17 mo and an attempt to close the bug, a patch is awaiting review.

    On the plus side I learned in my first trip into substantive wp dev that the bug tracker isn’t all that well indexed by google; on the downside, I found the bug tracker.

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘How to initialize WP_Filesystem object?’ is closed to new replies.