Example #1
0
 /**
  * This is the function called when we need to recompute the stats
  */
 public function collect()
 {
     $this->logger->log(__METHOD__, NULL, WATCHDOG_DEBUG);
     // exec external bootstraper.php file (you need php cli and exec rights on this file)
     $path = DRUPAL_ROOT . '/' . drupal_get_path('module', 'prod') . '/bootstrapper.php';
     $this->logger->log('External Bootstrapper file path is :path', array(':path' => $path), WATCHDOG_DEBUG);
     $out = array();
     // Ensure executions rights (scripts may remove theses rights on a regular basis)
     drupal_chmod($path, '0775');
     // EXECUTE External command!
     if (exec($path, $out)) {
         $first = TRUE;
         foreach ($out as $line) {
             $this->logger->log("Exec output line : " . $line, NULL, WATCHDOG_DEBUG);
             if ($first) {
                 if ('bootstrapper success run' !== $line) {
                     $this->logger->log("Bootstrapper time monitor script failure, first line of output is: :line", array(':line' => $line), WATCHDOG_WARNING);
                     break;
                 }
                 $first = FALSE;
             } else {
                 $line_split = explode('=', $line);
                 if (array_key_exists($line_split[0], $this->known_times)) {
                     // Note: no * 1000 because value is already in milliseconds
                     // a bootstrap_full_abs=127 means 0.127s
                     $this->known_times[$line_split[0]]['value'] = (int) $line_split[1];
                     $this->known_times[$line_split[0]]['timestamp'] = REQUEST_TIME;
                 }
             }
         }
         // end result loop
     }
     $this->save();
     $this->manageRRD();
 }
