]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-14233 Make bulk user picture upload handle subdirectories in zip files, merged...
authorjerome <jerome>
Thu, 3 Jul 2008 07:35:24 +0000 (07:35 +0000)
committerjerome <jerome>
Thu, 3 Jul 2008 07:35:24 +0000 (07:35 +0000)
admin/uploadpicture.php

index e8122bf6f19870325f43df6b51f095e767c9682e..bce28a86d7b4ab6763ab230bbb52e7f83e4a3692 100644 (file)
@@ -26,6 +26,10 @@ require_once($CFG->libdir.'/adminlib.php');
 require_once($CFG->libdir.'/gdlib.php');
 require_once('uploadpicture_form.php');
 
+define ('PIX_FILE_UPDATED', 0);
+define ('PIX_FILE_ERROR',   1);
+define ('PIX_FILE_SKIPPED', 2);    
+    
 $adminroot = admin_get_root();
 
 admin_externalpage_setup('uploadpictures', $adminroot);
@@ -46,8 +50,6 @@ $strfile = get_string('file');
 $struser = get_string('user');
 $strusersupdated = get_string('usersupdated');
 $struploadpictures = get_string('uploadpictures','admin');
-$usersupdated = 0;
-$userserrors = 0;
 
 $userfields = array (
     0 => 'username',
@@ -91,60 +93,16 @@ if ($formdata = $mform->get_data()) {
                 // We don't need the zip file any longer, so delete it to make
                 // it easier to process the rest of the files inside the directory.
                 @unlink($dstfile);
-                if(! ($handle = opendir($zipdir))) {
-                    notify(get_string('uploadpicture_cannotprocessdir','admin'));
-                } else {
-                    while (false !== ($item = readdir($handle))) {
-                        if($item != '.' && $item != '..' && is_file($zipdir.'/'.$item)) {
-                            
-                            // Add additional checks on the filenames, as they are user
-                            // controlled and we don't want to open any security holes.
-                            $path_parts = pathinfo(cleardoubleslashes($item));
-                            $basename  = $path_parts['basename'];
-                            $extension = $path_parts['extension'];
-                            if ($basename != clean_param($basename, PARAM_CLEANFILE)) {
-                                // The original picture file name has invalid characters
-                                notify(get_string('uploadpicture_invalidfilename', 'admin',
-                                                  clean_param($basename, PARAM_CLEANHTML)));
-                                continue;
-                            }
-
-                            // The picture file name (without extension) must match the
-                            // userfield attribute.
-                            $uservalue = substr($basename, 0,
-                                                strlen($basename) -
-                                                strlen($extension) - 1);
-                            // userfield names are safe, so don't quote them.
-                            if (!($user = $DB->get_record('user', array($userfields[$userfield], $uservalue)))) {
-                                $userserrors++;
-                                $a = new Object();
-                                $a->userfield = clean_param($userfields[$userfield], PARAM_CLEANHTML);
-                                $a->uservalue = clean_param($uservalue, PARAM_CLEANHTML);
-                                notify(get_string('uploadpicture_usernotfound', 'admin', $a));
-                                continue;
-                            }
-                            $haspicture = $DB->get_field('user', 'picture', array('id'=>$user->id));
-                            if ($haspicture && !$overwritepicture) {
-                                notify(get_string('uploadpicture_userskipped', 'admin', $user->username));
-                                continue;
-                            }
-                            if (my_save_profile_image($user->id, $zipdir.'/'.$item)) {
-                                $DB->set_field('user', 'picture', 1, array('id'=>$user->id));
-                                $usersupdated++;
-                                notify(get_string('uploadpicture_userupdated', 'admin', $user->username));
-                            } else {
-                                $userserrors++;
-                                notify(get_string('uploadpicture_cannotsave', 'admin', $user->username));
-                            }
-                        }
-                    }
-                }
-                closedir($handle);
+                
+                $results = array ('errors' => 0,'updated' => 0);
+
+                process_directory($zipdir, $userfields[$userfield], $overwritepicture, $results);
+
             
                 // Finally remove the temporary directory with all the user images and print some stats.
                 remove_dir($zipdir);
-                notify(get_string('usersupdated', 'admin') . ": $usersupdated");
-                notify(get_string('errors', 'admin') . ": $userserrors");
+                notify(get_string('usersupdated', 'admin') . ": " . $results['updated']);
+                notify(get_string('errors', 'admin') . ": " . $results['errors']);
                 echo '<hr />';
             }
         }
@@ -156,6 +114,17 @@ exit;
 
 // ----------- Internal functions ----------------
 
