Differences Between: [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Bulk upload of user pictures 19 * 20 * Based on .../admin/uploaduser.php and .../lib/gdlib.php 21 * 22 * @package tool 23 * @subpackage uploaduser 24 * @copyright (C) 2007 Inaki Arenaza 25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 26 */ 27 28 require('../../../config.php'); 29 require_once($CFG->libdir.'/adminlib.php'); 30 require_once($CFG->libdir.'/gdlib.php'); 31 require_once ('picture_form.php'); 32 33 define ('PIX_FILE_UPDATED', 0); 34 define ('PIX_FILE_ERROR', 1); 35 define ('PIX_FILE_SKIPPED', 2); 36 37 admin_externalpage_setup('tooluploaduserpictures'); 38 39 require_capability('tool/uploaduser:uploaduserpictures', context_system::instance()); 40 41 $site = get_site(); 42 43 if (!$adminuser = get_admin()) { 44 print_error('noadmins', 'error'); 45 } 46 47 $strfile = get_string('file'); 48 $struser = get_string('user'); 49 $strusersupdated = get_string('usersupdated', 'tool_uploaduser'); 50 $struploadpictures = get_string('uploadpictures','tool_uploaduser'); 51 52 $userfields = array ( 53 0 => 'username', 54 1 => 'idnumber', 55 2 => 'id' ); 56 57 $userfield = optional_param('userfield', 0, PARAM_INT); 58 $overwritepicture = optional_param('overwritepicture', 0, PARAM_BOOL); 59 60 /// Print the header 61 echo $OUTPUT->header(); 62 63 echo $OUTPUT->heading_with_help($struploadpictures, 'uploadpictures', 'tool_uploaduser'); 64 65 $mform = new admin_uploadpicture_form(null, $userfields); 66 if ($formdata = $mform->get_data()) { 67 if (!array_key_exists($userfield, $userfields)) { 68 echo $OUTPUT->notification(get_string('uploadpicture_baduserfield', 'tool_uploaduser')); 69 } else { 70 // Large files are likely to take their time and memory. Let PHP know 71 // that we'll take longer, and that the process should be recycled soon 72 // to free up memory. 73 core_php_time_limit::raise(); 74 raise_memory_limit(MEMORY_EXTRA); 75 76 // Create a unique temporary directory, to process the zip file 77 // contents. 78 $zipdir = my_mktempdir($CFG->tempdir.'/', 'usrpic'); 79 $dstfile = $zipdir.'/images.zip'; 80 81 if (!$mform->save_file('userpicturesfile', $dstfile, true)) { 82 echo $OUTPUT->notification(get_string('uploadpicture_cannotmovezip', 'tool_uploaduser')); 83 @remove_dir($zipdir); 84 } else { 85 $fp = get_file_packer('application/zip'); 86 $unzipresult = $fp->extract_to_pathname($dstfile, $zipdir); 87 if (!$unzipresult) { 88 echo $OUTPUT->notification(get_string('uploadpicture_cannotunzip', 'tool_uploaduser')); 89 @remove_dir($zipdir); 90 } else { 91 // We don't need the zip file any longer, so delete it to make 92 // it easier to process the rest of the files inside the directory. 93 @unlink($dstfile); 94 95 $results = array ('errors' => 0,'updated' => 0); 96 97 process_directory($zipdir, $userfields[$userfield], $overwritepicture, $results); 98 99 100 // Finally remove the temporary directory with all the user images and print some stats. 101 remove_dir($zipdir); 102 echo $OUTPUT->notification(get_string('usersupdated', 'tool_uploaduser') . ": " . $results['updated'], 'notifysuccess'); 103 echo $OUTPUT->notification(get_string('errors', 'tool_uploaduser') . ": " . $results['errors'], ($results['errors'] ? 'notifyproblem' : 'notifysuccess')); 104 echo '<hr />'; 105 } 106 } 107 } 108 } 109 $mform->display(); 110 echo $OUTPUT->footer(); 111 exit; 112 113 // ----------- Internal functions ---------------- 114 115 /** 116 * Create a unique temporary directory with a given prefix name, 117 * inside a given directory, with given permissions. Return the 118 * full path to the newly created temp directory. 119 * 120 * @param string $dir where to create the temp directory. 121 * @param string $prefix prefix for the temp directory name (default '') 122 * 123 * @return string The full path to the temp directory. 124 */ 125 function my_mktempdir($dir, $prefix='') { 126 global $CFG; 127 128 if (substr($dir, -1) != '/') { 129 $dir .= '/'; 130 } 131 132 do { 133 $path = $dir.$prefix.mt_rand(0, 9999999); 134 } while (file_exists($path)); 135 136 check_dir_exists($path); 137 138 return $path; 139 } 140 141 /** 142 * Recursively process a directory, picking regular files and feeding 143 * them to process_file(). 144 * 145 * @param string $dir the full path of the directory to process 146 * @param string $userfield the prefix_user table field to use to 147 * match picture files to users. 148 * @param bool $overwrite overwrite existing picture or not. 149 * @param array $results (by reference) accumulated statistics of 150 * users updated and errors. 151 * 152 * @return nothing 153 */ 154 function process_directory ($dir, $userfield, $overwrite, &$results) { 155 global $OUTPUT; 156 if(!($handle = opendir($dir))) { 157 echo $OUTPUT->notification(get_string('uploadpicture_cannotprocessdir', 'tool_uploaduser')); 158 return; 159 } 160 161 while (false !== ($item = readdir($handle))) { 162 if ($item != '.' && $item != '..') { 163 if (is_dir($dir.'/'.$item)) { 164 process_directory($dir.'/'.$item, $userfield, $overwrite, $results); 165 } else if (is_file($dir.'/'.$item)) { 166 $result = process_file($dir.'/'.$item, $userfield, $overwrite); 167 switch ($result) { 168 case PIX_FILE_ERROR: 169 $results['errors']++; 170 break; 171 case PIX_FILE_UPDATED: 172 $results['updated']++; 173 break; 174 } 175 } 176 // Ignore anything else that is not a directory or a file (e.g., 177 // symbolic links, sockets, pipes, etc.) 178 } 179 } 180 closedir($handle); 181 } 182 183 /** 184 * Given the full path of a file, try to find the user the file 185 * corresponds to and assign him/her this file as his/her picture. 186 * Make extensive checks to make sure we don't open any security holes 187 * and report back any success/error. 188 * 189 * @param string $file the full path of the file to process 190 * @param string $userfield the prefix_user table field to use to 191 * match picture files to users. 192 * @param bool $overwrite overwrite existing picture or not. 193 * 194 * @return integer either PIX_FILE_UPDATED, PIX_FILE_ERROR or 195 * PIX_FILE_SKIPPED 196 */ 197 function process_file ($file, $userfield, $overwrite) { 198 global $DB, $OUTPUT; 199 200 // Add additional checks on the filenames, as they are user 201 // controlled and we don't want to open any security holes. 202 $path_parts = pathinfo(cleardoubleslashes($file)); 203 $basename = $path_parts['basename']; 204 $extension = $path_parts['extension']; 205 206 // The picture file name (without extension) must match the 207 // userfield attribute. 208 $uservalue = substr($basename, 0, 209 strlen($basename) - 210 strlen($extension) - 1); 211 212 // userfield names are safe, so don't quote them. 213 if (!($user = $DB->get_record('user', array ($userfield => $uservalue, 'deleted' => 0)))) { 214 $a = new stdClass(); 215 $a->userfield = clean_param($userfield, PARAM_CLEANHTML); 216 $a->uservalue = clean_param($uservalue, PARAM_CLEANHTML); 217 echo $OUTPUT->notification(get_string('uploadpicture_usernotfound', 'tool_uploaduser', $a)); 218 return PIX_FILE_ERROR; 219 } 220 221 $haspicture = $DB->get_field('user', 'picture', array('id'=>$user->id)); 222 if ($haspicture && !$overwrite) { 223 echo $OUTPUT->notification(get_string('uploadpicture_userskipped', 'tool_uploaduser', $user->username)); 224 return PIX_FILE_SKIPPED; 225 } 226 227 if ($newrev = my_save_profile_image($user->id, $file)) { 228 $DB->set_field('user', 'picture', $newrev, array('id'=>$user->id)); 229 echo $OUTPUT->notification(get_string('uploadpicture_userupdated', 'tool_uploaduser', $user->username), 'notifysuccess'); 230 return PIX_FILE_UPDATED; 231 } else { 232 echo $OUTPUT->notification(get_string('uploadpicture_cannotsave', 'tool_uploaduser', $user->username)); 233 return PIX_FILE_ERROR; 234 } 235 } 236 237 /** 238 * Try to save the given file (specified by its full path) as the 239 * picture for the user with the given id. 240 * 241 * @param integer $id the internal id of the user to assign the 242 * picture file to. 243 * @param string $originalfile the full path of the picture file. 244 * 245 * @return mixed new unique revision number or false if not saved 246 */ 247 function my_save_profile_image($id, $originalfile) { 248 $context = context_user::instance($id); 249 return process_new_icon($context, 'user', 'icon', 0, $originalfile); 250 } 251 252
title
Description
Body
title
Description
Body
title
Description
Body
title
Body