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