Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to mimic or pass a file url to $_Files?

Tags:

I need to modify an application that was custom built for us by someone else. The application accepts a file (of type .ydk) from a form and then uploads that to WordPress (while also reading it's contents). I want to modify this so that it can also read a .ydk file from the server.

I've narrowed it down to the following:

if($_FILES['deckFile']){
    $attachment_ydk_id = upload_ydk_file($_FILES['deckFile']);
}

And the function it's then using:

//Upload ydk file
function upload_ydk_file( $file = array() ) {
    require_once( ABSPATH . 'wp-admin/includes/admin.php' );
      $file_return = wp_handle_upload( $file, array('test_form' => false ) );
      if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) {
          return false;
      } else {
          $filename = $file_return['file'];
          $attachment = array(
              'post_mime_type' => $file_return['type'],
              'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
              'post_content' => '',
              'post_status' => 'inherit',
              'guid' => $file_return['url']
          );
          $attachment_id = wp_insert_attachment( $attachment, $file_return['url'] );
          require_once(ABSPATH . 'wp-admin/includes/image.php');
          $attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
          wp_update_attachment_metadata( $attachment_id, $attachment_data );
          if( 0 < intval( $attachment_id ) ) {
            return $attachment_id;
          }
      }
      return false;
}

So the way I look at it. $_Files is needed since it's using wp_handle_upload which I believe requires $_Files array.

I tried fopen and file() as such but no luck:

    $attachment_ydk_id = upload_ydk_file(fopen("location_of_file.ydk", "r"));

EDIT: 1st Attempt

I've now tried the following (in an attempt to re-create $_Files):

$urls = 'YGOPRO_Decks/user_decks/58535.ydk';

$size = filesize($urls);
$info = pathinfo($urls);
$info_basename = $info['basename'];
$info_mime = 'application/octet-stream';

$UrlArray = array(
    'name' => $info_basename,
    'type' => $info_mime,
    'tmp_name' => 'YGOPRO_Decks/user_decks/58535.ydk',
    'error' => 0,
    'size' => $size
);  


if($_FILES['deckFile']){
    $attachment_ydk_id = upload_ydk_file($UrlArray);
}

The file exists in the location give. A print_r on the array gives:

 Array
(
    [name] => 58535.ydk
    [type] => application/octet-stream
    [tmp_name] => YGOPRO_Decks/user_decks/58535.ydk
    [error] => 0
    [size] => 576
)

Still no luck unfortunately. This seemed like a really good method and I thought I was on to something but it continues to fail.

like image 901
GenesisBits Avatar asked Sep 25 '19 09:09

GenesisBits


1 Answers

According to the documentation for wp_insert_attachement, the file must be located in the uploads directory. Assuming you have access to the full WordPress library (since you are already calling into it), you can get the path using wp_upload_dir.

$tmp_file = wp_upload_dir() . '/' . basename($urls);
if (!copy($url, $tmp_file)) 
    exit();

Note: If you don't have WordPress loaded (e.g. if you are trying to run this as a script from the command line) then the upload_ydk_file isn't going to work as it relies on several WordPress functions.

You also aren't actually ever calling upload_ydk_file because you are still checking if the deckFile node of the $_FILES array is set before calling it.

if($_FILES['deckFile']){
    $attachment_ydk_id = upload_ydk_file($UrlArray);
}

If you remove that and always call upload_ydk_file since you know that $UrlArray will always be set then you should be good to go.

$urls = 'YGOPRO_Decks/user_decks/58535.ydk';
$tmp_file = wp_upload_dir() . '/' . basename($urls);
if (!copy($url, $tmp_file)) 
    exit();

$size = filesize($tmp_file);
$info = pathinfo($tmp_file);
$info_basename = $info['basename'];
$info_mime = 'application/octet-stream';

$UrlArray = array(
    'name' => $info_basename,
    'type' => $info_mime,
    'tmp_name' => $tmp_file,
    'error' => 0,
    'size' => $size
);  

$attachment_ydk_id = upload_ydk_file($UrlArray);

EDIT: Using wp_handle_sideload is a safer way to do move the file into the uploads directory. However, it is going to move the file, not copy the file so if you want to use that instead you should still copy the original file before passing that to wp_handle_sideload.

like image 89
cjc Avatar answered Oct 13 '22 00:10

cjc