Example #1
0
 /**
  * Allow the admin to reset permissions on files.
  */
 public function action_perms()
 {
     global $context, $txt, $modSettings, $package_ftp;
     // Let's try and be good, yes?
     checkSession('get');
     // If we're restoring permissions this is just a pass through really.
     if (isset($_GET['restore'])) {
         create_chmod_control(array(), array(), true);
         fatal_lang_error('no_access', false);
     }
     // This is a time and memory eating ...
     setMemoryLimit('128M');
     @set_time_limit(600);
     // Load up some FTP stuff.
     create_chmod_control();
     if (empty($package_ftp) && !isset($_POST['skip_ftp'])) {
         require_once SUBSDIR . '/FtpConnection.class.php';
         $ftp = new Ftp_Connection(null);
         list($username, $detect_path, $found_path) = $ftp->detect_path(BOARDDIR);
         $context['package_ftp'] = array('server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', 'username' => empty($username) ? isset($modSettings['package_username']) ? $modSettings['package_username'] : '' : $username, 'path' => $detect_path, 'form_elements_only' => true);
     } else {
         $context['ftp_connected'] = true;
     }
     // Define the template.
     $context['page_title'] = $txt['package_file_perms'];
     $context['sub_template'] = 'file_permissions';
     // Define what files we're interested in, as a tree.
     $context['file_tree'] = array(strtr(BOARDDIR, array('\\' => '/')) => array('type' => 'dir', 'contents' => array('agreement.txt' => array('type' => 'file', 'writable_on' => 'standard'), 'Settings.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'Settings_bak.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'attachments' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'avatars' => array('type' => 'dir', 'writable_on' => 'standard'), 'cache' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'custom_avatar_dir' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'smileys' => array('type' => 'dir_recursive', 'writable_on' => 'standard'), 'sources' => array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'), 'themes' => array('type' => 'dir_recursive', 'writable_on' => 'standard', 'contents' => array('default' => array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))))), 'packages' => array('type' => 'dir', 'writable_on' => 'standard', 'contents' => array('temp' => array('type' => 'dir'), 'backup' => array('type' => 'dir'), 'installed.list' => array('type' => 'file', 'writable_on' => 'standard'))))));
     // Directories that can move.
     if (substr(SOURCEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['sources']);
         $context['file_tree'][strtr(SOURCEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard');
     }
     // Moved the cache?
     if (substr(CACHEDIR, 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['cache']);
         $context['file_tree'][strtr(CACHEDIR, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => false, 'writable_on' => 'restrictive');
     }
     // Are we using multiple attachment directories?
     if (!empty($modSettings['currentAttachmentUploadDir'])) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']);
         if (!is_array($modSettings['attachmentUploadDir'])) {
             $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
         }
         // @todo Should we suggest non-current directories be read only?
         foreach ($modSettings['attachmentUploadDir'] as $dir) {
             $context['file_tree'][strtr($dir, array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
         }
     } elseif (substr($modSettings['attachmentUploadDir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['attachments']);
         $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
     }
     if (substr($modSettings['smileys_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['smileys']);
         $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'writable_on' => 'standard');
     }
     if (substr($modSettings['avatar_directory'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['avatars']);
         $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'standard');
     }
     if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen(BOARDDIR)) != BOARDDIR) {
         unset($context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['custom_avatar_dir']);
         $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive');
     }
     // Load up any custom themes.
     require_once SUBSDIR . '/Themes.subs.php';
     $themes = getCustomThemes();
     foreach ($themes as $id => $theme) {
         // Skip the default
         if ($id == 1) {
             continue;
         }
         if (substr(strtolower(strtr($theme['theme_dir'], array('\\' => '/'))), 0, strlen(BOARDDIR) + 7) === strtolower(strtr(BOARDDIR, array('\\' => '/')) . '/themes')) {
             $context['file_tree'][strtr(BOARDDIR, array('\\' => '/'))]['contents']['themes']['contents'][substr($theme['theme_dir'], strlen(BOARDDIR) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true)));
         } else {
             $context['file_tree'][strtr($theme['theme_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true)));
         }
     }
     // If we're submitting then let's move on to another function to keep things cleaner..
     if (isset($_POST['action_changes'])) {
         return $this->action_perms_save();
     }
     $context['look_for'] = array();
     // Are we looking for a particular tree - normally an expansion?
     if (!empty($_REQUEST['find'])) {
         $context['look_for'][] = base64_decode($_REQUEST['find']);
     }
     // Only that tree?
     $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : '';
     if ($context['only_find']) {
         $context['look_for'][] = $context['only_find'];
     }
     // Have we got a load of back-catalogue trees to expand from a submit etc?
     if (!empty($_GET['back_look'])) {
         $potententialTrees = unserialize(base64_decode($_GET['back_look']));
         foreach ($potententialTrees as $tree) {
             $context['look_for'][] = $tree;
         }
     }
     // ... maybe posted?
     if (!empty($_POST['back_look'])) {
         $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']);
     }
     $context['back_look_data'] = base64_encode(serialize(array_slice($context['look_for'], 0, 15)));
     // Are we finding more files than first thought?
     $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0;
     // Don't list more than this many files in a directory.
     $context['file_limit'] = 150;
     // How many levels shall we show?
     $context['default_level'] = empty($context['only_find']) ? 2 : 25;
     // This will be used if we end up catching XML data.
     $context['xml_data'] = array('roots' => array('identifier' => 'root', 'children' => array(array('value' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])))), 'folders' => array('identifier' => 'folder', 'children' => array()));
     foreach ($context['file_tree'] as $path => $data) {
         // Run this directory.
         if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) {
             // Get the first level down only.
             fetchPerms__recursive($path, $context['file_tree'][$path], 1);
             $context['file_tree'][$path]['perms'] = array('chmod' => @is_writable($path), 'perms' => @fileperms($path));
         } else {
             unset($context['file_tree'][$path]);
         }
     }
     // Is this actually xml?
     if (isset($_GET['xml'])) {
         loadTemplate('Xml');
         $context['sub_template'] = 'generic_xml';
         Template_Layers::getInstance()->removeAll();
     }
 }
Example #2
0
function fetchPerms__recursive($path, &$data, $level)
{
    global $context;
    $isLikelyPath = false;
    foreach ($context['look_for'] as $possiblePath) {
        if (substr($possiblePath, 0, strlen($path)) == $path) {
            $isLikelyPath = true;
        }
    }
    // Is this where we stop?
    if (isset($_GET['xml']) && !empty($context['look_for']) && !$isLikelyPath) {
        return;
    } elseif ($level > $context['default_level'] && !$isLikelyPath) {
        return;
    }
    // Are we actually interested in saving this data?
    $save_data = empty($context['only_find']) || $context['only_find'] == $path;
    //!!! Shouldn't happen - but better error message?
    if (!is_dir($path)) {
        fatal_lang_error('no_access', false);
    }
    // This is where we put stuff we've found for sorting.
    $foundData = array('files' => array(), 'folders' => array());
    $dh = opendir($path);
    while ($entry = readdir($dh)) {
        // Some kind of file?
        if (!is_dir($path . '/' . $entry)) {
            // Are we listing PHP files in this directory?
            if ($save_data && !empty($data['list_contents']) && substr($entry, -4) == '.php') {
                $foundData['files'][$entry] = true;
            } elseif ($save_data && isset($data['contents'][$entry])) {
                $foundData['files'][$entry] = true;
            }
        } elseif ($entry != '.' && $entry != '..') {
            // Going further?
            if (!empty($data['type']) && $data['type'] == 'dir_recursive' || isset($data['contents'][$entry]) && (!empty($data['contents'][$entry]['list_contents']) || !empty($data['contents'][$entry]['type']) && $data['contents'][$entry]['type'] == 'dir_recursive')) {
                if (!isset($data['contents'][$entry])) {
                    $foundData['folders'][$entry] = 'dir_recursive';
                } else {
                    $foundData['folders'][$entry] = true;
                }
                // If this wasn't expected inherit the recusiveness...
                if (!isset($data['contents'][$entry])) {
                    // We need to do this as we will be going all recursive.
                    $data['contents'][$entry] = array('type' => 'dir_recursive');
                }
                // Actually do the recursive stuff...
                fetchPerms__recursive($path . '/' . $entry, $data['contents'][$entry], $level + 1);
            } elseif (isset($data['contents'][$entry])) {
                $foundData['folders'][$entry] = true;
            }
            // Otherwise we stop here.
        }
    }
    closedir($dh);
    // Nothing to see here?
    if (!$save_data) {
        return;
    }
    // Now actually add the data, starting with the folders.
    ksort($foundData['folders']);
    foreach ($foundData['folders'] as $folder => $type) {
        $additional_data = array('perms' => array('chmod' => @is_writable($path . '/' . $folder), 'perms' => @fileperms($path . '/' . $folder)));
        if ($type !== true) {
            $additional_data['type'] = $type;
        }
        // If there's an offset ignore any folders in XML mode.
        if (isset($_GET['xml']) && $context['file_offset'] == 0) {
            $context['xml_data']['folders']['children'][] = array('attributes' => array('writable' => $additional_data['perms']['chmod'] ? 1 : 0, 'permissions' => substr(sprintf('%o', $additional_data['perms']['perms']), -4), 'folder' => 1, 'path' => $context['only_find'], 'level' => $level, 'more' => 0, 'offset' => $context['file_offset'], 'my_ident' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'] . '/' . $folder), 'ident' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])), 'value' => $folder);
        } elseif (!isset($_GET['xml'])) {
            if (isset($data['contents'][$folder])) {
                $data['contents'][$folder] = array_merge($data['contents'][$folder], $additional_data);
            } else {
                $data['contents'][$folder] = $additional_data;
            }
        }
    }
    // Now we want to do a similar thing with files.
    ksort($foundData['files']);
    $counter = -1;
    foreach ($foundData['files'] as $file => $dummy) {
        $counter++;
        // Have we reached our offset?
        if ($context['file_offset'] > $counter) {
            continue;
        }
        // Gone too far?
        if ($counter > $context['file_offset'] + $context['file_limit']) {
            continue;
        }
        $additional_data = array('perms' => array('chmod' => @is_writable($path . '/' . $file), 'perms' => @fileperms($path . '/' . $file)));
        // XML?
        if (isset($_GET['xml'])) {
            $context['xml_data']['folders']['children'][] = array('attributes' => array('writable' => $additional_data['perms']['chmod'] ? 1 : 0, 'permissions' => substr(sprintf('%o', $additional_data['perms']['perms']), -4), 'folder' => 0, 'path' => $context['only_find'], 'level' => $level, 'more' => $counter == $context['file_offset'] + $context['file_limit'] ? 1 : 0, 'offset' => $context['file_offset'], 'my_ident' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'] . '/' . $file), 'ident' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])), 'value' => $file);
        } elseif ($counter != $context['file_offset'] + $context['file_limit']) {
            if (isset($data['contents'][$file])) {
                $data['contents'][$file] = array_merge($data['contents'][$file], $additional_data);
            } else {
                $data['contents'][$file] = $additional_data;
            }
        }
    }
}