Skip to content

Instantly share code, notes, and snippets.

@ngangchill
Forked from skunkbad/MY_Upload.php
Last active August 29, 2015 14:22
Show Gist options
  • Select an option

  • Save ngangchill/0cf06ce3bfe94d7c3cfd to your computer and use it in GitHub Desktop.

Select an option

Save ngangchill/0cf06ce3bfe94d7c3cfd to your computer and use it in GitHub Desktop.

Revisions

  1. @skunkbad skunkbad created this gist Sep 15, 2011.
    290 changes: 290 additions & 0 deletions MY_Upload.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,290 @@
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    class MY_Upload extends CI_Upload {

    public $destination_not_file_system = FALSE;

    public function __construct($props = array())
    {
    parent::__construct();

    if (count($props) > 0)
    {
    $this->initialize($props);
    }

    log_message('debug', "Upload Class Initialized");
    }

    public function initialize($config = array())
    {
    $defaults = array(
    'max_size' => 0,
    'max_width' => 0,
    'max_height' => 0,
    'max_filename' => 0,
    'allowed_types' => "",
    'file_temp' => "",
    'file_name' => "",
    'orig_name' => "",
    'file_type' => "",
    'file_size' => "",
    'file_ext' => "",
    'upload_path' => "",
    'overwrite' => FALSE,
    'encrypt_name' => FALSE,
    'is_image' => FALSE,
    'image_width' => '',
    'image_height' => '',
    'image_type' => '',
    'image_size_str' => '',
    'error_msg' => array(),
    'mimes' => array(),
    'remove_spaces' => TRUE,
    'xss_clean' => FALSE,
    'temp_prefix' => "temp_file_",
    'client_name' => '',
    // new destination_not_file_system key
    'destination_not_file_system' => FALSE
    );


    foreach ($defaults as $key => $val)
    {
    if (isset($config[$key]))
    {
    $method = 'set_'.$key;
    if (method_exists($this, $method))
    {
    $this->$method($config[$key]);
    }
    else
    {
    $this->$key = $config[$key];
    }
    }
    else
    {
    $this->$key = $val;
    }
    }

    // if a file_name was provided in the config, use it instead of the user input
    // supplied file name for all uploads until initialized again
    $this->_file_name_override = $this->file_name;
    }

    public function do_upload($field = 'userfile')
    {

    // Is $_FILES[$field] set? If not, no reason to continue.
    if ( ! isset($_FILES[$field]))
    {
    $this->set_error('upload_no_file_selected');
    return FALSE;
    }

    // Is the upload path valid? (only applies if file system is final destination
    if( $this->destination_not_file_system === FALSE )
    {
    if ( ! $this->validate_upload_path())
    {
    // errors will already be set by validate_upload_path() so just return FALSE
    return FALSE;
    }
    }

    // Was the file able to be uploaded? If not, determine the reason why.
    if ( ! is_uploaded_file($_FILES[$field]['tmp_name']))
    {
    $error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];

    switch($error)
    {
    case 1: // UPLOAD_ERR_INI_SIZE
    $this->set_error('upload_file_exceeds_limit');
    break;
    case 2: // UPLOAD_ERR_FORM_SIZE
    $this->set_error('upload_file_exceeds_form_limit');
    break;
    case 3: // UPLOAD_ERR_PARTIAL
    $this->set_error('upload_file_partial');
    break;
    case 4: // UPLOAD_ERR_NO_FILE
    $this->set_error('upload_no_file_selected');
    break;
    case 6: // UPLOAD_ERR_NO_TMP_DIR
    $this->set_error('upload_no_temp_directory');
    break;
    case 7: // UPLOAD_ERR_CANT_WRITE
    $this->set_error('upload_unable_to_write_file');
    break;
    case 8: // UPLOAD_ERR_EXTENSION
    $this->set_error('upload_stopped_by_extension');
    break;
    default : $this->set_error('upload_no_file_selected');
    break;
    }

    return FALSE;
    }


    // Set the uploaded data as class variables
    $this->file_temp = $_FILES[$field]['tmp_name'];
    $this->file_size = $_FILES[$field]['size'];
    $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type']);
    $this->file_type = strtolower(trim(stripslashes($this->file_type), '"'));
    $this->file_name = $this->_prep_filename($_FILES[$field]['name']);
    $this->file_ext = $this->get_extension($this->file_name);
    $this->client_name = $this->file_name;

    // Is the file type allowed to be uploaded?
    if ( ! $this->is_allowed_filetype())
    {
    $this->set_error('upload_invalid_filetype');
    return FALSE;
    }

    // if we're overriding, let's now make sure the new name and type is allowed
    if ($this->_file_name_override != '')
    {
    $this->file_name = $this->_prep_filename($this->_file_name_override);

    // If no extension was provided in the file_name config item, use the uploaded one
    if (strpos($this->_file_name_override, '.') === FALSE)
    {
    $this->file_name .= $this->file_ext;
    }

    // An extension was provided, lets have it!
    else
    {
    $this->file_ext = $this->get_extension($this->_file_name_override);
    }

    if ( ! $this->is_allowed_filetype(TRUE))
    {
    $this->set_error('upload_invalid_filetype');
    return FALSE;
    }
    }

    // Convert the file size to kilobytes
    if ($this->file_size > 0)
    {
    $this->file_size = round($this->file_size/1024, 2);
    }

    // Is the file size within the allowed maximum?
    if ( ! $this->is_allowed_filesize())
    {
    $this->set_error('upload_invalid_filesize');
    return FALSE;
    }

    // Are the image dimensions within the allowed size?
    // Note: This can fail if the server has an open_basdir restriction.
    if ( ! $this->is_allowed_dimensions())
    {
    $this->set_error('upload_invalid_dimensions');
    return FALSE;
    }

    // Sanitize the file name for security
    $this->file_name = $this->clean_file_name($this->file_name);

    // Truncate the file name if it's too long
    if ($this->max_filename > 0)
    {
    $this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);
    }

    // Remove white spaces in the name
    if ($this->remove_spaces == TRUE)
    {
    $this->file_name = preg_replace("/\s+/", "_", $this->file_name);
    }

    /*
    * Validate the file name
    * This function appends an number onto the end of
    * the file if one with the same name already exists.
    * If it returns false there was a problem.
    */
    $this->orig_name = $this->file_name;

    if ($this->overwrite == FALSE)
    {
    $this->file_name = $this->set_filename($this->upload_path, $this->file_name);

    if ($this->file_name === FALSE)
    {
    return FALSE;
    }
    }

    /*
    * Run the file through the XSS hacking filter
    * This helps prevent malicious code from being
    * embedded within a file. Scripts can easily
    * be disguised as images or other file types.
    */
    if ($this->xss_clean)
    {
    if ($this->do_xss_clean() === FALSE)
    {
    $this->set_error('upload_unable_to_write_file');
    return FALSE;
    }
    }

    if( $this->destination_not_file_system === FALSE )
    {
    /*
    * Move the file to the final destination
    * To deal with different server configurations
    * we'll attempt to use copy() first. If that fails
    * we'll use move_uploaded_file(). One of the two should
    * reliably work in most environments
    */
    if ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))
    {
    if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))
    {
    $this->set_error('upload_destination_error');
    return FALSE;
    }
    }

    /*
    * Set the finalized image dimensions for
    * files saved to the file system.
    * This sets the image width/height (assuming the
    * file was an image). We use this information
    * in the "data" function.
    */
    $this->set_image_properties($this->upload_path.$this->file_name);

    return TRUE;
    }
    else
    {
    /*
    * Set the finalized image dimensions for
    * files that were not saved to the file system.
    * This sets the image width/height (assuming the
    * file was an image). We use this information
    * in the "data" function.
    */

    $this->set_image_properties( $this->file_temp );

    return TRUE;
    }
    }

    }

    /* End of file MY_Upload.php */
    /* Location: ./application/libraries/MY_Upload.php */
    249 changes: 249 additions & 0 deletions uploads_manager.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,249 @@
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    class Uploads_manager extends MY_Controller {

    public $upload_details = array();
    private $upload_dir;
    private $primary_dir = FALSE;
    private $secondary_dir = FALSE;
    private $tertiary_dir = FALSE;
    private $quaternary_dir = FALSE;
    private $success_callback;

    public function __construct()
    {
    parent::__construct();

    $this->config->load('uploads_manager_config');
    $this->load->model('uploads_manager_model');
    }

    /*
    * BRIDGE DATABASE method does most of the work behind
    * uploading a file whos destination is the database.
    *
    * Argument 1 - $type - used as a suffix to the upload config set.
    * Argument 2 = $return - set to TRUE to return array instead of json.
    *
    * A mandatory callback function name must be supplied by post
    * element "success_callback"
    *
    */
    public function bridge_database( $type, $return = FALSE )
    {
    if($this->require_role('Sudo,Admin,VPM,RM,PM'))
    {
    // Use CSRF protection
    $this->load->library('csrf');

    // Check if a valid form submission has been made
    if( $this->csrf->token_match )
    {
    // Get special upload config for database storage
    $init_config = config_item( 'db_storage_configuration_' . $type );

    // Load and initialize file upload class
    $this->load->library('upload', $init_config);

    // Use upload library for file validation
    if ( $this->upload->do_upload() )
    {
    $handle = fopen( $this->upload->file_temp, "r" );
    $file_string = base64_encode( fread( $handle, filesize( $this->upload->file_temp ) ) );
    fclose($handle);

    // Need to have callback to handle the specific upload details
    if( empty( $this->success_callback ) )
    {
    $this->success_callback = $this->input->post('success_callback');
    }

    // Need to have callback handle the insertion to DB
    if( ! empty( $this->success_callback ) )
    {
    if( method_exists($this, $this->success_callback) )
    {
    $callback = $this->success_callback;

    // Pass the file string to the callback
    if( $callback_response = $this->$callback( $file_string ) )
    {
    // Send Success Response
    $response['status'] = 'success';
    $response['callback_response'] = $callback_response;
    }
    else
    {
    // Error: Callback Failed
    $response['status'] = 'error';
    $response['issue'] = 'Callback failed.';
    }
    }
    else
    {
    // Error: Callback Doesn't Exist
    $response['status'] = 'error';
    $response['issue'] = 'Callback does not exist.';
    }
    }
    else
    {
    // Error: No Callback Specified
    $response['status'] = 'error';
    $response['issue'] = 'No callback specified.';
    }
    }
    else
    {
    // Error: Upload Failed
    $response['status'] = 'error';
    $response['issue'] = 'Upload failed. Please try again later, or contact your supervisor.';
    }
    }
    else
    {
    // Error: No Token Match
    $response['status'] = 'error';
    $response['issue'] = 'No Token Match. Please reload the page.';
    }

    $response['token'] = $this->csrf->token;

    if( $return )
    {
    return $response;
    }
    else
    {
    echo json_encode( $response );
    }

    }
    }

    /*
    * BRIDGE FTP method does most of the work behind
    * uploading a file whos destination is another server.
    *
    * Argument 1 - $type - used as a suffix to the upload config set.
    * Is is also the prefix of the FTP config set.
    * Argument 2 = $return - set to TRUE to return array instead of json.
    *
    * A mandatory callback function name must be supplied by post
    * element "success_callback"
    *
    */
    public function bridge_ftp( $type, $return = FALSE )
    {
    if($this->require_role('Sudo,Admin,VPM,RM,PM'))
    {
    // Use CSRF protection
    $this->load->library('csrf');

    // Check if a valid form submission has been made
    if( $this->csrf->token_match )
    {
    // Get special upload config for FTP transfer
    $init_config = config_item( 'ftp_configuration_' . $type );

    // Load and initialize file upload class
    $this->load->library('upload', $init_config);

    // Use upload library for file validation
    if ( $this->upload->do_upload() )
    {
    // FTP the file to the backoffice
    $this->load->library('ftp');
    $this->config->load('ftp');
    $ftp_config = config_item( $type . '_ftp_settings' );

    $this->ftp->connect( $ftp_config );

    if( $this->ftp->upload( $this->upload->file_temp, $ftp_config['remote_directory'] . $this->upload->file_name ) )
    {
    // Need to have callback to handle the specific upload details
    if( empty( $this->success_callback ) )
    {
    $this->success_callback = $this->input->post('success_callback');
    }

    // If success callback supplied, run it
    if( ! empty( $this->success_callback ) )
    {
    if( method_exists($this, $this->success_callback) )
    {
    $callback = $this->success_callback;

    if( $callback_response = $this->$callback() )
    {
    // Send Success Response ( Callback Used )
    $response['status'] = 'success';
    $response['callback_response'] = $callback_response;
    }
    else
    {
    // Error: Callback Failed
    $response['status'] = 'error';
    $response['issue'] = 'Callback failed.';
    }
    }
    else
    {
    // Error: Callback Doesn't Exist
    $response['status'] = 'error';
    $response['issue'] = 'Callback does not exist.';
    }
    }
    else
    {
    // Send Success Response ( No Callback Used )
    $response['status'] = 'success';
    }
    }
    else
    {
    // Get FTP Errors
    $errors = $this->ftp->error_stack;

    $formatted_errors = '';
    foreach( $errors as $error )
    {
    $formatted_errors .= $error . "\n";
    }

    // Send FTP Errors as Response
    $response['status'] = 'error';
    $response['issue'] = $formatted_errors;
    }

    $this->ftp->close();
    }
    else
    {
    // Error: Upload Failed
    $response['status'] = 'error';
    $response['issue'] = 'Upload failed. Please try again later, or contact your supervisor.';
    }
    }
    else
    {
    // Error: No Token Match
    $response['status'] = 'error';
    $response['issue'] = 'No Token Match. Please reload the page.';
    }

    $response['token'] = $this->csrf->token;

    if( $return )
    {
    return $response;
    }
    else
    {
    echo json_encode( $response );
    }

    }
    }

    }
    43 changes: 43 additions & 0 deletions uploads_manager_config.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    // upload_dir must be a single public root level directory

    $config['upload_dir'] = 'site_uploads';

    // FILE SYSTEM ---------------------------------------------
    $config['filesystem_configuration_documents'] = array(
    'allowed_types' => 'doc|docx|pdf|txt|xls',
    'max_size' => '100',
    );

    $config['filesystem_configuration_listing_image'] = array(
    'allowed_types' => 'gif|jpg|jpeg|png',
    'max_size' => '250',
    'max_width' => '480',
    'max_height' => '360',
    'primary_dir' => 'region_directory', // <- post key of primary directory
    'secondary_dir' => 'unit_id' // <- post key of secondary directory
    );
    // ----------------------------------------------------------


    // FTP ------------------------------------------------------
    $config['ftp_configuration_report'] = array(
    'allowed_types' => 'pdf',
    'max_size' => '2000',
    'destination_not_file_system' => TRUE
    );
    // ----------------------------------------------------------


    // DATABASE -------------------------------------------------
    $config['db_storage_configuration_photo'] = array(
    'allowed_types' => 'gif|jpg|jpeg|png',
    'max_size' => '256',
    'destination_not_file_system' => TRUE
    );
    // ----------------------------------------------------------


    /* End of file uploads_manager_config.php */
    /* Location: /application/config/uploads_manager_config.php */