* @contributor Vernon Mauery * porting to Drupal 6 * @author Heshan Wanigasooriya * @todo */ /** * Implementation of hook_menu */ function video_upload_menu() { $items = array(); $maycache = true; if($maycache) { $items['node/add/video/upload'] = array( 'title' => 'Upload', 'access arguments' => array('create video') ); $items['admin/settings/video/upload'] = array( 'title' => 'Upload', 'description' => 'Configure various settings of the video upload plugin.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('video_upload_admin_settings'), 'type' => MENU_NORMAL_ITEM, ); } return $items; } /** * Setting form for video_upload */ function video_upload_admin_settings() { $form = array(); $form['video_upload_allowed_extensions'] = array( '#type' => 'textfield', '#title' => t('Allowed extensions'), '#description' => t('A comma separated list of video extesions uploadable with the video upload feature. Do not insert any space.'), '#default_value' => variable_get('video_upload_allowed_extensions', 'mov,flv,wmv'), ); $form['video_upload_path_prefix'] = array( '#type' => 'textfield', '#title' => t('Pattern for the file prefix'), '#description' => t('Specify the pattern to prefix to file names uploaded with the video_upload module. It will be appended after the site files directory (e.g., files) but before the file name itself. Do not include a leading or trailing slash. Spaces will be converted to underscores to avoid file system issues.'), '#default_value' => variable_get('video_upload_path_prefix', 'videos'), ); $form['token_help'] = array( '#title' => t('Replacement patterns'), '#type' => 'fieldset', '#collapsible' => TRUE, '#collapsed' => TRUE, '#description' => t('Prefer raw-text replacements for text to avoid problems with HTML entities!'), ); $form['token_help']['help'] = array( '#value' => theme('token_help', 'node'), ); return system_settings_form($form); } /** * Implementation of hook_cron(). * Look for uploaded videos which have not been submitted (only previews) and * delete them */ function video_upload_cron() { /* look for crusty files */ $temppath = file_directory_temp() . '/video/'; $files = file_scan_directory(file_create_path($temppath), '.*'); foreach ($files as $file => $info) { if (time() - filemtime($file) > 60*60*6) { db_query("DELETE FROM {files} WHERE filename LIKE 'video_upload_temp.%' AND nid = 1 AND filepath = '%s'", $file); file_delete($file); } } } /** * Implementation of hook_v_help */ function video_upload_v_help() { $help = array(); $help['upload']['data'] = '' . t('Upload support') . ''; $help['upload']['children'] = array(t('You can upload a video file from your computer to this website.')); return $help; } /** * Implementation of hook_v_info() */ function video_upload_v_info() { $info['upload'] = array( '#name' => 'Upload Video', '#description' => t('Post a video available on your computer as a file to this website.'), '#downloadable' => true, '#autothumbable' => module_exists('video_ffmpeg_helper') && variable_get('video_image_auto_thumbnail', false), '#autoresolution' => module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_resolution', false), '#autoplaytime' => module_exists('video_ffmpeg_helper') && variable_get('video_ffmpeg_helper_auto_playtime', false), ); return $info; } /** * Implements the hook_v_auto_thumnail */ function video_upload_v_auto_thumbnail(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_thumbnail($node); } return false; } /** * Implements the hook_v_auto_resolution */ function video_upload_v_auto_resolution(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_resolution($node); } return false; } /** * Implements the hook_v_auto_resolution */ function video_upload_v_auto_playtime(&$node) { // as we rely on ffmpeg_helper, let's check if we have video_ffmpeg_helper_installed if(module_exists('video_ffmpeg_helper')) { return _video_ffmpeg_helper_auto_playtime($node); } return false; } /** * Implements the hook_v_download */ function video_upload_v_download($node) { // the code below comes from the audio.module // The mime_header_encode function does not (yet) support // quoted-string encoding of ASCII strings with special // characters. See discussion at http://drupal.org/node/82614 $filename = basename($node->current_video_upload_file->filename); // If the string contains non-ASCII characters, process it through // the mime_header_encode function. if (preg_match('/[^\x20-\x7E]/', $filename)) { $filename = mime_header_encode($filename); } // Otherwise, if the string contains special characters (like // space), perform quoted-string encoding. elseif (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $filename)) { $filename = '"'. str_replace('"', '\"', $filename) .'"'; } $headers = array( 'Content-Type: '. mime_header_encode($node->current_video_upload_file->filemime), 'Content-Length: '. $node->current_video_upload_file->filesize, 'Content-Disposition: attachment; filename='. $filename, ); video_upload_file_transfer($node->current_video_upload_file->filepath, $headers); } /** * Variation on Drupal's file_transfer() function. The only difference * is that set_time_limit() is called to allow for large files. * This code comes from audio module * * @param $source File to transfer. * @param $headers An array of http headers to send along with file. */ function video_upload_file_transfer($source, $headers) { ob_end_clean(); foreach ($headers as $header) { // To prevent HTTP header injection, we delete new lines that are // not followed by a space or a tab. // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 $header = preg_replace('/\r?\n(?!\t| )/', '', $header); header($header); } $source = file_create_path($source); // Transfer file in 1024 byte chunks to save memory usage. if ($fd = fopen($source, 'rb')) { if (!ini_get('safe_mode')){ set_time_limit(0); } while (!feof($fd)) { print fread($fd, 1024); ob_flush(); flush(); } fclose($fd); } else { drupal_not_found(); } exit(); } /** * Implementation of hook_v_form() */ function video_upload_v_form(&$node, &$form) { //print 'form'; // add js stuff for the 'upload in progess' message theme('video_upload_get_script'); // add hidden html used for the 'upload in progess' message $form['#suffix'] = theme('video_upload_busy'); // required for upload to work $form['#attributes']['enctype'] = 'multipart/form-data'; $form['video'] += _video_upload_form($node); return $form; } /** * Implementation of hook_nodeapi() */ function video_upload_nodeapi(&$node, $op) { if($node->type == 'video' && $node->vtype == 'upload') { switch ($op) { case 'load': //exit; //print_r($node); //exit; return _video_upload_load($node); case 'prepare': //exit; _video_upload_prepare($node); break; case 'validate': //exit; //_video_upload_validate($node); break; case 'presave': //exit; //_video_upload_submit($node); break; case 'submit': // exit; //_video_upload_submit($node); break; case 'insert': //exit; //print_r($node); //exit; //_video_upload_submit($node); //_video_upload_insert($node); _video_upload_validate($node); break; case 'update': // exit; _video_upload_update($node); break; case 'delete': //exit; _video_upload_delete($node); break; case 'delete revision': //exit; video_upload_delete_revision($node); break; case 'view': // exit; _video_upload_view($node); } } } function _video_upload_load(&$node) { //print 'load'; //print_r($node); //exit; $fileBuf = db_fetch_object(db_query('SELECT fid FROM {upload} WHERE nid = %d', $node->nid)); $output = array(); $output['video_fid'] = $fileBuf->fid; $file = _video_upload_get_file($output['video_fid']); $output['current_video_upload_file'] = $file; $output['vidfile'] = file_create_url($file->filepath); // set the filesize $output['size'] = $file->filesize; //print_r($output); return $output; } /* The following hooks implementation is pretty Drupal voodoo :-) .. you should be pretty confortable on drupal apis. See http://www.varesano.net/blog/fabio/understanding+drupal+hook+nodeapi+execution+order for some hints */ function _video_upload_prepare(&$node) { //print 'prepare'; //exit; if (!count($_POST)) return; //print 'prepare'; //print_r($node); //exit; if (is_object($node->video_upload_file)) { $file_field = $node->video_upload_file; } else { $file_field = 'video_upload_file'; } /* TODO Modify the validators array to suit your needs. This array is used in the revised file_save_upload */ $validators = array( 'file_validate_is_image' => array(), 'file_validate_image_resolution' => array('85x85'), 'file_validate_size' => array(30 * 1024), ); if (count($_POST) && $file = file_save_upload($file_field , $validators) ){ // a file has been uploaded // this is the temp directory to store files $temppath = file_directory_temp() . '/video/'; // let's check that the directory is good file_check_directory($temppath, TRUE); // let's save the uploaded file to the temp directory $file = file_save_upload($file, $temppath . '/' . $file->filename, FILE_EXISTS_REPLACE); // let's store the temp file into the DB $file->fid = db_last_insert_id('files','fid'); db_query("INSERT INTO {files} (fid, filename, filepath, filemime, filesize) VALUES (%d, '%s', '%s', '%s', %d)", $file->fid, 'video_upload_temp.'.$file->filename, $file->filepath, $file->filemime, $file->filesize); // TODO: delete here the previous $node->new_video_upload_file $node->new_video_upload_file = $file; } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Submit') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Preview') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } } /** * Create video upload specific form fields */ function _video_upload_form(&$node) { _video_upload_check_settings(); $form = array(); if($node->new_video_upload_file) { // there is a newly uploaded file (this has been initialized by _prepare()) $form['new_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => $node->new_video_upload_file->fid); $form['new_video_upload_file_info'] = array('#type' => 'item', '#value' => theme('video_upload_file_info_form', $node->new_video_upload_file, $node), '#weight' => -10); $we_have_video = true; } else { $form['new_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => 0); if($node->current_video_upload_file) { // we don't have a new file $form['current_video_upload_file_fid'] = array('#type' => 'hidden', '#value' => $node->current_video_upload_file->fid); $form['current_video_upload_file_info'] = array('#type' => 'item', '#value' => theme('video_upload_file_info_form', $node->current_video_upload_file, $node), '#weight' => -10); $we_have_video = true; } } $form['video_upload_file'] = array( '#type' => 'file', '#title' => $we_have_video ? t('Replace with') : t('Upload video file'), '#size' => 40, '#weight' => -9, '#description' => t('Choose a video file from your pc.
NOTE: The max upload size is') . ' ' . format_size(file_upload_max_size()) . '.', // no need to set this as required as we do validation in the validate nodeapi hook ); return $form; } /** * Validate video file */ function _video_upload_validate(&$node) { //print 'validate'; //print_r($node); die; //##################### PREPARE ########################## if (is_object($node->video_upload_file)) { $file_field = $node->video_upload_file; } else { $file_field = 'video_upload_file'; } /* TODO Modify the validators array to suit your needs. This array is used in the revised file_save_upload $validators = array( 'file_validate_is_image' => array(), 'file_validate_image_resolution' => array('85x85'), 'file_validate_size' => array(30 * 1024), ); */ // get extention list $extentions = explode(",",variable_get('video_upload_allowed_extensions', 'mov,flv,wmv')); $validators = array( 'file_validate_extensions' => array(variable_get('video_upload_allowed_extensions', 'mov,flv,wmv')) ); // TODO : add file sixe validation // 'file_validate_size' => array($limits['file_size'], $limits['user_size']), if (count($_POST) && $file = file_save_upload($file_field , $validators) ){ // a file has been uploaded // this is the temp directory to store files //$temppath = file_directory_temp() . '/video/'; // let's check that the directory is good //file_check_directory($temppath, TRUE); // let's save the uploaded file to the temp directory //$file = file_save_upload($file, $validators, $temppath . '/' . $file->filename, FILE_EXISTS_REPLACE); //TODO : set status value //$status=0; // let's store the temp file into the DB //$file->fid = db_last_insert_id('files','fid'); //db_query("INSERT INTO {files} (fid, filename, filepath, filemime, filesize,status) VALUES (%d, '%s', '%s', '%s', %d, %d)", $file->fid, 'video_upload_temp.'.$file->filename, $file->filepath, $file->filemime, $file->filesize, $file->status); // TODO: delete here the previous $node->new_video_upload_file //print_r($file); //exit; $node->new_video_upload_file = $file->fid; $node->new_video_upload_file_fid = $file->fid; } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Submit') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Preview') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } //print_r($node); //exit; //######################################################### if(!($node->new_file_uploaded || $node->new_video_upload_file_fid > 0 || $node->new_video_upload_file_fid > 0 || $node->current_video_upload_file_fid > 0)) { // form_set_error('video_upload_file', t('You have not provided any video file. Please upload one.
If you uploaded a video but the system did not received it, please check that it is smaller than') . ' ' . format_size(file_upload_max_size()).'.'); } else if($node->new_file_uploaded || $node->new_video_upload_file_fid > 0 || $node->new_video_upload_file_fid > 0){ if($node->new_file_uploaded) { // only if the user oploaded a new file $file = $node->new_file_uploaded; } else { $file = _video_upload_get_file($node->new_video_upload_file_fid); } // let's check file extension $extensions = variable_get('video_upload_allowed_extensions', 'mov,flv,wmv'); $regex = '/\.('. ereg_replace(',+', '|', preg_quote($extensions)) .')$/i'; if (!preg_match($regex, $file->filename)) { //set an error message and delete the the file form_set_error('audio', t('The selected file %name can not be uploaded, because it is only possible to upload files with the following extensions: %files-allowed.', array('%name' => $file->filename, '%files-allowed' => $extensions))); _video_upload_delete_file($file); } } //call to submit function //print_r($node); //exit; _video_upload_submit($file,$node); } function _video_upload_submit(&$file,&$node) { //print 'submit'; //print_r($node); die; if($node->new_video_upload_file_fid) { $fid = $node->new_video_upload_file_fid; } else { $fid = $node->current_video_upload_file_fid; } $node->serial_data['video_fid'] = $fid; _video_upload_insert($file,$node); } function _video_upload_insert(&$file,&$node) { // global $file; //print 'insert'; //print_r($node); die; // if($node->new_video_upload_file_fid && $file = _video_upload_get_file($node->new_video_upload_file_fid)) { // there is a new file uploaded (now stored on the temp path); need to store in the final directory //print_r($node); //exit; _video_upload_store_file($file, $node); //} } function _video_upload_update(&$node) { //##################### PREPARE ########################## if (is_object($node->video_upload_file)) { $file_field = $node->video_upload_file; } else { $file_field = 'video_upload_file'; } /* TODO Modify the validators array to suit your needs. This array is used in the revised file_save_upload $validators = array( 'file_validate_is_image' => array(), 'file_validate_image_resolution' => array('85x85'), 'file_validate_size' => array(30 * 1024), ); */ // get extention list $extentions = explode(",",variable_get('video_upload_allowed_extensions', 'mov,flv,wmv')); $validators = array( 'file_validate_extensions' => array(variable_get('video_upload_allowed_extensions', 'mov,flv,wmv')) ); // TODO : add file sixe validation // 'file_validate_size' => array($limits['file_size'], $limits['user_size']), if (count($_POST) && $file = file_save_upload($file_field , $validators) ){ // a file has been uploaded // this is the temp directory to store files //$temppath = file_directory_temp() . '/video/'; // let's check that the directory is good //file_check_directory($temppath, TRUE); // let's save the uploaded file to the temp directory //$file = file_save_upload($file, $validators, $temppath . '/' . $file->filename, FILE_EXISTS_REPLACE); //TODO : set status value //$status=0; // let's store the temp file into the DB //$file->fid = db_last_insert_id('files','fid'); //db_query("INSERT INTO {files} (fid, filename, filepath, filemime, filesize,status) VALUES (%d, '%s', '%s', '%s', %d, %d)", $file->fid, 'video_upload_temp.'.$file->filename, $file->filepath, $file->filemime, $file->filesize, $file->status); // TODO: delete here the previous $node->new_video_upload_file //print_r($file); //exit; $node->new_video_upload_file = $file->fid; $node->new_video_upload_file_fid = $file->fid; } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Submit') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } else if (($node->new_video_upload_file_fid || $_POST['new_video_upload_file_fid']) && $_POST['op'] == 'Preview') { $node->new_video_upload_file = _video_upload_get_file($_POST['new_video_upload_file_fid']); } //print_r($node); //exit; //######################################################### if($node->new_video_upload_file_fid && $file = _video_upload_get_file($node->new_video_upload_file_fid)) { // there is a new file uploaded (now stored on the temp path) //need to store in the final directory //exit; _video_upload_store_file($file, $node); ///print_r($node); //exit; //$node = _video_upload_load($node); if($node->current_video_upload_file_fid) { // let's delete the old video _video_upload_delete_file($node->current_video_upload_file_fid); } } } /** * Delete files associated to this video node */ function _video_upload_delete(&$node) { //print 'delete'; // delete file file_delete($node->current_video_upload_file->path); // delete file information from database db_query('DELETE FROM {upload} WHERE fid = %d', $node->current_video_upload_file->fid); db_query('DELETE FROM {files} WHERE fid = %d', $node->current_video_upload_file->fid); } /** * */ function _video_upload_view(&$node) { //print 'view'; } /** * Move a temp file into the final directory associating it with the node */ function _video_upload_store_file(&$file, &$node) { //global $file; // $file->filename is video_upload_temp.realfile.ext : let's restore original filename //print_r($file); //exit; $file->filename = _video_get_original_filename($file->filename); _video_upload_get_path($file, $node); if (file_move($file, file_directory_path())) { // file moved successfully // update the file db entry db_query("UPDATE {files} SET filename = '%s', filepath = '%s', filemime = '%s', filesize = %d WHERE fid = %d", $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->fid); // add an entry in the file_revisions table db_query("INSERT INTO {upload} (fid, nid, vid, list, description) VALUES (%d, %d, %d, %d, '%s')", $file->fid, $node->nid, $node->vid, $file->list, $file->description); // update the file db entry //db_query("UPDATE {video} SET serialized_data = '%s' WHERE vid = %d", $file->filename, $file->filepath, $file->filemime, $file->filesize, $file->fid); } else { drupal_set_message(t('An error occurred during file saving. Your video file has not been stored.'), 'error'); $rep = array( '!path' => $file, '!dest' => $dest_path, ); watchdog('video_upload', 'moving file !path to !dest failed', $rep); } } /** * Gets the definitive path for stored videos */ function _video_upload_get_path(&$file, &$node) { // this code is from uploadpath.module $file_name = str_replace(array(' ', "\n", "\t"), '_', token_replace(variable_get('video_upload_path_prefix', 'videos') . '/', 'node', $node)) . $file->filename; // Create the directory if it doesn't exist yet. $dirs = explode('/', dirname($file_name)); $directory = file_directory_path(); while (count($dirs)) { $directory .= '/' . array_shift($dirs); file_check_directory($directory, FILE_CREATE_DIRECTORY); } $file->filename = $file_name; } /** * Get the file object with the given $fid. This function cache its results */ function _video_upload_get_file($fid) { static $files = array(); if (!$fid) { return null; } if (!isset($files[$fid])) { $files[$fid] = db_fetch_object(db_query('SELECT * from {files} WHERE fid = %d', $fid)); } return $files[$fid]; } /** * Delete a file */ function _video_upload_delete_file($file) { // delete file file_delete($file->path); // delete file information from database db_query('DELETE FROM {upload} WHERE fid = %d', $file); db_query('DELETE FROM {files} WHERE fid = %d', $file); } /** * Display informations about already uploaded file */ function theme_video_upload_file_info_form($file, $node) { // create array containing uploaded file informations $items = array( ''. t('file name') .': ' . _video_get_original_filename(basename($file->filename)), // do not display parent folders ''. t('file size') .': ' . format_size($file->filesize), ); // create information list $output .= theme_item_list($items, t('uploaded video information:')); return $output; } /** * Return the original filename (without 'video_upload_temp.') */ function _video_get_original_filename($filename) { if(strpos($filename, 'video_upload_temp.') === 0) { return substr($filename, strlen('video_upload_temp.')); } return $filename; } /** * Verify the video_upload module settings. */ function _video_upload_check_settings() { /* // File paths $video_path = file_create_path(variable_get('video_upload_default_path', 'videos')); $temp_path = rtrim($video_path, '/') . '/temp'; if (!file_check_directory($video_path, FILE_CREATE_DIRECTORY, 'video_upload_default_path')) { return false; } if (!file_check_directory($temp_path, FILE_CREATE_DIRECTORY, 'video_upload_default_path')) { return false; } */ return true; } /** * Import the video_upload.js script */ function theme_video_upload_get_script() { drupal_add_js(drupal_get_path('module', 'video_upload') . '/video_upload.js'); } /** * Renders a 'upload in progress' message */ function theme_video_upload_busy() { return ''; } /** * Implementation of hook_v_play */ function video_upload_v_play($node) { module_load_include('inc', 'video', '/includes/common'); return _video_common_get_player($node); } /** * Function to other modules to use to create image nodes. * * @param $filepath * String filepath of an image file. Note that this file will be moved into * the image module's images directory. * @param $title * String to be used as the node's title. If this is ommitted the filename * will be used. * @param $body * String to be used as the node's body. * @param $taxonomy * Taxonomy terms to assign to the node if the taxonomy.module is installed. * @return * A node object if the node is created successfully or FALSE on error. */ function video_upload_create_node_from($filepath, $title = NULL, $body = '', $taxonomy = NULL) { global $user; if (!user_access('create video')) { drupal_access_denied(); } if (!is_object($filepath)) { $p = $filepath; $filepath = new stdClass(); $filepath->filepath = $p; $filepath->filename = basename($p); $filepath->filesize = filesize($p); } // Ensure it's a valid video //if (!$image_info = image_get_info($filepath)) { // return FALSE; //} // Build the node. $node = new stdClass(); $node->type = 'video'; $node->vtype = 'upload'; $node->uid = $user->uid; $node->name = $user->name; $node->title = isset($title) ? $title : basename($filepath); $node->body = $body; // Set the node's defaults... (copied this from node and comment.module) $node_options = variable_get('node_options_'. $node->type, array('status', 'promote')); $node->status = in_array('status', $node_options); $node->promote = in_array('promote', $node_options); if (module_exists('comment')) { $node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE); } if (module_exists('taxonomy')) { $node->taxonomy = $taxonomy; } $node->video_upload_file = $filepath; node_invoke_nodeapi($node, 'prepare'); $node->new_video_upload_file_fid = $node->new_video_upload_file->fid; // Save the node. $node = node_submit($node); node_save($node); // Remove the original image now that the import has completed. file_delete($original_path); return $node; } /** * Implementation of hook_theme(). */ function video_upload_theme() { return array( 'video_upload_busy' => array( 'arguments' => array(), ), 'video_upload_file_info_form' => array( 'arguments' => array('file' => NULL,'node' => NULL), ), 'video_upload_get_script' => array( 'arguments' => array(), ), 'video_play_dcr' => array( 'arguments' => array('node' => NULL), ), 'video_play_divx' => array( 'arguments' => array('node' => NULL), ), 'video_play_flash' => array( 'arguments' => array('node' => NULL), ), 'video_play_ogg_theora' => array( 'arguments' => array('node' => NULL), ), 'video_play_quicktime' => array( 'arguments' => array('node' => NULL), ), 'video_play_realmedia' => array( 'arguments' => array('node' => NULL), ), 'video_play_swf' => array( 'arguments' => array('node' => NULL), ), 'video_play_windowsmedia' => array( 'arguments' => array('node' => NULL), ), ); }