Example #2
0
 /**
  * Test directory handling functions.
  */
 function testFileCheckDirectoryHandling()
 {
     // A directory to operate on.
     $directory = file_default_scheme() . '://' . $this->randomMachineName() . '/' . $this->randomMachineName();
     $this->assertFalse(is_dir($directory), 'Directory does not exist prior to testing.');
     // Non-existent directory.
     $this->assertFalse(file_prepare_directory($directory, 0), 'Error reported for non-existing directory.', 'File');
     // Make a directory.
     $this->assertTrue(file_prepare_directory($directory, FILE_CREATE_DIRECTORY), 'No error reported when creating a new directory.', 'File');
     // Make sure directory actually exists.
     $this->assertTrue(is_dir($directory), 'Directory actually exists.', 'File');
     if (substr(PHP_OS, 0, 3) != 'WIN') {
         // PHP on Windows doesn't support any kind of useful read-only mode for
         // directories. When executing a chmod() on a directory, PHP only sets the
         // read-only flag, which doesn't prevent files to actually be written
         // in the directory on any recent version of Windows.
         // Make directory read only.
         @drupal_chmod($directory, 0444);
         $this->assertFalse(file_prepare_directory($directory, 0), 'Error reported for a non-writeable directory.', 'File');
         // Test directory permission modification.
         $this->setSetting('file_chmod_directory', 0777);
         $this->assertTrue(file_prepare_directory($directory, FILE_MODIFY_PERMISSIONS), 'No error reported when making directory writeable.', 'File');
     }
     // Test that the directory has the correct permissions.
     $this->assertDirectoryPermissions($directory, 0777, 'file_chmod_directory setting is respected.');
     // Remove .htaccess file to then test that it gets re-created.
     @drupal_unlink(file_default_scheme() . '://.htaccess');
     $this->assertFalse(is_file(file_default_scheme() . '://.htaccess'), 'Successfully removed the .htaccess file in the files directory.', 'File');
     file_ensure_htaccess();
     $this->assertTrue(is_file(file_default_scheme() . '://.htaccess'), 'Successfully re-created the .htaccess file in the files directory.', 'File');
     // Verify contents of .htaccess file.
     $file = file_get_contents(file_default_scheme() . '://.htaccess');
     $this->assertEqual($file, FileStorage::htaccessLines(FALSE), 'The .htaccess file contains the proper content.', 'File');
 }
    public function parse(ServicesContextInterface $context) {

        global $user;

        $destination = DATASET_FILE_STORAGE_DESTINATION;
        if (substr($destination, -1) != '/') {
            $destination .= '/';
        }

        $file = new stdClass();
        $file->uid = $user->uid;
        $file->status = 0;
        $file->filename = uniqid('push-api_');
        $file->uri = file_destination($destination . $file->filename, FILE_EXISTS_RENAME);
        $file->filemime = 'text/csv';

        if ( false === file_put_contents($file->uri,$context->getRequestBody()) ) {
            throw new IllegalArgumentException(t('Could not store received data on file system'));
        }
        drupal_chmod($file->uri);

        file_save($file);

        return array(PARAMETER_NAME_CONTENT => $file);
    }
 /**
  * Test write functionality of the read-only stream wrapper.
  */
 function testWriteFunctions()
 {
     // Generate a test file
     $filename = $this->randomMachineName();
     $filepath = conf_path() . '/files/' . $filename;
     file_put_contents($filepath, $filename);
     // Generate a read-only stream wrapper instance
     $uri = $this->scheme . '://' . $filename;
     file_stream_wrapper_get_instance_by_scheme($this->scheme);
     // Attempt to open a file in read/write mode
     $handle = @fopen($uri, 'r+');
     $this->assertFalse($handle, 'Unable to open a file for reading and writing with the read-only stream wrapper.');
     // Attempt to open a file in binary read mode
     $handle = fopen($uri, 'rb');
     $this->assertTrue($handle, 'Able to open a file for reading in binary mode with the read-only stream wrapper.');
     $this->assertTrue(fclose($handle), 'Able to close file opened in binary mode using the read_only stream wrapper.');
     // Attempt to open a file in text read mode
     $handle = fopen($uri, 'rt');
     $this->assertTrue($handle, 'Able to open a file for reading in text mode with the read-only stream wrapper.');
     $this->assertTrue(fclose($handle), 'Able to close file opened in text mode using the read_only stream wrapper.');
     // Attempt to open a file in read mode
     $handle = fopen($uri, 'r');
     $this->assertTrue($handle, 'Able to open a file for reading with the read-only stream wrapper.');
     // Attempt to change file permissions
     $this->assertFalse(@drupal_chmod($uri, 0777), 'Unable to change file permissions when using read-only stream wrapper.');
     // Attempt to acquire an exclusive lock for writing
     $this->assertFalse(@flock($handle, LOCK_EX | LOCK_NB), 'Unable to acquire an exclusive lock using the read-only stream wrapper.');
     // Attempt to obtain a shared lock
     $this->assertTrue(flock($handle, LOCK_SH | LOCK_NB), 'Able to acquire a shared lock using the read-only stream wrapper.');
     // Attempt to release a shared lock
     $this->assertTrue(flock($handle, LOCK_UN | LOCK_NB), 'Able to release a shared lock using the read-only stream wrapper.');
     // Attempt to write to the file
     $this->assertFalse(@fwrite($handle, $this->randomMachineName()), 'Unable to write to file using the read-only stream wrapper.');
     // Attempt to flush output to the file
     $this->assertFalse(@fflush($handle), 'Unable to flush output to file using the read-only stream wrapper.');
     // Attempt to close the stream.  (Suppress errors, as fclose triggers fflush.)
     $this->assertTrue(fclose($handle), 'Able to close file using the read_only stream wrapper.');
     // Test the rename() function
     $this->assertFalse(@rename($uri, $this->scheme . '://newname.txt'), 'Unable to rename files using the read-only stream wrapper.');
     // Test the unlink() function
     $this->assertTrue(@drupal_unlink($uri), 'Able to unlink file using read-only stream wrapper.');
     $this->assertTrue(file_exists($filepath), 'Unlink File was not actually deleted.');
     // Test the mkdir() function by attempting to create a directory.
     $dirname = $this->randomMachineName();
     $dir = conf_path() . '/files/' . $dirname;
     $readonlydir = $this->scheme . '://' . $dirname;
     $this->assertFalse(@drupal_mkdir($readonlydir, 0775, 0), 'Unable to create directory with read-only stream wrapper.');
     // Create a temporary directory for testing purposes
     $this->assertTrue(drupal_mkdir($dir), 'Test directory created.');
     // Test the rmdir() function by attempting to remove the directory.
     $this->assertFalse(@drupal_rmdir($readonlydir), 'Unable to delete directory with read-only stream wrapper.');
     // Remove the temporary directory.
     drupal_rmdir($dir);
 }
 /**
  * {@inheritdoc}
  */
 public static function value(array &$element, &$input, FormStateInterface $form_state)
 {
     if (!empty($input['filefield_flysystem']['filename'])) {
         $instance = entity_load('field_config', $element['#entity_type'] . '.' . $element['#bundle'] . '.' . $element['#field_name']);
         $filepath = $input['filefield_flysystem']['filename'];
         $directory = $element['#upload_location'];
         $mode = Settings::get('file_chmod_directory', FILE_CHMOD_DIRECTORY);
         if (!drupal_chmod($directory, $mode) && !file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
             \Drupal::logger('filefield_sources')->log(E_NOTICE, 'File %file could not be copied, because the destination directory %destination is not configured correctly.', array('%file' => $filepath, '%destination' => drupal_realpath($directory)));
             drupal_set_message(t('The specified file %file could not be copied, because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', array('%file' => $filepath)), 'error');
             return;
         }
         // Clean up the file name extensions and transliterate.
         $original_filepath = $filepath;
         $new_filepath = filefield_sources_clean_filename($filepath, $instance->getSetting('file_extensions'));
         rename($filepath, $new_filepath);
         $filepath = $new_filepath;
         // Run all the normal validations, minus file size restrictions.
         $validators = $element['#upload_validators'];
         if (isset($validators['file_validate_size'])) {
             unset($validators['file_validate_size']);
         }
         // Serve files from source folder directly.
         if ($element['#filefield_sources_settings']['flysystem']['attach_mode'] == FILEFIELD_SOURCE_FLYSYSTEM_ATTACH_MODE_SERVEFROMFOLDER) {
             $directory = $filepath;
             if ($file = filefield_sources_flysystem_save_file_servefromattach($filepath, $validators, $directory)) {
                 if (!in_array($file->id(), $input['fids'])) {
                     $input['fids'][] = $file->id();
                 }
             }
         } else {
             if ($file = filefield_sources_save_file($filepath, $validators, $directory)) {
                 if (!in_array($file->id(), $input['fids'])) {
                     $input['fids'][] = $file->id();
                 }
                 // Delete the original file if "moving" the file instead of copying.
                 if ($element['#filefield_sources_settings']['flysystem']['attach_mode'] !== FILEFIELD_SOURCE_FLYSYSTEM_ATTACH_MODE_COPY) {
                     @unlink($filepath);
                 }
             }
         }
         // Restore the original file name if the file still exists.
         if (file_exists($filepath) && $filepath != $original_filepath) {
             rename($filepath, $original_filepath);
         }
         $input['filefield_flysystem']['filename'] = '';
     }
 }