+/**
+ * Create a unique temporary directory with a given prefix name,
+ * inside a given directory, with given permissions. Return the
+ * full path to the newly created temp directory.
+ *
+ * @param string $dir where to create the temp directory.
+ * @param string $prefix prefix for the temp directory name (default '')
+ * @param string $mode permissions for the temp directory (default 700)
+ *
+ * @return string The full path to the temp directory.
+ */
 function my_mktempdir($dir, $prefix='', $mode=0700) {
     if (substr($dir, -1) != '/') {
         $dir .= '/';
@@ -168,6 +137,117 @@ function my_mktempdir($dir, $prefix='', $mode=0700) {
     return $path;
 }
 
+/**
+ * Recursively process a directory, picking regular files and feeding
+ * them to process_file().
+ *
+ * @param string $dir the full path of the directory to process
+ * @param string $userfield the prefix_user table field to use to
+ *               match picture files to users.
+ * @param bool $overwrite overwrite existing picture or not.
+ * @param array $results (by reference) accumulated statistics of
+ *              users updated and errors.
+ *
+ * @return nothing
+ */
+function process_directory ($dir, $userfield, $overwrite, &$results) {
+    if(!($handle = opendir($dir))) {
+        notify(get_string('uploadpicture_cannotprocessdir','admin'));
+        return;
+    }
+
+    while (false !== ($item = readdir($handle))) {
+        if ($item != '.' && $item != '..') {
+            if (is_dir($dir.'/'.$item)) {
+                process_directory($dir.'/'.$item, $userfield, $overwrite, $results);
+            } else if (is_file($dir.'/'.$item))  {
+                $result = process_file($dir.'/'.$item, $userfield, $overwrite);
+                switch ($result) {
+                    case PIX_FILE_ERROR:
+                        $results['errors']++;
+                        break;
+                    case PIX_FILE_UPDATED:
+                        $results['updated']++;
+                        break;
+                }
+            }
+            // Ignore anything else that is not a directory or a file (e.g.,
+            // symbolic links, sockets, pipes, etc.)
+        }
+    }
+    closedir($handle);
+}
+
+/**
+ * Given the full path of a file, try to find the user the file
+ * corresponds to and assign him/her this file as his/her picture.
+ * Make extensive checks to make sure we don't open any security holes
+ * and report back any success/error.
+ *
+ * @param string $file the full path of the file to process
+ * @param string $userfield the prefix_user table field to use to
+ *               match picture files to users.
+ * @param bool $overwrite overwrite existing picture or not.
+ *
+ * @return integer either PIX_FILE_UPDATED, PIX_FILE_ERROR or
+ *                  PIX_FILE_SKIPPED
+ */
+function process_file ($file, $userfield, $overwrite) {
+    global $DB;
+    
+    // Add additional checks on the filenames, as they are user
+    // controlled and we don't want to open any security holes.
+    $path_parts = pathinfo(cleardoubleslashes($file));
+    $basename  = $path_parts['basename'];
+    $extension = $path_parts['extension'];
+    if ($basename != clean_param($basename, PARAM_CLEANFILE)) {
+        // The original picture file name has invalid characters
+        notify(get_string('uploadpicture_invalidfilename', 'admin',
+                          clean_param($basename, PARAM_CLEANHTML)));
+        return PIX_FILE_ERROR;
+    }
+
+    // The picture file name (without extension) must match the
+    // userfield attribute.
+    $uservalue = substr($basename, 0,
+                        strlen($basename) -
+                        strlen($extension) - 1);
+
+    // userfield names are safe, so don't quote them.
+    if (!($user = $DB->get_record('user', array ($userfield => $uservalue)))) {
+        $a = new Object();
+        $a->userfield = clean_param($userfield, PARAM_CLEANHTML);
+        $a->uservalue = clean_param($uservalue, PARAM_CLEANHTML);
+        notify(get_string('uploadpicture_usernotfound', 'admin', $a));
+        return PIX_FILE_ERROR;
+    }
+
+    $haspicture = $DB->get_field('user', 'picture', array('id'=>$user->id));
+    if ($haspicture && !$overwrite) {
+        notify(get_string('uploadpicture_userskipped', 'admin', $user->username));
+        return PIX_FILE_SKIPPED;
+    }
+
+    if (my_save_profile_image($user->id, $file)) {
+        $DB->set_field('user', 'picture', 1, array('id'=>$user->id));
+        notify(get_string('uploadpicture_userupdated', 'admin', $user->username));
+        return PIX_FILE_UPDATED;
+    } else {
+        notify(get_string('uploadpicture_cannotsave', 'admin', $user->username));
+        return PIX_FILE_ERROR;
+    }
+}
+
+/**
+ * Try to save the given file (specified by its full path) as the
+ * picture for the user with the given id.
+ *
+ * @param integer $id the internal id of the user to assign the
+ *                picture file to.
+ * @param string $originalfile the full path of the picture file.
+ *
+ * @return bool 
+ */
 function my_save_profile_image($id, $originalfile) {
     $destination = create_profile_image_destination($id, 'user');
     if ($destination === false) {