From: mjollnir_ Date: Tue, 14 Sep 2004 22:58:13 +0000 (+0000) Subject: Centralised file upload code, integration with clam AV, integration with some modules... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=18b8fbfa0dbaad888cab24eac7d7e1b13521f857;p=moodle.git Centralised file upload code, integration with clam AV, integration with some modules: assignment, exercise, forum, glossaryt, resource, scorm (more to come soon). These patches are maintained in an publicly accessible Arch repository, see: http://lists.eduforge.org/cgi-bin/archzoom.cgi/arch-eduforge@catalyst.net.nz--2004-MIRROR/moodle--eduforge--1.3.3 Index of arch patches in this commit: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-15 final touches to sears stuff until testing can begin, beginning of magical uploadey wrappery function goodness arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-18 Virus scanning on upload arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-19 made emacs use spaces instead of tabs and fixed lib/moodlelib.php where it was bad in the new functions; few wording changes, added in support for clamdscan arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-20 handlevirus.php = new script to handle output of clamscan (designed for cron clamscan), changes to strings for emailing out virus notifications, changes to moodlelib - slightly different notice reporting in handle_infected_file and new function for replacing file with message arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-21 refactor to filter out invalid lines in input to handlevirus arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-22 modified assignment to use hande_file_upload arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-25 bug fix for handle_file_upload arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-26 Small fix for non thinking brain doing something silly arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-35 small fix to switch order of items in drop down to allow sensible defaults arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-36 small changes to strings file arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-38 taken stuff out of moodlelib to put in upload class arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-39 new upload class -in a changeset by itself just in case - not quite finished arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-40 tweaks to upload class - clam_scan_file can now take a path as an argument, not just an entry from _FILES, there is better handling of failure and notification, more allowance for module writers to keep control in general. Also slightly nicer strings entries for a few things arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-41 upload class integration with assignment module, bug fix, slight tweak arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-42 small changes to uploadlib, integration with assessment and assignment arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-44 tweaks for assessment and assignment for uploading arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-48 integration with exercise module arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-49 integration of virus stuff with forum module arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-50 integration of upload class and glossary module arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-51 just in case glossary_move_attachments is ever used, we change the log entries before we move the files. also moved clam_log_upload out of the class arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-52 virus scanning for imports for glossary arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-53 relog entries when moving files attached to forum posts arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-54 resource module integration with virus scanning arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-55 scorm integration with upload/virus class arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-56 fix for handlevirus.php since upload class changes Full logs: Revision: moodle--eduforge--1.3.3--patch-15 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Wed Sep 1 17:28:13 NZST 2004 Standard-date: 2004-09-01 05:28:13 GMT Modified-files: lang/en/moodle.php lib/moodlelib.php mod/assessment/sears.php mod/assessment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-15 Summary: final touches to sears stuff until testing can begin, beginning of magical uploadey wrappery function goodness Keywords: Revision: moodle--eduforge--1.3.3--patch-18 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Thu Sep 2 15:49:54 NZST 2004 Standard-date: 2004-09-02 03:49:54 GMT Modified-files: admin/config.html lang/en/moodle.php lib/moodlelib.php mod/assessment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-18 Summary: Virus scanning on upload Keywords: Revision: moodle--eduforge--1.3.3--patch-19 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Thu Sep 2 17:06:14 NZST 2004 Standard-date: 2004-09-02 05:06:14 GMT Modified-files: lang/en/moodle.php lib/moodlelib.php mod/assessment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-19 Summary: made emacs use spaces instead of tabs and fixed lib/moodlelib.php where it was bad in the new functions; few wording changes, added in support for clamdscan Keywords: Revision: moodle--eduforge--1.3.3--patch-20 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 3 16:06:05 NZST 2004 Standard-date: 2004-09-03 04:06:05 GMT New-files: admin/.arch-ids/handlevirus.php.id admin/handlevirus.php Modified-files: lang/en/moodle.php lib/moodlelib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-20 Summary: handlevirus.php = new script to handle output of clamscan (designed for cron clamscan), changes to strings for emailing out virus notifications, changes to moodlelib - slightly different notice reporting in handle_infected_file and new function for replacing file with message Keywords: Revision: moodle--eduforge--1.3.3--patch-21 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 6 11:37:31 NZST 2004 Standard-date: 2004-09-05 23:37:31 GMT Modified-files: admin/handlevirus.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-21 Summary: refactor to filter out invalid lines in input to handlevirus Keywords: Revision: moodle--eduforge--1.3.3--patch-22 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 6 13:07:48 NZST 2004 Standard-date: 2004-09-06 01:07:48 GMT Modified-files: mod/assignment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-22 Summary: modified assignment to use hande_file_upload Keywords: Revision: moodle--eduforge--1.3.3--patch-25 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 6 16:32:11 NZST 2004 Standard-date: 2004-09-06 04:32:11 GMT Modified-files: lib/moodlelib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-25 Summary: bug fix for handle_file_upload Keywords: Revision: moodle--eduforge--1.3.3--patch-26 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 6 16:51:50 NZST 2004 Standard-date: 2004-09-06 04:51:50 GMT Modified-files: lib/moodlelib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-26 Summary: Small fix for non thinking brain doing something silly Keywords: Revision: moodle--eduforge--1.3.3--patch-35 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 10:09:53 NZST 2004 Standard-date: 2004-09-09 22:09:53 GMT Modified-files: admin/config.html New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-35 Summary: small fix to switch order of items in drop down to allow sensible defaults Keywords: Revision: moodle--eduforge--1.3.3--patch-36 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 10:11:29 NZST 2004 Standard-date: 2004-09-09 22:11:29 GMT Modified-files: lang/en/moodle.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-36 Summary: small changes to strings file Keywords: Revision: moodle--eduforge--1.3.3--patch-38 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 10:17:24 NZST 2004 Standard-date: 2004-09-09 22:17:24 GMT Modified-files: lib/moodlelib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-38 Summary: taken stuff out of moodlelib to put in upload class Keywords: Revision: moodle--eduforge--1.3.3--patch-39 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 10:21:21 NZST 2004 Standard-date: 2004-09-09 22:21:21 GMT New-files: lib/.arch-ids/uploadlib.php.id lib/uploadlib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-39 Summary: new upload class -in a changeset by itself just in case - not quite finished Keywords: Revision: moodle--eduforge--1.3.3--patch-40 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 11:58:24 NZST 2004 Standard-date: 2004-09-09 23:58:24 GMT Modified-files: lang/en/moodle.php lib/uploadlib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-40 Summary: tweaks to upload class - clam_scan_file can now take a path as an argument, not just an entry from _FILES, there is better handling of failure and notification, more allowance for module writers to keep control in general. Also slightly nicer strings entries for a few things Keywords: Revision: moodle--eduforge--1.3.3--patch-41 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 12:38:02 NZST 2004 Standard-date: 2004-09-10 00:38:02 GMT Modified-files: lib/uploadlib.php mod/assignment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-41 Summary: upload class integration with assignment module, bug fix, slight tweak Keywords: Revision: moodle--eduforge--1.3.3--patch-42 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 15:30:20 NZST 2004 Standard-date: 2004-09-10 03:30:20 GMT Modified-files: lib/uploadlib.php mod/assessment/upload.php mod/assessment/view.php mod/assignment/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-42 Summary: small changes to uploadlib, integration with assessment and assignment Keywords: Revision: moodle--eduforge--1.3.3--patch-44 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Fri Sep 10 16:54:40 NZST 2004 Standard-date: 2004-09-10 04:54:40 GMT Modified-files: mod/assessment/lib.php mod/assignment/lib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-44 Summary: tweaks for assessment and assignment for uploading Keywords: Revision: moodle--eduforge--1.3.3--patch-48 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 09:57:03 NZST 2004 Standard-date: 2004-09-12 21:57:03 GMT Modified-files: lang/en/moodle.php mod/exercise/locallib.php mod/exercise/upload.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-48 Summary: integration with exercise module Keywords: Revision: moodle--eduforge--1.3.3--patch-49 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 11:35:46 NZST 2004 Standard-date: 2004-09-12 23:35:46 GMT Modified-files: mod/forum/lib.php mod/forum/post.html New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-49 Summary: integration of virus stuff with forum module Keywords: Revision: moodle--eduforge--1.3.3--patch-50 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 14:00:29 NZST 2004 Standard-date: 2004-09-13 02:00:29 GMT Modified-files: lang/en/glossary.php mod/glossary/edit.html mod/glossary/edit.php mod/glossary/lib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-50 Summary: integration of upload class and glossary module Keywords: Revision: moodle--eduforge--1.3.3--patch-51 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 15:13:02 NZST 2004 Standard-date: 2004-09-13 03:13:02 GMT Modified-files: lib/uploadlib.php mod/glossary/lib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-51 Summary: just in case glossary_move_attachments is ever used, we change the log entries before we move the files. also moved clam_log_upload out of the class Keywords: Revision: moodle--eduforge--1.3.3--patch-52 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 15:26:56 NZST 2004 Standard-date: 2004-09-13 03:26:56 GMT Modified-files: mod/glossary/import.html mod/glossary/import.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-52 Summary: virus scanning for imports for glossary Keywords: Revision: moodle--eduforge--1.3.3--patch-53 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 16:02:22 NZST 2004 Standard-date: 2004-09-13 04:02:22 GMT Modified-files: mod/forum/lib.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-53 Summary: relog entries when moving files attached to forum posts Keywords: Revision: moodle--eduforge--1.3.3--patch-54 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Mon Sep 13 16:58:37 NZST 2004 Standard-date: 2004-09-13 04:58:37 GMT Modified-files: mod/resource/coursefiles.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-54 Summary: resource module integration with virus scanning Keywords: Revision: moodle--eduforge--1.3.3--patch-55 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Tue Sep 14 16:15:47 NZST 2004 Standard-date: 2004-09-14 04:15:47 GMT Modified-files: mod/scorm/coursefiles.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-55 Summary: scorm integration with upload/virus class Keywords: Revision: moodle--eduforge--1.3.3--patch-56 Archive: arch-eduforge@catalyst.net.nz--2004 Creator: Penny Leach Date: Wed Sep 15 10:33:23 NZST 2004 Standard-date: 2004-09-14 22:33:23 GMT Modified-files: admin/handlevirus.php New-patches: arch-eduforge@catalyst.net.nz--2004/moodle--eduforge--1.3.3--patch-56 Summary: fix for handlevirus.php since upload class changes Keywords: --- diff --git a/admin/config.html b/admin/config.html index f642c1c3f3..18bbaad5e8 100644 --- a/admin/config.html +++ b/admin/config.html @@ -476,6 +476,40 @@ + +