Example #6
0
 /**
  * {@inheritdoc}
  */
 public static function value(array &$element, &$input, FormStateInterface $form_state)
 {
     if (isset($input['filefield_clipboard']['contents']) && strlen($input['filefield_clipboard']['contents']) > 0) {
         // Check that the destination is writable.
         $temporary_directory = 'temporary://';
         if (!file_prepare_directory($temporary_directory, FILE_MODIFY_PERMISSIONS)) {
             \Drupal::logger('filefield_sources')->log(E_NOTICE, 'The directory %directory is not writable, because it does not have the correct permissions set.', array('%directory' => drupal_realpath($temporary_directory)));
             drupal_set_message(t('The file could not be transferred because the temporary directory is not writable.'), 'error');
             return;
         }
         // Check that the destination is writable.
         $directory = $element['#upload_location'];
         $mode = Settings::get('file_chmod_directory', FILE_CHMOD_DIRECTORY);
         // This first chmod check is for other systems such as S3, which don't
         // work with file_prepare_directory().
         if (!drupal_chmod($directory, $mode) && !file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
             $url = $input['filefield_clipboard']['filename'];
             \Drupal::logger('filefield_sources')->log(E_NOTICE, 'File %file could not be copied, because the destination directory %destination is not configured correctly.', array('%file' => $url, '%destination' => drupal_realpath($directory)));
             drupal_set_message(t('The specified file %file could not be copied, because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', array('%file' => $url)), 'error');
             return;
         }
         // Split the file information in mimetype and base64 encoded binary.
         $base64_data = $input['filefield_clipboard']['contents'];
         $comma_position = strpos($base64_data, ',');
         $semicolon_position = strpos($base64_data, ';');
         $file_contents = base64_decode(substr($base64_data, $comma_position + 1));
         $mimetype = substr($base64_data, 5, $semicolon_position - 5);
         $extension = \Drupal::service('file.mime_type.guesser.extension')->convertMimeTypeToExtension($mimetype);
         $filename = trim($input['filefield_clipboard']['filename']);
         $filename = preg_replace('/\\.[a-z0-9]{3,4}$/', '', $filename);
         $filename = (empty($filename) ? 'paste_' . REQUEST_TIME : $filename) . '.' . $extension;
         $filepath = file_create_filename($filename, $temporary_directory);
         $copy_success = FALSE;
         if ($fp = @fopen($filepath, 'w')) {
             fwrite($fp, $file_contents);
             fclose($fp);
             $copy_success = TRUE;
         }
         if ($copy_success && ($file = filefield_sources_save_file($filepath, $element['#upload_validators'], $element['#upload_location']))) {
             if (!in_array($file->id(), $input['fids'])) {
                 $input['fids'][] = $file->id();
             }
         }
         // Remove the temporary file generated from paste.
         @unlink($filepath);
     }
 }
Example #7
0
 /**
  * Returns TRUE if the path is a directory or we can create one in that path.
  */
 public static function checkDirectory($dir_path)
 {
     if (!is_dir($dir_path)) {
         if (drupal_mkdir($dir_path, NULL, TRUE)) {
             return TRUE;
         } else {
             // If the directory does not exists and cannot be created.
             drupal_set_message(st('The directory %directory does not exist and could not be created.', array('%directory' => $dir_path)), 'error');
             watchdog('file system', 'The directory %directory does not exist and could not be created.', array('%directory' => $dir_path), WATCHDOG_ERROR);
             return FALSE;
         }
     } else {
         if (is_writable($dir_path) || drupal_chmod($dir_path)) {
             return TRUE;
         }
         watchdog('configuration', 'The current user does not have write permissions in the directory %dir.', array('%dir' => $dir_path), WATCHDOG_ERROR);
         drupal_set_message(t('The current user does not have write permissions in the directory %dir.', array('%dir' => $dir_path)), 'error', FALSE);
     }
     return FALSE;
 }