runclamonupload:

+ + runclamonupload,"","",""); + ?> + + + + +

pathtoclam:

+ + + + +

quarantinedir:

+ + + + +

clamfailureonupload

+ clamfailureonupload,"","",""); + ?> + +

fullnamedisplay: diff --git a/admin/handlevirus.php b/admin/handlevirus.php new file mode 100644 index 0000000000..a2b1bf3b38 --- /dev/null +++ b/admin/handlevirus.php @@ -0,0 +1,99 @@ + 2>&1 | php thisfile.php + * also it's important that the output of clamscan prints the FULL PATH to each infected file, so use absolute paths for area to scan + */ + + +$fd = fopen('php://stdin','r'); +if (!$fd) { + exit(); +} + +$FULLME='cron'; +require_once(dirname(dirname(__FILE__)).'/config.php'); +require_once($CFG->dirroot.'/lib/uploadlib.php'); // contains virus handling stuff. + +$site = get_site(); + +while(!feof($fd)) { + $entry = fgets($fd); + if (strlen(trim($entry)) == 0) { + continue; + } + if (!$file = validate_line($entry)) { + continue; + } + $bits = explode('/',$file); + $a->filename = $bits[count($bits)-1]; + + if (!$log = get_record("log","module","upload","info",$file)) { + $a->action = clam_handle_infected_file($file,0,false); + clam_replace_infected_file($file); + notify_admins_unknown($file,$a); + continue; + } + $action = clam_handle_infected_file($file,$log->userid,true); + clam_replace_infected_file($file); + + $user = get_record("user","id",$log->userid); + $course = get_record("course","id",$log->course); + $subject = get_string('virusfoundsubject','moodle',$site->fullname); + $a->date = userdate($log->time); + + $a->action = $action; + $a->course = $course->fullname; + $a->user = $user->firstname.' '.$user->lastname; + + notify_user($user,$subject,$a); + notify_admins($user,$subject,$a); +} +fclose($fd); + + +function notify_user($user,$subject,$a) { + + if (!$user) { + return false; + } + $body = get_string('virusfoundlater','moodle',$a); + email_to_user($user,get_admin(),$subject,$body); +} + + +function notify_admins($user,$subject,$a) { + + $admins = get_admins(); + + $body = get_string('virusfoundlateradmin','moodle',$a); + foreach ($admins as $admin) { + email_to_user($admin,$admin,$subject,$body); + } +} + +function notify_admins_unknown($file,$a) { + + global $site; + + $admins = get_admins(); + $subject = get_string('virusfoundsubject','moodle',$site->fullname); + $body = get_string('virusfoundlateradminnolog','moodle',$a); + foreach ($admins as $admin) { + email_to_user($admin,$admin,$subject,$body); + } +} + +function validate_line($line) { + if (strpos($line,"FOUND") === false) { + return false; + } + $index = strpos($line,":"); + $file = substr($line,0,$index); + $file = preg_replace('/\/\//','/',$file); + if (!file_exists($file)) { + return false; + } + return $file; +} + +?> diff --git a/lang/en/glossary.php b/lang/en/glossary.php index c9fe9de12f..b7d790644e 100644 --- a/lang/en/glossary.php +++ b/lang/en/glossary.php @@ -85,6 +85,8 @@ $string['entrydeleted'] = 'Entry deleted'; $string['entryexported'] = 'Entry succesfully exported'; $string['entryishidden'] = '(this entry is currently hidden)'; $string['entryleveldefaultsettings'] = 'Entry Level Default Settings'; +$string['entrysaved'] = 'This entry has been saved'; +$string['entryupdated'] = 'This entry has been updated'; $string['entryusedynalink'] = 'This entry should be automatically linked'; $string['explainaddentry'] = 'Add a new entry to the current glossary.
Concept and definition are mandatory fields.'; $string['explainall'] = 'Shows ALL entries on one page'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index bd19dfb142..1480fbaa46 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -143,6 +143,17 @@ $string['choosereportfilter'] = 'Choose a filter for the report'; $string['choosetheme'] = 'Choose theme'; $string['chooseuser'] = 'Choose a user'; $string['city'] = 'City/town'; +$string['clambroken'] = 'Your administrator has enabled virus checking for file uploads but has misconfigured something.
Your file upload was NOT successful. Your administrator has been emailed to notify them so they can fix it.'; +$string['clamdeletedfile'] = 'The file has been deleted'; +$string['clamdeletedfilefailed'] ='The file could not be deleted'; +$string['clamemailsubject'] = '$a :: Clam AV notification'; +$string['clamfailed'] = 'Clam AV has failed to run. The return error message was $a. Here is the output from Clam:'; +$string['clamlost'] = 'Moodle is configured to run clam on file upload, but the path supplied to Clam AV, $a, is invalid.'; +$string['clamlostandactinglikevirus'] = 'In addition, moodle is configured so that if clam fails to run, files are treated like viruses. This essentially means that no student can upload a file successfully until you fix this.'; +$string['clammovedfile'] = 'The file has been moved to your specified quarantine directory, the new location is $a'; +$string['clammovedfilebasic'] = 'The file has been moved to a quarantine directory.'; +$string['clamquarantinedirfailed'] = 'Could not move the file into your specified quarantine directory, $a. You need to fix this as files are being deleted if they\'re found to be infected.'; +$string['clamunknownerror'] = 'There was an unknown error with clam.'; $string['cleaningtempdata'] = 'Cleaning temp data'; $string['clicktochange'] = 'Click to change'; $string['closewindow'] = 'Close this window'; @@ -152,6 +163,9 @@ $string['configallowunenroll'] = 'If this is set \'Yes\', then students are allo $string['configallusersaresitestudents'] = 'For activities on the front page of the site, should ALL users be considered as students? If you answer \"Yes\", then any confirmed user account will be allowed to participate as a student in those activities. If you answer \"No\", then only users who are already a participant in at least one course will be able to take part in those front page activities. Only admins and specially assigned teachers can act as teachers for these front page activities.'; $string['configautologinguests'] = 'Should visitors be logged in as guests automatically when entering courses with guest access?'; $string['configcachetext'] = 'For larger sites or sites that use text filters, this setting can really speed things up. Copies of texts will be retained in their processed form for the time specified here. Setting this too small may actually slow things down slightly, but setting it too large may mean texts take too long to refresh (with new links, for example).'; +$string['configclamactlikevirus'] = 'Treat files like viruses'; +$string['configclamdonothing'] = 'Treat files as OK'; +$string['configclamfailureonupload'] = 'If you have configured clam to scan uploaded files, but it is configured incorrectly or fails to run for some unknown reason, how should it behave? If you choose \'Treat files like viruses\', they\'ll be moved into the quarantine area, or deleted. If you choose \'Treat files as OK\', the files will be moved to the desination directory like normal. Either way, admins will be alerted that clam has failed. If you choose \'Treat files like viruses\' and for some reason clam fails to run (usually because you have entered an invalid pathtoclam), ALL files that are uploaded will be moved to the given quarantine area, or deleted. Be careful with this setting.'; $string['configcountry'] = 'If you set a country here, then this country will be selected by default on new user accounts. To force users to choose a country, just leave this unset.'; $string['configdebug'] = 'If you turn this on, then PHP\'s error_reporting will be increased so that more warnings are printed. This is only useful for developers.'; $string['configdeleteunconfirmed'] = 'If you are using email authentication, this is the period within which a response will be accepted from users. After this period, old unconfirmed accounts are deleted.'; @@ -186,7 +200,10 @@ $string['confignoreplyaddress'] = 'Emails are sometimes sent out on behalf of a $string['confignotifyloginfailures'] = 'If login failures have been recorded, email notifications can be sent out. Who should see these notifications?'; $string['confignotifyloginthreshold'] = 'If notifications about failed logins are active, how many failed login attempts by one user or one IP address is it worth notifying about?'; $string['configopentogoogle'] = 'If you enable this setting, then Google will be allowed to enter your site as a Guest. In addition, people coming in to your site via a Google search will automatically be logged in as a Guest. Note that this only provides transparent access to courses that already allow guest access.'; -$string['configproxyhost'] = 'If this server needs to use a proxy computer (eg a firewall) to access the Internet, then provide the proxy hostname and port here. Otherwise leave it blank.'; +$string['configpathtoclam'] = 'Path to clam AV. Probably something like /usr/bin/clamscan or /usr/bin/clamdscan. You need this in order for clam AV to run.'; +$string['configproxyhost'] = 'If this server needs to use a proxy computer (eg a firewall) to access the Internet, then provide the proxy hostname and port here. Otherwise leave it blank.'; +$string['configquarantinedir'] = 'If you want clam AV to move infected files to a quarantine directory, enter it here. It must be writable by the webserver. If you leave this blank, or if you enter a directory that doesn\'t exit or isn\'t writable, infected files will be deleted. Do not include a trailing slash.'; +$string['configrunclamonupload'] = 'Run clam AV on file upload? You will need a correct path in pathtoclam for this to work. (Clam AV is a free virus scanner that you can get from http://www.clamav.net/)'; $string['configsecureforms'] = 'Moodle can use an additional level of security when accepting data from web forms. If this is enabled, then the browser\'s HTTP_REFERER variable is checked against the current form address. In a very few cases this can cause problems if the user is using a firewall (eg Zonealarm) configured to strip HTTP_REFERER from their web traffic. Symptoms are getting \'stuck\' on a form. If your users are having problems with the login page (for example) you might want to disable this setting, although it might leave your site more open to brute-force password attacks. If in doubt, leave this set to \'Yes\'.'; $string['configsessioncookie'] = 'This setting customises the name of the cookie used for Moodle sessions. This is optional, and only useful to avoid cookies being confused when there is more than one copy of Moodle running within the same web site.'; $string['configsessiontimeout'] = 'If people logged in to this site are idle for a long time (without loading pages) then they are automatically logged out (their session is ended). This variable specifies how long this time should be.'; @@ -996,12 +1013,20 @@ $string['updatinga'] = 'Updating: $a'; $string['updatingain'] = 'Updating $a->what in $a->in'; $string['upload'] = 'Upload'; $string['uploadafile'] = 'Upload a file'; +$string['uploadedfile'] = 'File uploaded successfully'; +$string['uploadfailednotrecovering'] = 'Your file upload has failed because there was a problem with one of the files, $a->name.
Here is a log of the problems:
$a->problem
Not recovering.'; +$string['uploadfilelog'] = 'Upload log for file $a'; $string['uploadedfileto'] = 'Uploaded $a->file to $a->directory'; +$string['uploadedfiletoobig'] = 'Sorry, but that file is too big (limit is $a bytes)'; $string['uploadformlimit'] = 'Uploaded file exceeded the maximum size limit set by the form'; +$string['uploadlabel'] = 'Title:'; $string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?'; $string['uploadnotallowed'] = 'Uploads are not allowed'; +$string['uploadoldfilesdeleted'] = 'The old file(s) in your upload area have been deleted'; $string['uploadpartialfile'] = 'File was only partially uploaded'; $string['uploadproblem'] = 'An unknown problem occurred while uploading the file \'$a\' (perhaps it was too large?)'; +$string['uploadrenamedchars'] = 'File was renamed from $a->oldname to $a->newname because of invalid characters.'; +$string['uploadrenamedcollision'] = 'File was renamed from $a->oldname to $a->newname because there was a filename conflict.'; $string['uploadserverlimit'] = 'Uploaded file exceeded the maximum size limit set by the server'; $string['uploadthisfile'] = 'Upload this file'; $string['uploadusers'] = 'Upload users'; @@ -1023,6 +1048,13 @@ $string['userzones'] = 'User zones'; $string['usingexistingcourse'] = 'Using existing course'; $string['version'] = 'Version'; $string['view'] = 'View'; +$string['virusfoundsubject'] = '$a: Virus found!'; +$string['virusfound'] = 'Attention administrator! Clam AV has found a virus in a file uploaded by $a->user for the course $a->course. Here is the output of clamscan:'; +$string['virusfounduser'] = 'The file you have uploaded, $a->filename, has been scanned by a virus checker and found to be infected! Your file upload was NOT successful.'; +$string['virusfoundlater'] = 'A file you uploaded on $a->date with the filename $a->filename for the course $a->course has since been found to contain a virus. Here is a summary of what has happened to your file:'."\n\n".'$a->action'."\n\n".'If this was submitted work, you may want to resubmit it so that your tutor can see it.'; +$string['virusfoundlateradmin'] = 'Attention administrator! A file that was uploaded on $a->date with the filename $a->filename for the course $a->course by the user $a->user has since been found to contain a virus. Here is a summary of what has happened to the file:'."\n\n".'$a->action'."\n\n".'The user has also been notified.'; +$string['virusfoundlateradminnolog'] = 'Attention administrator! A file that was uploaded with the filename $a->filename has since been found to contain a virus. Moodle was unable to resolve this file back to the user that originally uploaded it.'."\n\n".'Here is a summary of what has happened to the file:'."\n\n".'$a->action'; +$string['virusplaceholder'] = 'This file that has been uploaded was found to contain a virus and has been moved or delted and the user notified.'; $string['webpage'] = 'Web page'; $string['week'] = 'Week'; $string['weekhide'] = 'Hide this week from $a'; diff --git a/lib/uploadlib.php b/lib/uploadlib.php new file mode 100644 index 0000000000..676f854632 --- /dev/null +++ b/lib/uploadlib.php @@ -0,0 +1,589 @@ +maxbytes are used to get the maxbytes to use (lowest) from get_max_upload_file_size(). + */ + function upload_manager($inputname='',$deleteothers=false,$handlecollisions=false,$course=null,$recoverifmultiple=false,$modbytes=0) { + + global $CFG; + + $this->config->deleteothers = $deleteothers; + $this->config->handlecollisions = $handlecollisions; + $this->config->recoverifmultiple = $recoverifmultiple; + $this->config->maxbytes = get_max_upload_file_size($CFG->maxbytes,$course->maxbytes,$modbytes); + $this->files = array(); + $this->status = false; + $this->course = $course; + $this->inputname = $inputname; + } + + /** + * Gets all entries out of $_FILES and stores them locally in $files + * Checks each one against get_max_upload_file_size and calls cleanfilename and scans them for viruses etc. + */ + function preprocess_files() { + global $CFG; + foreach ($_FILES as $name => $file) { + $this->status = true; // only set it to true here so that we can check if this function has been called. + if (empty($this->inputname) || $name == $this->inputname) { // if we have input name, only process if it matches. + $file['originalname'] = $file['name']; // do this first for the log. + $this->files[$name] = $file; // put it in first so we can get uploadlog out in print_upload_log. + $this->status = $this->validate_file($this->files[$name],empty($this->inputname)); // default to only allowing empty on multiple uploads. + if (!$this->status && $this->files[$name]['error'] = 0 || $this->files[$name]['error'] == 4 && empty($this->inputname)) { + // this shouldn't cause everything to stop.. modules should be responsible for knowing which if any are compulsory. + continue; + } + if ($this->status && $CFG->runclamonupload) { + $this->status = clam_scan_file($this->files[$name],$this->course); + } + if (!$this->status) { + if (!$this->config->recoverifmultiple && count($this->files) > 1) { + $a->name = $this->files[$name]['originalname']; + $a->problem = $this->files[$name]['uploadlog']; + notify(get_string('uploadfailednotrecovering','moodle',$a)); + $this->status = false; + return false; + } + else if (count($this->files) == 1) { + notify($this->files[$name]['uploadlog']); + $this->status = false; + return false; + } + } + else { + $newname = clean_filename($this->files[$name]['name']); + if ($newname != $this->files[$name]['name']) { + $a->oldname = $this->files[$name]['name']; + $a->newname = $newname; + $this->files[$name]['uploadlog'] .= get_string('uploadrenamedchars','moodle',$a); + } + $this->files[$name]['name'] = $newname; + $this->files[$name]['clear'] = true; // ok to save. + } + } + } + $this->status = true; + return true; // if we've got this far it means that we're recovering so we want status to be ok. + } + + /** + * Validates a single file entry from _FILES + * @param $file - the entry from _FILES to validate + * @param $allowempty - this is to allow module owners to control which files are compulsory if this function is being called straight from the module. + * @return true if ok. + */ + function validate_file(&$file,$allowempty=true) { + if (empty($file)) { + return $allowempty; // this shouldn't cause everything to stop.. modules should be responsible for knowing which if any are compulsory. + } + if (!is_uploaded_file($file['tmp_name']) || $file['size'] == 0) { + $file['uploadlog'] .= "\n".$this->get_file_upload_error($file); + if ($file['error'] == 0 || $file['error'] == 4) { + return $allowempty; + } + return false; + } + if ($file['size'] > $this->config->maxbytes) { + $file['uploadlog'] .= "\n".get_string("uploadedfiletoobig", "moodle", $this->config->maxbytes); + return false; + } + return true; + } + + /** + * Moves all the files to the destination directory. + * @param $destination - the destination directory. + * @return status; + */ + function save_files($destination) { + global $CFG,$USER; + + if (!$this->status) { // preprocess_files hasn't been run + $this->preprocess_files(); + } + if ($this->status) { + if (!(strpos($destination,$CFG->dataroot) === false)) { + // take it out for giving to make_upload_directory + $destination = substr($destination,strlen($CFG->dataroot)+1); + } + + if ($destination{strlen($destination)-1} == "/") { // strip off a trailing / if we have one + $destination = substr($destination,0,-1); + } + + if (!make_upload_directory($destination,true)) { //TODO maybe put this function here instead of moodlelib.php now. + $this->status = false; + return false; + } + + $destination = $CFG->dataroot.'/'.$destination; // now add it back in so we have a full path + + $exceptions = array(); //need this later if we're deleting other files. + + foreach (array_keys($this->files) as $i) { + + if (!$this->files[$i]['clear']) { + // not ok to save + continue; + } + + if ($this->config->handlecollisions) { + $this->handle_filename_collision($destination,$this->files[$i]); + } + if (move_uploaded_file($this->files[$i]['tmp_name'], $destination.'/'.$this->files[$i]['name'])) { + chmod($destination.'/'.$this->files[$i]['name'], $CFG->directorypermissions); + $this->files[$i]['fullpath'] = $destination.'/'.$this->files[$i]['name']; + $this->files[$i]['uploadlog'] .= "\n".get_string('uploadedfile'); + $this->files[$i]['saved'] = true; + $exceptions[] = $this->files[$i]['name']; + // now add it to the log (this is important so we know who to notify if a virus is found later on) + clam_log_upload($this->files[$i]['fullpath'],$this->course); + $savedsomething=true; + } + } + if ($savedsomething && $this->config->deleteothers) { + $this->delete_other_files($destination,$exceptions); + } + } + if (!$savedsomething) { + $this->status = false; + return false; + } + return $this->status; + } + + /** + * Wrapper function that calls preprocess_files and viruscheck_files and then save_files + * Modules that require the insert id in the filepath should not use this and call these functions seperately in the required order. + * @parameter $destination - where to save the uploaded files to. + */ + function process_file_uploads($destination) { + if ($this->preprocess_files()) { + return $this->save_files($destination); + } + return false; + } + + /** + * Deletes all the files in a given directory except for the files in $exceptions (full paths) + * @param $destination - the directory to clean up. + * @param $exceptions - array of full paths of files to KEEP. + */ + function delete_other_files($destination,$exceptions=null) { + if ($filestodel = get_directory_list($destination)) { + foreach ($filestodel as $file) { + if (!is_array($exceptions) || !in_array($file,$exceptions)) { + unlink("$destination/$file"); + $deletedsomething = true; + } + } + } + if ($deletedsomething) { + notify(get_string('uploadoldfilesdeleted')); + } + } + + /** + * Handles filename collisions - if the desired filename exists it will rename it according to the pattern in $format + * @param $destination - destination directory (to check existing files against) + * @param $file - the current file from $files we're processing. + * @param $format - the printf style format to rename the file to (defaults to filename_number.extn) + * @return new filename. + */ + function handle_filename_collision($destination,&$file,$format='%s_%d.%s') { + $bits = explode('.',$file['name']); + // check for collisions and append a nice numberydoo. + if (file_exists($destination.'/'.$file['name'])) { + $a->oldname = $file['name']; + for ($i = 1; true; $i++) { + $try = sprintf($format,$bits[0],$i,$bits[1]); + if ($this->check_before_renaming($destination,$try,$file)) { + $file['name'] = $try; + break; + } + } + $a->newname = $file['name']; + $file['uploadlog'] .= "\n".get_string('uploadrenamedcollision','moodle',$a); + } + } + + /** + * This function checks a potential filename against what's on the filesystem already and what's been saved already. + */ + function check_before_renaming($destination,$nametocheck,$file) { + if (!file_exists($destination.'/'.$nametocheck)) { + return true; + } + if ($this->config->deleteothers) { + foreach ($this->files as $tocheck) { + // if we're deleting files anyway, it's not THIS file and we care about it and it has the same name and has already been saved.. + if ($file['tmp_name'] != $tocheck['tmp_name'] && $tocheck['clear'] && $nametocheck == $tocheck['name'] && $tocheck['saved']) { + $collision = true; + } + } + if (!$collision) { + return true; + } + } + return false; + } + + + function get_file_upload_error(&$file) { + + switch ($file['error']) { + case 0: // UPLOAD_ERR_OK + if ($file['size'] > 0) { + $errmessage = get_string('uploadproblem', $file['name']); + } else { + $errmessage = get_string('uploadnofilefound'); /// probably a dud file name + } + break; + + case 1: // UPLOAD_ERR_INI_SIZE + $errmessage = get_string('uploadserverlimit'); + break; + + case 2: // UPLOAD_ERR_FORM_SIZE + $errmessage = get_string('uploadformlimit'); + break; + + case 3: // UPLOAD_ERR_PARTIAL + $errmessage = get_string('uploadpartialfile'); + break; + + case 4: // UPLOAD_ERR_NO_FILE + $errmessage = get_string('uploadnofilefound'); + break; + + default: + $errmessage = get_string('uploadproblem', $file['name']); + } + return $errmessage; + } + + /** + * prints a log of everything that happened (of interest) to each file in _FILES + * @param $return - optional, defaults to false (log is echoed) + */ + function print_upload_log($return=false) { + foreach (array_keys($this->files) as $i => $key) { + $str .= ''.get_string('uploadfilelog','moodle',$i+1).' ' + .((!empty($this->files[$key]['originalname'])) ? '('.$this->files[$key]['originalname'].')' : '') + .' :'.nl2br($this->files[$key]['uploadlog']).'
'; + } + if ($return) { + return $str; + } + echo $str; + } + + /** + * If we're only handling one file (if inputname was given in the constructor) this will return the (possibly changed) filename of the file. + */ + function get_new_filename() { + if (!empty($this->inputname) && count($this->files) == 1) { + return $this->files[$this->inputname]['name']; + } + return false; + } + + /** + * If we're only handling one file (if inputname was given in the constructor) this will return the ORIGINAL filename of the file. + */ + function get_original_filename() { + if (!empty($this->inputname) && count($this->files) == 1) { + return $this->files[$this->inputname]['originalname']; + } + return false; + } +} + +/************************************************************************************** +THESE FUNCTIONS ARE OUTSIDE THE CLASS BECAUSE THEY NEED TO BE CALLED FROM OTHER PLACES. +FOR EXAMPLE CLAM_HANDLE_INFECTED_FILE AND CLAM_REPLACE_INFECTED_FILE USED FROM CRON +UPLOAD_PRINT_FORM_FRAGMENT DOESN'T REALLY BELONG IN THE CLASS BUT CERTAINLY IN THIS FILE +***************************************************************************************/ + + +/** + * This function prints out a number of upload form elements + * @param $numfiles - the number of elements required (optional, defaults to 1) + * @param $names - array of element names to use (optional, defaults to FILE_n) + * @param $descriptions - array of strings to be printed out before each file bit. + * @param $uselabels - whether to output text fields for file descriptions or not (optional, defaults to false) + * @param $labelnames - array of element names to use for labels (optional, defaults to LABEL_n) + * @param $coursebytes + * @param $modbytes - these last two are used to calculate upload max size ( using get_max_upload_file_size) + * @param $return - whether to return the string (defaults to false - string is echoed) + */ +function upload_print_form_fragment($numfiles=1,$names=null,$descriptions=null,$uselabels=false,$labelnames=null,$coursebytes=0,$modbytes=0,$return=false) { + global $CFG; + $maxbytes = get_max_upload_file_size($CFG->maxbytes,$coursebytes,$modbytes); + $str = ''."\n"; + for ($i = 0; $i < $numfiles; $i++) { + if (is_array($descriptions) && !empty($descriptions[$i])) { + $str .= ''.$descriptions[$i].'
'; + } + $str .= '
'."\n"; + if ($uselabels) { + $str .= get_string('uploadlabel').'

'."\n"; + } + } + if ($return) { + return $str; + } + else { + echo $str; + } +} + + +/** + * Deals with an infected file - either moves it to a quarantinedir + * (specified in CFG->quarantinedir) or deletes it. + * If moving it fails, it deletes it. + * @param file full path to the file + * @param userid - if not used, defaults to $USER->id (there in case called from cron) + * @param basiconly - admin level reporting or user level reporting. + * @return a string of what it did. + */ +function clam_handle_infected_file($file,$userid=0,$basiconly=false) { + + global $CFG,$USER; + if ($USER && !$userid) { + $userid = $USER->id; + } + $delete = true; + if (file_exists($CFG->quarantinedir) && is_dir($CFG->quarantinedir) && is_writable($CFG->quarantinedir)) { + $now = date('YmdHis'); + if (rename($file,$CFG->quarantinedir.'/'.$now.'-user-'.$userid.'-infected')) { + $delete = false; + if ($basiconly) { + $notice .= "\n".get_string('clammovedfilebasic'); + } + else { + $notice .= "\n".get_string('clammovedfile','moodle',$CFG->quarantinedir.'/'.$now.'-user-'.$userid.'-infected'); + } + } + else { + if ($basiconly) { + $notice .= "\n".get_string('clamdeletedfile'); + } + else { + $notice .= "\n".get_string('clamquarantinedirfailed','moodle',$CFG->quarantinedir); + } + } + } + else { + if ($basiconly) { + $notice .= "\n".get_string('clamdeletedfile'); + } + else { + $notice .= "\n".get_string('clamquarantinedirfailed','moodle',$CFG->quarantinedir); + } + } + if ($delete) { + if (unlink($file)) { + $notice .= "\n".get_string('clamdeletedfile'); + } + else { + if ($basiconly) { + // still tell the user the file has been deleted. this is only for admins. + $notice .= "\n".get_string('clamdeletedfile'); + } + else { + $notice .= "\n".get_string('clamdeletedfilefailed'); + } + } + } + return $notice; +} + +/** + * Replaces the given file with a string to notify that the original file had a virus. + * This is to avoid missing files but could result in the wrong content-type. + * @param file - full path to the file. + */ +function clam_replace_infected_file($file) { + $newcontents = get_string('virusplaceholder'); + if (!$f = fopen($file,'w')) { + return false; + } + if (!fwrite($f,$newcontents)) { + return false; + } + return true; +} + + +/** + * If $CFG->runclamonupload is set, we scan a given file. (called from preprocess_files) + * This function will add on a uploadlog index in $file. + * @param $file - the file to scan from $files. or an absolute path to a file. + * @return 1 if good, 0 if something goes wrong (opposite from actual error code from clam) + */ +function clam_scan_file(&$file,$course) { + global $CFG,$USER; + + if (is_array($file) && is_uploaded_file($file['tmp_name'])) { // it's from $_FILES + $appendlog = true; + $fullpath = $file['tmp_name']; + } + else if (file_exists($file)) { // it's a path to somewhere on the filesystem! + $fullpath = $file; + } + else { + return false; // erm, what is this supposed to be then, huh? + } + + if (!$CFG->pathtoclam || !file_exists($CFG->pathtoclam) || !is_executable($CFG->pathtoclam)) { + $newreturn = 1; + $notice = get_string('clamlost','moodle',$CFG->pathtoclam); + if ($CFG->clamfailureonupload == 'actlikevirus') { + $notice .= "\n".get_string('clamlostandactinglikevirus'); + $notice .= "\n".clam_handle_infected_file($fullpath); + $newreturn = false; + } + clam_mail_admins($notice); + return $newreturn; // return 1 if we're allowing clam failures + } + + $cmd = $CFG->pathtoclam.' '.$fullpath." 2>&1"; + + // before we do anything we need to change perms so that clamscan can read the file (clamdscan won't work otherwise) + chmod($fullpath,0644); + + exec($cmd,$output,$return); + + + switch ($return) { + case 0: // glee! we're ok. + return 1; // translate clam return code into reasonable return code consistent with everything else. + case 1: // bad wicked evil, we have a virus. + if (!empty($course)) { + $info->course = $course->fullname; + } + else { + $info->course = 'No course'; + } + $info->user = $USER->firstname.' '.$USER->lastname; + $notice = get_string('virusfound','moodle',$info); + $notice .= "\n\n".implode("\n",$output); + $notice .= "\n\n".clam_handle_infected_file($fullpath); + clam_mail_admins($notice); + if ($appendlog) { + $info->filename = $file['originalname']; + $file['uploadlog'] .= "\n".get_string('virusfounduser','moodle',$info); + $file['virus'] = 1; + } + return false; // in this case, 0 means bad. + default: + // error - clam failed to run or something went wrong + $notice .= get_string('clamfailed','moodle',get_clam_error_code($return)); + $notice .= "\n\n".implode("\n",$output); + $newreturn = true; + if ($CFG->clamfailureonupload == 'actlikevirus') { + $notice .= "\n".clam_handle_infected_file($fullpath); + $newreturn = false; + } + clam_mail_admins($notice); + if ($appendlog) { + $file['uploadlog'] .= "\n".get_string('clambroken'); + $file['clam'] = 1; + } + return $newreturn; // return 1 if we're allowing failures. + } +} + +/** + * emails admins about a clam outcome + * @param notice - the body of the email. + */ +function clam_mail_admins($notice) { + + $site = get_site(); + + $subject = get_string('clamemailsubject','moodle',$site->fullname); + $admins = get_admins(); + foreach ($admins as $admin) { + email_to_user($admin,get_admin(),$subject,$notice); + } +} + + +function get_clam_error_code($returncode) { + $returncodes = array(); + $returncodes[0] = 'No virus found.'; + $returncodes[1] = 'Virus(es) found.'; + $returncodes[2] = ' An error occured'; // specific to clamdscan + // all after here are specific to clamscan + $returncodes[40] = 'Unknown option passed.'; + $returncodes[50] = 'Database initialization error.'; + $returncodes[52] = 'Not supported file type.'; + $returncodes[53] = 'Can\'t open directory.'; + $returncodes[54] = 'Can\'t open file. (ofm)'; + $returncodes[55] = 'Error reading file. (ofm)'; + $returncodes[56] = 'Can\'t stat input file / directory.'; + $returncodes[57] = 'Can\'t get absolute path name of current working directory.'; + $returncodes[58] = 'I/O error, please check your filesystem.'; + $returncodes[59] = 'Can\'t get information about current user from /etc/passwd.'; + $returncodes[60] = 'Can\'t get information about user \'clamav\' (default name) from /etc/passwd.'; + $returncodes[61] = 'Can\'t fork.'; + $returncodes[63] = 'Can\'t create temporary files/directories (check permissions).'; + $returncodes[64] = 'Can\'t write to temporary directory (please specify another one).'; + $returncodes[70] = 'Can\'t allocate and clear memory (calloc).'; + $returncodes[71] = 'Can\'t allocate memory (malloc).'; + if ($returncodes[$returncode]) + return $returncodes[$returncode]; + return get_string('clamunknownerror'); + +} + +/** + * adds a file upload to the log table so that clam can resolve the filename to the user later if necessary + */ +function clam_log_upload($newfilepath,$course=null) { + global $CFG,$USER; + // get rid of any double // that might have appeared + $newfilepath = preg_replace('/\/\//','/',$newfilepath); + if (strpos($newfilepath,$CFG->dataroot) === false) { + $newfilepath = $CFG->dataroot.'/'.$newfilepath; + } + $CFG->debug=10; + $courseid = 0; + if ($course) { + $courseid = $course->id; + } + add_to_log($courseid,"upload","upload","",$newfilepath); +} + +/** + * some of the modules allow moving attachments (glossary), in which case we need to hunt down an original log and change the path. + */ +function clam_change_log($oldpath,$newpath) { + global $CFG; + $sql = "UPDATE {$CFG->prefix}log SET info = '$newpath' WHERE module = 'upload' AND info = '$oldpath'"; + execute_sql($sql); +} +?> \ No newline at end of file diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 1cee5d6905..992919ca0d 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -661,6 +661,7 @@ function assignment_print_user_files($assignment, $user) { } } +// this function should be defunct now that we're using uploadlib.php function assignment_delete_user_files($assignment, $user, $exception) { // Deletes all the user files in the assignment area for a user // EXCEPT for any file named $exception @@ -680,11 +681,13 @@ function assignment_delete_user_files($assignment, $user, $exception) { function assignment_print_upload_form($assignment) { // Arguments are objects + global $CFG; + echo "

"; echo "
id\">"; - echo " maxbytes\" />"; echo " id\" />"; - echo " "; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + upload_print_form_fragment(1,array('newfile'),false,null,0,$assignment->maxbytes,false); echo " "; echo "
"; echo "
"; diff --git a/mod/assignment/upload.php b/mod/assignment/upload.php index 240f666ddb..98783ca4f0 100644 --- a/mod/assignment/upload.php +++ b/mod/assignment/upload.php @@ -2,15 +2,9 @@ require_once("../../config.php"); require_once("lib.php"); - require_variable($id); // Assignment ID - if (!empty($_FILES['newfile'])) { - $newfile = $_FILES['newfile']; - } - - if (! $assignment = get_record("assignment", "id", $id)) { error("Not a valid assignment ID"); } @@ -25,8 +19,6 @@ require_login($course->id); - add_to_log($course->id, "assignment", "upload", "view.php?a=$assignment->id", "$assignment->id", $cm->id); - $strassignments = get_string("modulenameplural", "assignment"); $strassignment = get_string("modulename", "assignment"); $strupload = get_string("upload"); @@ -42,55 +34,38 @@ } } - if (! $dir = assignment_file_area($assignment, $USER)) { - error("Sorry, an error in the system prevents you from uploading files: contact your teacher or system administrator"); - } - - if (empty($newfile)) { - notify(get_string("uploadfiletoobig", "assignment", get_max_upload_file_size($CFG->maxbytes, $course->maxbytes, $assignment->maxbytes)) ); - - } else if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) { - $newfile_name = clean_filename($newfile['name']); - if ($newfile_name) { - if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) { - chmod("$dir/$newfile_name", $CFG->directorypermissions); - assignment_delete_user_files($assignment, $USER, $newfile_name); - if ($submission) { - $submission->timemodified = time(); - $submission->numfiles = 1; - $submission->comment = addslashes($submission->comment); - if (update_record("assignment_submissions", $submission)) { - print_heading(get_string("uploadsuccess", "assignment", $newfile_name) ); - } else { - notify(get_string("uploadfailnoupdate", "assignment")); - } - } else { - $newsubmission->assignment = $assignment->id; - $newsubmission->userid = $USER->id; - $newsubmission->timecreated = time(); - $newsubmission->timemodified = time(); - $newsubmission->numfiles = 1; - if (insert_record("assignment_submissions", $newsubmission)) { - print_heading(get_string("uploadsuccess", "assignment", $newfile_name) ); - } else { - notify(get_string("uploadnotregistered", "assignment", $newfile_name) ); - } - } + $dir = assignment_file_area_name($assignment,$USER); + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newfile',true,false,$course,false,$assignment->maxbytes); + $newfile_name = $um->get_new_filename(); + if ($um->process_file_uploads($dir)) { + if ($submission) { + $submission->timemodified = time(); + $submission->numfiles = 1; + $submission->comment = addslashes($submission->comment); + if (update_record("assignment_submissions", $submission)) { + print_heading(get_string('uploadedfile')); } else { - notify(get_string("uploaderror", "assignment") ); + notify(get_string("uploadfailnoupdate", "assignment")); } } else { - notify(get_string("uploadbadname", "assignment") ); - } - } else { - - print_file_upload_error(); - + $newsubmission->assignment = $assignment->id; + $newsubmission->userid = $USER->id; + $newsubmission->timecreated = time(); + $newsubmission->timemodified = time(); + $newsubmission->numfiles = 1; + if (insert_record("assignment_submissions", $newsubmission)) { + add_to_log($course->id, "assignment", "upload", "view.php?a=$assignment->id", "$assignment->id", $cm->id); + print_heading(get_string('uploadedfile')); + } else { + notify(get_string("uploadnotregistered", "assignment", $newfile_name) ); + } + } } - + // upload class will take care of printing out errors. + print_continue("view.php?a=$assignment->id"); print_footer($course); - ?> diff --git a/mod/exercise/locallib.php b/mod/exercise/locallib.php index 05a2ff1bd6..9fbde29322 100644 --- a/mod/exercise/locallib.php +++ b/mod/exercise/locallib.php @@ -2856,6 +2856,8 @@ function exercise_print_time_to_deadline($time) { /////////////////////////////////////////////////////////////////////////////////////////////// function exercise_print_upload_form($exercise) { + global $CFG; + if (! $course = get_record("course", "id", $exercise->course)) { error("Course is misconfigured"); } @@ -2865,10 +2867,9 @@ function exercise_print_upload_form($exercise) { echo "
"; echo "
"; - echo " maxbytes\" />"; echo " id\" />"; - echo "".get_string("title", "exercise").":

\n"; - echo " "; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + upload_print_form_fragment(1,array('newfile'),null,true,array('title'),$course->maxbytes,$exercise->maxbytes,false); echo " "; echo " (".get_string("maximumupload").": ".display_size($exercise->maxbytes).")\n"; echo "
"; diff --git a/mod/exercise/upload.php b/mod/exercise/upload.php index b881c4aea8..ef2efa9b27 100644 --- a/mod/exercise/upload.php +++ b/mod/exercise/upload.php @@ -7,8 +7,6 @@ require_variable($id); // course module ID $timenow = time(); - $newfile = $HTTP_POST_FILES["newfile"]; - // get some esential stuff... if (! $cm = get_record("course_modules", "id", $id)) { error("Course Module ID was incorrect"); @@ -54,55 +52,38 @@ notify(get_string("notitlegiven", "exercise") ); } else { - if (is_uploaded_file($newfile['tmp_name']) and $newfile['size'] > 0) { - if ($newfile['size'] > $exercise->maxbytes) { - notify(get_string("uploadfiletoobig", "assignment", $exercise->maxbytes)); - } + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('newfile',false,false,$course,false,$exercise->maxbytes); + if ($um->preprocess_files()) { + $newsubmission->exerciseid = $exercise->id; + if (isteacher($course->id)) { + // it's an exercise submission, flag it as such + $newsubmission->userid = 0; + $newsubmission->isexercise = 1; // it's a description of an exercise + } else { - $newfile_name = clean_filename($newfile['name']); - if ($newfile_name) { - $newsubmission->exerciseid = $exercise->id; - if (isteacher($course->id)) { - // it's an exercise submission, flag it as such - $newsubmission->userid = 0; - $newsubmission->isexercise = 1; // it's a description of an exercise - } - else { - $newsubmission->userid = $USER->id; - } - $newsubmission->title = $title; - $newsubmission->timecreated = $timenow; - if ($timenow > $exercise->deadline) { - $newsubmission->late = 1; - } - if (!$newsubmission->id = insert_record("exercise_submissions", $newsubmission)) { - error("exercise upload: Failure to create new submission record!"); - } - if (! $dir = exercise_file_area($exercise, $newsubmission)) { - error("Sorry, an error in the system prevents you from uploading files: contact your teacher or system administrator"); - } - if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) { - add_to_log($course->id, "exercise", "submit", "view.php?id=$cm->id", "$exercise->id"); - print_heading(get_string("uploadsuccess", "assignment", $newfile_name) ); - } - else { - notify(get_string("uploaderror", "assignment") ); - } - // clear resubmit flags - if (!set_field("exercise_submissions", "resubmit", 0, "exerciseid", $exercise->id, "userid", $USER->id)) { - error("Exercise Upload: unable to reset resubmit flag"); - } - } - else { - notify(get_string("uploadbadname", "assignment") ); - } + $newsubmission->userid = $USER->id; } - } - elseif (!is_uploaded_file($newfile['tmp_name']) and !$newfile['size'] > 0 and $newfile['name']) { - notify(get_string("uploadfiletoobig", "assignment", $exercise->maxbytes)); - } else { - notify(get_string("uploadnofilefound", "assignment")); - } + $newsubmission->title = $title; + $newsubmission->timecreated = $timenow; + if ($timenow > $exercise->deadline) { + $newsubmission->late = 1; + } + if (!$newsubmission->id = insert_record("exercise_submissions", $newsubmission)) { + error("exercise upload: Failure to create new submission record!"); + } + $dir = exercise_file_area_name($exercise, $newsubmission); + if ($um->save_files($dir)) { + add_to_log($course->id, "exercise", "submit", "view.php?id=$cm->id", "$exercise->id"); + print_heading(get_string("uploadsuccess", "assignment", $um->get_new_filename()) ); + } + // upload manager will print errors. + // clear resubmit flags + if (!set_field("exercise_submissions", "resubmit", 0, "exerciseid", $exercise->id, "userid", $USER->id)) { + error("Exercise Upload: unable to reset resubmit flag"); + } + } + // upload manager will print errors. } print_continue("view.php?id=$cm->id"); diff --git a/mod/forum/lib.php b/mod/forum/lib.php index d4884f5790..4da192053a 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1907,6 +1907,8 @@ function forum_move_attachments($discussion, $forumid) { global $CFG; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $return = true; if ($posts = get_records_select("forum_posts", "discussion = '$discussion->id' AND attachment <> ''")) { @@ -1918,9 +1920,13 @@ function forum_move_attachments($discussion, $forumid) { $newpost = $oldpost; $newpost->forum = $forumid; $newpostdir = forum_file_area($newpost); + $files = get_directory_list($oldpostdir); // get it before we rename it. if (! @rename($oldpostdir, $newpostdir)) { $return = false; } + foreach ($files as $file) { + clam_change_log($oldpostdir.'/'.$file,$newpostdir.'/'.$file); + } } } } @@ -1979,17 +1985,13 @@ function forum_print_attachments($post, $return=NULL) { return $imagereturn; } -function forum_add_attachment($post, $newfile) { +function forum_add_attachment($post, $inputname) { // $post is a full post record, including course and forum // $newfile is a full upload array from $_FILES // If successful, this function returns the name of the file global $CFG; - if (empty($newfile['name'])) { - return ""; - } - if (!$forum = get_record("forum", "id", $post->forum)) { return ""; } @@ -1998,35 +2000,13 @@ function forum_add_attachment($post, $newfile) { return ""; } - $maxbytes = get_max_upload_file_size($CFG->maxbytes, $course->maxbytes, $forum->maxbytes); - - $newfile_name = clean_filename($newfile['name']); - - if (valid_uploaded_file($newfile)) { - if ($maxbytes and $newfile['size'] > $maxbytes) { - return ""; - } - if (! $newfile_name) { - notify("This file had a wierd filename and couldn't be uploaded"); - - } else if (! $dir = forum_file_area($post)) { - notify("Attachment could not be stored"); - $newfile_name = ""; - - } else { - if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) { - chmod("$dir/$newfile_name", $CFG->directorypermissions); - forum_delete_old_attachments($post, $newfile_name); - } else { - notify("An error happened while saving the file on the server"); - $newfile_name = ""; - } - } - } else { - $newfile_name = ""; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager($inputname,true,false,$course,false,$forum->maxbytes); + $dir = forum_file_area_name($post); + if ($um->process_file_uploads($dir)) { + return $um->get_new_filename(); } - - return $newfile_name; + // upload manager will print any errors. } function forum_add_new_post($post) { @@ -2034,14 +2014,13 @@ function forum_add_new_post($post) { $post->created = $post->modified = time(); $post->mailed = "0"; - $newfile = $post->attachment; $post->attachment = ""; if (! $post->id = insert_record("forum_posts", $post)) { return false; } - if ($post->attachment = forum_add_attachment($post, $newfile)) { + if ($post->attachment = forum_add_attachment($post, 'attachment')) { set_field("forum_posts", "attachment", $post->attachment, "id", $post->id); } @@ -2060,7 +2039,7 @@ function forum_update_post($post) { set_field("forum_discussions", "name", $post->subject, "id", $post->discussion); } - if ($newfilename = forum_add_attachment($post, $post->attachment)) { + if ($newfilename = forum_add_attachment($post, 'attachment')) { $post->attachment = $newfilename; } else { unset($post->attachment); @@ -2101,7 +2080,7 @@ function forum_add_discussion($discussion) { return 0; } - if ($post->attachment = forum_add_attachment($post, $discussion->attachment)) { + if ($post->attachment = forum_add_attachment($post, 'attachment')) { set_field("forum_posts", "attachment", $post->attachment, "id", $post->id); //ignore errors } diff --git a/mod/forum/post.html b/mod/forum/post.html index 6a3bdd8d4b..52b6778d27 100644 --- a/mod/forum/post.html +++ b/mod/forum/post.html @@ -89,9 +89,9 @@

:
(

maxbytes, $course->maxbytes, $forum->maxbytes); ?> - - dirroot.'/lib/uploadlib.php'); + upload_print_form_fragment(1,array('attachment'),null,false,null,$course->maxbytes,$forum->maxbytes,false); helpbutton("attachment", get_string("attachment", "forum"), "forum"); print_string("maxsize", "", display_size($maxbytes)); ?> diff --git a/mod/glossary/edit.html b/mod/glossary/edit.html index b45930940b..030f1429e3 100644 --- a/mod/glossary/edit.html +++ b/mod/glossary/edit.html @@ -158,9 +158,9 @@ if (isset($errors)) {

:
(

- - dirroot.'/lib/uploadlib.php'); + upload_print_form_fragment(1,array('attachment'),null,false,null,$course->maxbytes,0,false); helpbutton("attachment", get_string("attachment", "glossary"), "glossary"); print_string("maxsize", "", display_size(get_max_upload_file_size($CFG->maxbytes, $course->maxbytes))); ?> @@ -170,8 +170,8 @@ if (isset($errors)) {

id)) { - echo "id\" />"; - } + echo "id\" />"; + } ?> diff --git a/mod/glossary/edit.php b/mod/glossary/edit.php index ece35a86af..91219b67a8 100644 --- a/mod/glossary/edit.php +++ b/mod/glossary/edit.php @@ -89,7 +89,13 @@ if ( $confirm ) { print_footer($course); die; } - + print_header_simple(strip_tags("$glossary->name"), "", + "id\">$strglossaries -> + id\">$glossary->name -> $stredit", "form.text", + "", true, "", navmenu($course, $cm)); + + print_heading($glossary->name); + if ($e) { //We are updating an entry, so we compare current session user with //existing entry user to avoid some potential problems if secureforms=off @@ -123,7 +129,7 @@ if ( $confirm ) { if ( $permissiongranted ) { $newentry->attachment = $_FILES["attachment"]; - if ($newfilename = glossary_add_attachment($newentry, $newentry->attachment)) { + if ($newfilename = glossary_add_attachment($newentry, 'attachment')) { $newentry->attachment = $newfilename; } else { unset($newentry->attachment); @@ -133,12 +139,13 @@ if ( $confirm ) { error("Could not update your glossary"); } else { add_to_log($course->id, "glossary", "update entry", "view.php?id=$cm->id&mode=entry&hook=$newentry->id", $newentry->id,$cm->id); + notify(get_string('entryupdated','glossary')); } } else { error("Could not update this glossary entry because this concept already exist."); } } else { - + $newentry->userid = $USER->id; $newentry->timecreated = $timenow; $newentry->sourceglossaryid = 0; @@ -156,13 +163,14 @@ if ( $confirm ) { } else { $e = $newentry->id; $newentry->attachment = $_FILES["attachment"]; - if ($newfilename = glossary_add_attachment($newentry, $newentry->attachment)) { + if ($newfilename = glossary_add_attachment($newentry, 'attachment')) { $newentry->attachment = $newfilename; } else { unset($newentry->attachment); } set_field("glossary_entries", "attachment", $newfilename, "id", $newentry->id); add_to_log($course->id, "glossary", "add entry", "view.php?id=$cm->id&mode=entry&hook=$newentry->id", $newentry->id,$cm->id); + notify(get_string('entrysaved','glossary')); } } else { error("Could not insert this glossary entry because this concept already exist."); @@ -196,8 +204,8 @@ if ( $confirm ) { } } } - - redirect("view.php?id=$cm->id&mode=entry&hook=$newentry->id"); + print_continue("view.php?id=$cm->id&mode=entry&hook=$newentry->id"); + print_footer(); die; } else { if ($e) { diff --git a/mod/glossary/import.html b/mod/glossary/import.html index 4b6e3a275b..d1b90e4086 100644 --- a/mod/glossary/import.html +++ b/mod/glossary/import.html @@ -3,9 +3,9 @@

:

- -
dirroot.'/lib/uploadlib.php'); + upload_print_form_fragment(1,array('file'),null,false,null,0,0); helpbutton("filetoimport", get_string("filetoimport", "glossary"), "glossary"); print_string("maxsize", "", display_size(get_max_upload_file_size())); ?> diff --git a/mod/glossary/import.php b/mod/glossary/import.php index 2e689877ad..32fa5ad454 100644 --- a/mod/glossary/import.php +++ b/mod/glossary/import.php @@ -75,6 +75,15 @@ $form = data_submitted(); $file = $_FILES["file"]; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager('file',false,false,$course,false,0); + + if (!$um->preprocess_files()) { + print_continue('import.php?id='.$id); + print_footer(); + die(); + } + if ($xml = glossary_read_imported_file($file['tmp_name']) ) { $importedentries = 0; diff --git a/mod/glossary/lib.php b/mod/glossary/lib.php index 1b89d373e8..030edac334 100644 --- a/mod/glossary/lib.php +++ b/mod/glossary/lib.php @@ -1010,6 +1010,8 @@ function glossary_move_attachments($entry, $glossaryid) { global $CFG; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $return = true; if ($entries = get_records_select("glossary_entries", "glossaryid = '$entry->id' AND attachment <> ''")) { @@ -1021,50 +1023,43 @@ function glossary_move_attachments($entry, $glossaryid) { $newentry = $oldentry; $newentry->glossaryid = $glossaryid; $newentrydir = "$CFG->dataroot/".glossary_file_area_name($newentry); + $files = get_directory_list($oldentrydir); // get it before we rename it. if (! @rename($oldentrydir, $newentrydir)) { $return = false; } + foreach ($files as $file) { + // this is not tested as I can't find anywhere that calls this function, grepping the source. + clam_change_log($oldentrydir.'/'.$file,$newentrydir.'/'.$file); + } } } } return $return; } -function glossary_add_attachment($entry, $newfile) { +function glossary_add_attachment($entry, $inputname) { // $entry is a full entry record, including course and glossary // $newfile is a full upload array from $_FILES // If successful, this function returns the name of the file global $CFG; - if (empty($newfile['name'])) { - return ""; + if (!$glossary = get_record("glossary","id",$entry->glossaryid)) { + return false; + } + + if (!$course = get_record("course","id",$glossary->course)) { + return false; } - $newfile_name = clean_filename($newfile['name']); - - if (valid_uploaded_file($newfile)) { - if (! $newfile_name) { - notify("This file had a wierd filename and couldn't be uploaded"); - - } else if (! $dir = glossary_file_area($entry)) { - notify("Attachment could not be stored"); - $newfile_name = ""; + require_once($CFG->dirroot.'/lib/uploadlib.php'); + $um = new upload_manager($inputname,true,false,$course,false,0); + $dir = glossary_file_area_name($entry); - } else { - if (move_uploaded_file($newfile['tmp_name'], "$dir/$newfile_name")) { - chmod("$dir/$newfile_name", $CFG->directorypermissions); - glossary_delete_old_attachments($entry, $newfile_name); - } else { - notify("An error happened while saving the file on the server"); - $newfile_name = ""; - } - } - } else { - $newfile_name = ""; + if ($um->process_file_uploads($dir)) { + return $um->get_new_filename(); } - - return $newfile_name; + // upload manager will take care of errors. } function glossary_print_attachments($entry, $return=NULL, $align="left") { diff --git a/mod/resource/coursefiles.php b/mod/resource/coursefiles.php index 3fe5d1aac1..e0a38e410c 100644 --- a/mod/resource/coursefiles.php +++ b/mod/resource/coursefiles.php @@ -112,32 +112,16 @@ case "upload": html_header($course, $wdir); - - if (!empty($_FILES['userfile'])) { - $userfile = $_FILES['userfile']; - } else { - $save = false; - } + require_once($CFG->dirroot.'/lib/uploadlib.php'); + if (!empty($save)) { - if (!is_uploaded_file($userfile['tmp_name']) or $userfile['size'] == 0) { - notify(get_string("uploadnofilefound")); - } else { - $userfile_name = clean_filename($userfile['name']); - if ($userfile_name) { - $newfile = "$basedir$wdir/$userfile_name"; - if (move_uploaded_file($userfile['tmp_name'], $newfile)) { - chmod($newfile, 0666); - $a = NULL; - $a->file = "$userfile_name (".$userfile['type'].")"; - $a->directory = $wdir; - print_string("uploadedfileto", "", $a); - } else { - notify(get_string("uploadproblem", "", $userfile_name)); - } - } + $um = new upload_manager('userfile',false,false,$course,false,0); + $dir = "$basedir$wdir"; + if ($um->process_file_uploads($dir)) { + notify(get_string('uploadedfile')); } + // um will take care of error reporting. displaydir($wdir); - } else { $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes); $filesize = display_size($upload_max_filesize); @@ -150,11 +134,10 @@ echo "

$struploadafile ($strmaxsize) --> $wdir"; echo "
"; echo "
"; - echo " "; + upload_print_form_fragment(1,array('userfile'),null,false,null,$course->maxbytes,0,false); echo " "; echo " "; echo " "; - echo " "; echo "
"; echo " "; echo ""; @@ -663,6 +646,7 @@ function print_cell($alignment="center", $text=" ") { } function displaydir ($wdir) { + // $wdir == / or /a or /a/b/c/d etc global $basedir; @@ -742,7 +726,6 @@ function displaydir ($wdir) { } } - if (!empty($filelist)) { asort($filelist); foreach ($filelist as $file) { diff --git a/mod/scorm/coursefiles.php b/mod/scorm/coursefiles.php index 0b402be330..ae42a919d5 100755 --- a/mod/scorm/coursefiles.php +++ b/mod/scorm/coursefiles.php @@ -112,32 +112,16 @@ case "upload": html_header($course, $wdir); - - if (!empty($_FILES['userfile'])) { - $userfile = $_FILES['userfile']; - } else { - $save = false; - } + require_once($CFG->dirroot.'/lib/uploadlib.php'); + if (!empty($save)) { - if (!is_uploaded_file($userfile['tmp_name']) or $userfile['size'] == 0) { - notify(get_string("uploadnofilefound")); - } else { - $userfile_name = clean_filename($userfile['name']); - if ($userfile_name) { - $newfile = "$basedir$wdir/$userfile_name"; - if (move_uploaded_file($userfile['tmp_name'], $newfile)) { - chmod($newfile, 0666); - $a = NULL; - $a->file = "$userfile_name (".$userfile['type'].")"; - $a->directory = $wdir; - print_string("uploadedfileto", "", $a); - } else { - notify(get_string("uploadproblem", "", $userfile_name)); - } - } + $um = new upload_manager('userfile',false,false,$course,false,0); + $dir = "$basedir$wdir"; + if ($um->process_file_uploads($dir)) { + notify(get_string('uploadedfile')); } + // um will take care of error reporting. displaydir($wdir); - } else { $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes); $filesize = display_size($upload_max_filesize); @@ -150,11 +134,10 @@ echo "

$struploadafile ($strmaxsize) --> $wdir"; echo "
"; echo "
"; - echo " "; echo " "; echo " "; echo " "; - echo " "; + upload_print_form_fragment(1,array('userfile'),null,false,null,$course->maxbytes,0,false); echo "
"; echo " "; echo "";