Example #8
0
 /**
  * {@inheritdoc}
  */
 public function write($name, array $data)
 {
     try {
         $data = $this->encode($data);
     } catch (InvalidDataTypeException $e) {
         throw new StorageException("Invalid data type in config {$name}: {$e->getMessage()}");
     }
     $target = $this->getFilePath($name);
     $status = @file_put_contents($target, $data);
     if ($status === FALSE) {
         // Try to make sure the directory exists and try writing again.
         $this->ensureStorage();
         $status = @file_put_contents($target, $data);
     }
     if ($status === FALSE) {
         throw new StorageException('Failed to write configuration file: ' . $this->getFilePath($name));
     } else {
         drupal_chmod($target);
     }
     return TRUE;
 }
  /**
   * An adaptation of file_save_upload() that includes more verbose errors.
   *
   * @param string $source
   *   A string specifying the filepath or URI of the uploaded file to save.
   *
   * @return stdClass
   *   The saved file object.
   *
   * @throws \RestfulBadRequestException
   * @throws \RestfulServiceUnavailable
   *
   * @see file_save_upload()
   */
  protected function fileSaveUpload($source) {
    static $upload_cache;

    $account = $this->getAccount();
    $options = $this->getPluginKey('options');

    $validators = $options['validators'];
    $destination = $options['scheme'] . "://";
    $replace = $options['replace'];

    // Return cached objects without processing since the file will have
    // already been processed and the paths in _FILES will be invalid.
    if (isset($upload_cache[$source])) {
      return $upload_cache[$source];
    }

    // Make sure there's an upload to process.
    if (empty($_FILES['files']['name'][$source])) {
      return NULL;
    }

    // Check for file upload errors and return FALSE if a lower level system
    // error occurred. For a complete list of errors:
    // See http://php.net/manual/features.file-upload.errors.php.
    switch ($_FILES['files']['error'][$source]) {
      case UPLOAD_ERR_INI_SIZE:
      case UPLOAD_ERR_FORM_SIZE:
        $message = format_string('The file %file could not be saved, because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $_FILES['files']['name'][$source], '%maxsize' => format_size(file_upload_max_size())));
        throw new \RestfulBadRequestException($message);

      case UPLOAD_ERR_PARTIAL:
      case UPLOAD_ERR_NO_FILE:
        $message = format_string('The file %file could not be saved, because the upload did not complete.', array('%file' => $_FILES['files']['name'][$source]));
        throw new \RestfulBadRequestException($message);

      case UPLOAD_ERR_OK:
        // Final check that this is a valid upload, if it isn't, use the
        // default error handler.
        if (is_uploaded_file($_FILES['files']['tmp_name'][$source])) {
          break;
        }

      // Unknown error
      default:
        $message = format_string('The file %file could not be saved. An unknown error has occurred.', array('%file' => $_FILES['files']['name'][$source]));
        throw new \RestfulServiceUnavailable($message);
    }

    // Begin building file object.
    $file = new stdClass();
    $file->uid      = $account->uid;
    $file->status   = 0;
    $file->filename = trim(drupal_basename($_FILES['files']['name'][$source]), '.');
    $file->uri      = $_FILES['files']['tmp_name'][$source];
    $file->filemime = file_get_mimetype($file->filename);
    $file->filesize = $_FILES['files']['size'][$source];

    $extensions = '';
    if (isset($validators['file_validate_extensions'])) {
      if (isset($validators['file_validate_extensions'][0])) {
        // Build the list of non-munged extensions if the caller provided them.
        $extensions = $validators['file_validate_extensions'][0];
      }
      else {
        // If 'file_validate_extensions' is set and the list is empty then the
        // caller wants to allow any extension. In this case we have to remove the
        // validator or else it will reject all extensions.
        unset($validators['file_validate_extensions']);
      }
    }
    else {
      // No validator was provided, so add one using the default list.
      // Build a default non-munged safe list for file_munge_filename().
      $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
      $validators['file_validate_extensions'] = array();
      $validators['file_validate_extensions'][0] = $extensions;
    }

    if (!empty($extensions)) {
      // Munge the filename to protect against possible malicious extension hiding
      // within an unknown file type (ie: filename.html.foo).
      $file->filename = file_munge_filename($file->filename, $extensions);
    }

    // Rename potentially executable files, to help prevent exploits (i.e. will
    // rename filename.php.foo and filename.php to filename.php.foo.txt and
    // filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
    // evaluates to TRUE.
    if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
      $file->filemime = 'text/plain';
      $file->uri .= '.txt';
      $file->filename .= '.txt';
      // The .txt extension may not be in the allowed list of extensions. We have
      // to add it here or else the file upload will fail.
      if (!empty($extensions)) {
        $validators['file_validate_extensions'][0] .= ' txt';

        // Unlike file_save_upload() we don't need to let the user know that
        // for security reasons, your upload has been renamed, since RESTful
        // will return the file name in the response.
      }
    }

    // If the destination is not provided, use the temporary directory.
    if (empty($destination)) {
      $destination = 'temporary://';
    }

    // Assert that the destination contains a valid stream.
    $destination_scheme = file_uri_scheme($destination);
    if (!$destination_scheme || !file_stream_wrapper_valid_scheme($destination_scheme)) {
      $message = format_string('The file could not be uploaded, because the destination %destination is invalid.', array('%destination' => $destination));
      throw new \RestfulServiceUnavailable($message);
    }

    $file->source = $source;
    // A URI may already have a trailing slash or look like "public://".
    if (substr($destination, -1) != '/') {
      $destination .= '/';
    }
    $file->destination = file_destination($destination . $file->filename, $replace);
    // If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
    // there's an existing file so we need to bail.
    if ($file->destination === FALSE) {
      $message = format_string('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination));
      throw new \RestfulServiceUnavailable($message);
    }

    // Add in our check of the the file name length.
    $validators['file_validate_name_length'] = array();

    // Call the validation functions specified by this function's caller.
    $errors = file_validate($file, $validators);

    // Check for errors.
    if (!empty($errors)) {
      $message = format_string('The specified file %name could not be uploaded.', array('%name' => $file->filename));
      if (count($errors) > 1) {
        $message .= theme('item_list', array('items' => $errors));
      }
      else {
        $message .= ' ' . array_pop($errors);
      }

      throw new \RestfulServiceUnavailable($message);
    }

    // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
    // directory. This overcomes open_basedir restrictions for future file
    // operations.
    $file->uri = $file->destination;
    if (!drupal_move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
      watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
      $message = 'File upload error. Could not move uploaded file.';
      throw new \RestfulServiceUnavailable($message);
    }

    // Set the permissions on the new file.
    drupal_chmod($file->uri);

    // If we are replacing an existing file re-use its database record.
    if ($replace == FILE_EXISTS_REPLACE) {
      $existing_files = file_load_multiple(array(), array('uri' => $file->uri));
      if (count($existing_files)) {
        $existing = reset($existing_files);
        $file->fid = $existing->fid;
      }
    }

    // If we made it this far it's safe to record this file in the database.
    if ($file = file_save($file)) {
      // Add file to the cache.
      $upload_cache[$source] = $file;
      return $file;
    }

    // Something went wrong, so throw a general exception.
    throw new \RestfulServiceUnavailable('Unknown error has occurred.');
  }
Example #10
0
 /**
  * Provides a wrapper for drupal_chmod() to allow unit testing.
  *
  * @param string $uri
  *   A string containing a URI file, or directory path.
  * @param int $mode
  *   Integer value for the permissions. Consult PHP chmod() documentation for
  *   more information.
  *
  * @see drupal_chmod()
  *
  * @todo Remove when https://www.drupal.org/node/2050759 is in.
  *
  * @return bool
  *   TRUE for success, FALSE in the event of an error.
  */
 protected function chmod($uri, $mode = NULL)
 {
     return drupal_chmod($uri, $mode);
 }
Example #11
0
 /**
  * {@inheritdoc}
  */
 public static function value(array &$element, &$input, FormStateInterface $form_state)
 {
     if (isset($input['filefield_remote']['url']) && strlen($input['filefield_remote']['url']) > 0 && UrlHelper::isValid($input['filefield_remote']['url']) && $input['filefield_remote']['url'] != FILEFIELD_SOURCE_REMOTE_HINT_TEXT) {
         $field = entity_load('field_config', $element['#entity_type'] . '.' . $element['#bundle'] . '.' . $element['#field_name']);
         $url = $input['filefield_remote']['url'];
         // Check that the destination is writable.
         $temporary_directory = 'temporary://';
         if (!file_prepare_directory($temporary_directory, FILE_MODIFY_PERMISSIONS)) {
             \Drupal::logger('filefield_sources')->log(E_NOTICE, 'The directory %directory is not writable, because it does not have the correct permissions set.', array('%directory' => drupal_realpath($temporary_directory)));
             drupal_set_message(t('The file could not be transferred because the temporary directory is not writable.'), 'error');
             return;
         }
         // Check that the destination is writable.
         $directory = $element['#upload_location'];
         $mode = Settings::get('file_chmod_directory', FILE_CHMOD_DIRECTORY);
         // This first chmod check is for other systems such as S3, which don't
         // work with file_prepare_directory().
         if (!drupal_chmod($directory, $mode) && !file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
             \Drupal::logger('filefield_sources')->log(E_NOTICE, 'File %file could not be copied, because the destination directory %destination is not configured correctly.', array('%file' => $url, '%destination' => drupal_realpath($directory)));
             drupal_set_message(t('The specified file %file could not be copied, because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', array('%file' => $url)), 'error');
             return;
         }
         // Check the headers to make sure it exists and is within the allowed
         // size.
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_URL, $url);
         curl_setopt($ch, CURLOPT_HEADER, TRUE);
         curl_setopt($ch, CURLOPT_NOBODY, TRUE);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
         curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(get_called_class(), 'parseHeader'));
         // Causes a warning if PHP safe mode is on.
         @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
         curl_exec($ch);
         $info = curl_getinfo($ch);
         if ($info['http_code'] != 200) {
             curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
             $file_contents = curl_exec($ch);
             $info = curl_getinfo($ch);
         }
         curl_close($ch);
         if ($info['http_code'] != 200) {
             switch ($info['http_code']) {
                 case 403:
                     $form_state->setError($element, t('The remote file could not be transferred because access to the file was denied.'));
                     break;
                 case 404:
                     $form_state->setError($element, t('The remote file could not be transferred because it was not found.'));
                     break;
                 default:
                     $form_state->setError($element, t('The remote file could not be transferred due to an HTTP error (@code).', array('@code' => $info['http_code'])));
             }
             return;
         }
         // Update the $url variable to reflect any redirects.
         $url = $info['url'];
         $url_info = parse_url($url);
         // Determine the proper filename by reading the filename given in the
         // Content-Disposition header. If the server fails to send this header,
         // fall back on the basename of the URL.
         //
         // We prefer to use the Content-Disposition header, because we can then
         // use URLs like http://example.com/get_file/23 which would otherwise be
         // rejected because the URL basename lacks an extension.
         $filename = static::filename();
         if (empty($filename)) {
             $filename = rawurldecode(basename($url_info['path']));
         }
         $pathinfo = pathinfo($filename);
         // Create the file extension from the MIME header if all else has failed.
         if (empty($pathinfo['extension']) && ($extension = static::mimeExtension())) {
             $filename = $filename . '.' . $extension;
             $pathinfo = pathinfo($filename);
         }
         $filename = filefield_sources_clean_filename($filename, $field->getSetting('file_extensions'));
         $filepath = file_create_filename($filename, $temporary_directory);
         if (empty($pathinfo['extension'])) {
             $form_state->setError($element, t('The remote URL must be a file and have an extension.'));
             return;
         }
         // Perform basic extension check on the file before trying to transfer.
         $extensions = $field->getSetting('file_extensions');
         $regex = '/\\.(' . preg_replace('/[ +]/', '|', preg_quote($extensions)) . ')$/i';
         if (!empty($extensions) && !preg_match($regex, $filename)) {
             $form_state->setError($element, t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $extensions)));
             return;
         }
         // Check file size based off of header information.
         if (!empty($element['#upload_validators']['file_validate_size'][0])) {
             $max_size = $element['#upload_validators']['file_validate_size'][0];
             $file_size = $info['download_content_length'];
             if ($file_size > $max_size) {
                 $form_state->setError($element, t('The remote file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size($file_size), '%maxsize' => format_size($max_size))));
                 return;
             }
         }
         // Set progress bar information.
         $options = array('key' => $element['#entity_type'] . '_' . $element['#bundle'] . '_' . $element['#field_name'] . '_' . $element['#delta'], 'filepath' => $filepath);
         static::setTransferOptions($options);
         $transfer_success = FALSE;
         // If we've already downloaded the entire file because the
         // header-retrieval failed, just ave the contents we have.
         if (isset($file_contents)) {
             if ($fp = @fopen($filepath, 'w')) {
                 fwrite($fp, $file_contents);
                 fclose($fp);
                 $transfer_success = TRUE;
             }
         } else {
             $ch = curl_init();
             curl_setopt($ch, CURLOPT_URL, $url);
             curl_setopt($ch, CURLOPT_HEADER, FALSE);
             curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(get_called_class(), 'curlWrite'));
             // Causes a warning if PHP safe mode is on.
             @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
             $transfer_success = curl_exec($ch);
             curl_close($ch);
         }
         if ($transfer_success && ($file = filefield_sources_save_file($filepath, $element['#upload_validators'], $element['#upload_location']))) {
             if (!in_array($file->id(), $input['fids'])) {
                 $input['fids'][] = $file->id();
             }
         }
         // Delete the temporary file.
         @unlink($filepath);
     }
 }
 /**
  * Returns the git clone file system directory path.
  *
  * @param bool $create
  *   Toggle determining whether or not to create the directory if it does not
  *   exist.
  * @param bool $absolute
  *   Toggle determining whether or not to return the entire system path. If
  *   FALSE, it will be prefixed with the gitclone:// stream wrapper.
  *
  * @return string|FALSE
  *   The git clone path or FALSE on error.
  */
 public function getPath($create = TRUE, $absolute = TRUE)
 {
     if (empty($this->refType) || empty($this->ref) || empty($this->name)) {
         return FALSE;
     }
     $path = "gitclone://{$this->refType}/{$this->name}";
     if ($create) {
         if (!is_dir($path) && !drupal_mkdir($path, NULL, TRUE)) {
             drupal_set_message(t('The directory %directory does not exist and could not be created.', array('%directory' => $path)), 'error');
             return FALSE;
         }
         if (is_dir($path) && !is_writable($path) && !drupal_chmod($path)) {
             drupal_set_message(t('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $path)), 'error');
             return FALSE;
         }
     } else {
         if (!is_dir($path)) {
             return FALSE;
         }
         if (!drupal_is_cli() && is_dir($path) && !is_writable($path) && !drupal_chmod($path)) {
             drupal_set_message(t('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $path)), 'error');
         }
     }
     if ($absolute) {
         return drupal_realpath($path);
     }
     return $path;
 }
 /**
  * Create temporary file.
  *
  * @return object
  *   Permanent file object.
  */
 public function createTemporaryFile($path = '')
 {
     $filename = $this->randomMachineName() . '.txt';
     if (empty($path)) {
         $path = file_default_scheme() . '://';
     }
     $uri = $path . '/' . $filename;
     $contents = $this->randomString();
     // Change mode so that we can create files.
     file_prepare_directory($path, FILE_CREATE_DIRECTORY);
     drupal_chmod($path, FILE_CHMOD_DIRECTORY);
     file_put_contents($uri, $contents);
     $this->assertTrue(is_file($uri), 'The temporary file has been created.');
     // Change mode so that we can delete created file.
     drupal_chmod($uri, FILE_CHMOD_FILE);
     // Return object similar to file_scan_directory().
     $file = new \stdClass();
     $file->uri = $uri;
     $file->filename = $filename;
     $file->name = pathinfo($filename, PATHINFO_FILENAME);
     return $file;
 }
Example #14
0
 /**
  * Uploads the file to EMDB.
  *
  * @param string $form_field_name
  *   A string that is the associative array key of the upload form element in
  *   the form array.
  * @param string $catalog_id
  *   The catalog id for the catalog we are uploading to.
  * @param array $metadata
  *   Additional properties that can be passed into EMDB and stored as metadata
  *   on the file. These values are not stored locally in Drupal.
  * @param array $validators
  *   An optional, associative array of callback functions used to validate the
  *   file.
  * @param string|bool $destination_dir
  *   A string containing the URI that the file should be copied to. This must
  *   be a stream wrapper URI. If this value is omitted, Drupal's temporary
  *   files scheme will be used ("temporary://").
  * @param int $delta
  *   Delta of the file to save or NULL to save all files. Defaults to NULL.
  * @param int $replace
  *   Replace behavior when the destination file already exists:
  *   - FILE_EXISTS_REPLACE: Replace the existing file.
  *   - FILE_EXISTS_RENAME: Append _{incrementing number} until the filename is
  *     unique.
  *   - FILE_EXISTS_ERROR: Do nothing and return FALSE.
  *
  * @return \Drupal\embridge\EmbridgeAssetEntityInterface[]
  *   Function returns array of files or a single file object if $delta
  *   != NULL. Each file object contains the file information if the
  *   upload succeeded or FALSE in the event of an error. Function
  *   returns NULL if no file was uploaded.
  *
  *   The docs for the "File interface" group, which you can find under
  *   Related topics, or the header at the top of this file, documents the
  *   components of a file entity. In addition to the standard components,
  *   this function adds:
  *   - source: Path to the file before it is moved.
  *   - destination: Path to the file after it is moved (same as 'uri').
  */
 public static function saveUpload($form_field_name, $catalog_id, $metadata = array(), $validators = array(), $destination_dir = FALSE, $delta = NULL, $replace = FILE_EXISTS_RENAME)
 {
     $user = \Drupal::currentUser();
     static $upload_cache;
     $file_upload = \Drupal::request()->files->get("files[{$form_field_name}]", NULL, TRUE);
     // Make sure there's an upload to process.
     if (empty($file_upload)) {
         return NULL;
     }
     // Return cached objects without processing since the file will have
     // already been processed and the paths in $_FILES will be invalid.
     if (isset($upload_cache[$form_field_name])) {
         if (isset($delta)) {
             return $upload_cache[$form_field_name][$delta];
         }
         return $upload_cache[$form_field_name];
     }
     // Prepare uploaded files info. Representation is slightly different
     // for multiple uploads and we fix that here.
     /** @var \Symfony\Component\HttpFoundation\File\UploadedFile[] $uploaded_files */
     $uploaded_files = $file_upload;
     if (!is_array($file_upload)) {
         $uploaded_files = array($file_upload);
     }
     $assets = array();
     foreach ($uploaded_files as $i => $file_info) {
         // Check for file upload errors and return FALSE for this file if a lower
         // level system error occurred. For a complete list of errors:
         // See http://php.net/manual/features.file-upload.errors.php.
         switch ($file_info->getError()) {
             case UPLOAD_ERR_INI_SIZE:
             case UPLOAD_ERR_FORM_SIZE:
                 drupal_set_message(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $file_info->getFilename(), '%maxsize' => format_size(file_upload_max_size()))), 'error');
                 $assets[$i] = FALSE;
                 continue;
             case UPLOAD_ERR_PARTIAL:
             case UPLOAD_ERR_NO_FILE:
                 drupal_set_message(t('The file %file could not be saved because the upload did not complete.', array('%file' => $file_info->getFilename())), 'error');
                 $assets[$i] = FALSE;
                 continue;
             case UPLOAD_ERR_OK:
                 // Final check that this is a valid upload, if it isn't, use the
                 // default error handler.
                 if (is_uploaded_file($file_info->getRealPath())) {
                     break;
                 }
             default:
                 // Unknown error.
                 drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $file_info->getFilename())), 'error');
                 $assets[$i] = FALSE;
                 continue;
         }
         // Begin building file entity.
         $values = array('uid' => $user->id(), 'filename' => $file_info->getClientOriginalName(), 'filesize' => $file_info->getSize(), 'catalog_id' => $catalog_id);
         $values['filemime'] = \Drupal::service('file.mime_type.guesser')->guess($values['filename']);
         // Create our Embridge Entity.
         /** @var \Drupal\embridge\EmbridgeAssetEntityInterface $asset */
         $asset = EmbridgeAssetEntity::create($values);
         $extensions = '';
         if (isset($validators['embridge_asset_validate_file_extensions'])) {
             if (isset($validators['embridge_asset_validate_file_extensions'][0])) {
                 // Build the list of non-munged exts if the caller provided them.
                 $extensions = $validators['embridge_asset_validate_file_extensions'][0];
             } else {
                 // If 'file_validate_extensions' is set and the list is empty then the
                 // caller wants to allow any extension. In this case we have to remove
                 // the validator or else it will reject all extensions.
                 unset($validators['embridge_asset_validate_file_extensions']);
             }
         } else {
             // No validator was provided, so add one using the default list.
             // Build a default non-munged safe list for file_munge_filename().
             $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';
             $validators['embridge_asset_validate_file_extensions'] = array();
             $validators['embridge_asset_validate_file_extensions'][0] = $extensions;
         }
         if (!empty($extensions)) {
             // Munge the filename to protect against possible malicious extension
             // hiding within an unknown file type (ie: filename.html.foo).
             $asset->setFilename(file_munge_filename($asset->getFilename(), $extensions));
         }
         // Rename potentially executable files, to help prevent exploits.
         if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match('/\\.(php|pl|py|cgi|asp|js)(\\.|$)/i', $asset->getFilename()) && substr($asset->getFilename(), -4) != '.txt') {
             $asset->setMimeType('text/plain');
             // The destination filename will also later be used to create the URI.
             $asset->setFilename($asset->getFilename() . '.txt');
             // The .txt extension may not be in the allowed list of extensions.
             // We have to add it here or else the file upload will fail.
             if (!empty($extensions)) {
                 $validators['embridge_asset_validate_file_extensions'][0] .= ' txt';
                 drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $asset->getFilename())));
             }
         }
         // If the destination is not provided, use the temporary directory.
         if (empty($destination_dir)) {
             $destination_dir = 'temporary://';
         }
         // Assert that the destination contains a valid stream.
         $destination_scheme = file_uri_scheme($destination_dir);
         if (!file_stream_wrapper_valid_scheme($destination_scheme)) {
             drupal_set_message(t('The file could not be uploaded because the destination %destination is invalid.', array('%destination' => $destination_dir)), 'error');
             $assets[$i] = FALSE;
             continue;
         }
         // A file URI may already have a trailing slash or look like "public://".
         if (substr($destination_dir, -1) != '/') {
             $destination_dir .= '/';
         }
         $asset_destination = file_destination($destination_dir . $asset->getFilename(), $replace);
         // If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR
         // and there's an existing file so we need to bail.
         if ($asset_destination === FALSE) {
             drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $form_field_name, '%directory' => $destination_dir)), 'error');
             $assets[$i] = FALSE;
             continue;
         }
         // Add in our check of the file name length.
         // TODO: Do we need this?
         // $validators['file_validate_name_length'] = array();
         // Call the validation functions specified by this function's caller.
         $errors = embridge_asset_validate($asset, $validators);
         // Check for errors.
         if (!empty($errors)) {
             $message = array('error' => array('#markup' => t('The specified file %name could not be uploaded.', array('%name' => $asset->getFilename()))), 'item_list' => array('#theme' => 'item_list', '#items' => $errors));
             // @todo Add support for render arrays in drupal_set_message()? See
             // https://www.drupal.org/node/2505497.
             drupal_set_message(\Drupal::service('renderer')->renderPlain($message), 'error');
             $assets[$i] = FALSE;
             continue;
         }
         // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
         // directory. This overcomes open_basedir restrictions for future file
         // operations.
         $asset->setSourcePath($asset_destination);
         if (!drupal_move_uploaded_file($file_info->getRealPath(), $asset->getSourcePath())) {
             drupal_set_message(t('File upload error. Could not move uploaded file.'), 'error');
             \Drupal::logger('file')->notice('Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $asset->getFilename(), '%destination' => $asset->getSourcePath()));
             $assets[$i] = FALSE;
             continue;
         }
         // Set the permissions on the new file.
         drupal_chmod($asset->getSourcePath());
         // If we are replacing an existing file re-use its database record.
         // @todo Do not create a new entity in order to update it. See
         // https://www.drupal.org/node/2241865.
         if ($replace == FILE_EXISTS_REPLACE) {
             $existing_files = entity_load_multiple_by_properties('embridge_asset_entity', array('uri' => $asset->getSourcePath()));
             if (count($existing_files)) {
                 $existing = reset($existing_files);
                 $asset->setOriginalId($existing->id());
             }
         }
         /** @var \Drupal\embridge\EnterMediaDbClientInterface $embridge_client */
         $embridge_client = \Drupal::getContainer()->get('embridge.client');
         try {
             $embridge_client->upload($asset, $metadata);
         } catch (\Exception $e) {
             $message = $e->getMessage();
             drupal_set_message(t('Uploading the file "%file" to EnterMedia failed with the message "%message".', array('%file' => $asset->getFilename(), '%message' => $message)), 'error');
             $assets[$i] = FALSE;
             continue;
         }
         // If we made it this far it's safe to record this file in the database.
         $asset->save();
         $assets[$i] = $asset;
     }
     // Add files to the cache.
     $upload_cache[$form_field_name] = $assets;
     return isset($delta) ? $assets[$delta] : $assets;
 }