/[drupal]/contributions/modules/fbu/fbu.module
ViewVC logotype

Contents of /contributions/modules/fbu/fbu.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Sun Aug 28 10:05:44 2005 UTC (4 years, 3 months ago) by robertDouglass
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
File MIME type: text/x-php
Removing directory limitations that were in place for testing
1 <?php
2 // $Id:
3
4 function fbu_perm() {
5 return array ('administer file backup');
6 }
7
8 function fbu_help($section = '') {
9 switch ($section) {
10 case 'admin/modules/fbu':
11 case 'admin/modules#description':
12 $output = t('Receive filesystem backups by mail.');
13 break;
14 case 'admin/help#fbu':
15 $output .= t("
16 <p>The fbu module allows site administrators to receive backups of their server's file system by email.</p>");
17 break;
18 }
19 return $output;
20 }
21
22 function fbu_settings() {
23 if($_POST['op'] == t('Run backup now')) {
24 fbu_make_backup(TRUE);
25 }
26
27 $tasks = unserialize(variable_get('fbu_stored_tasks', serialize(array())));
28 $tasks_count = count($tasks);
29 drupal_set_message(t('There are %count tasks in the backup queue', array('%count' => $tasks_count)));
30
31 $disabled = false;
32 if(!@include_once('File/Archive.php') ) {
33 drupal_set_message(t('This module depends on the following %pear packages: <ol><li>%file</li><li>%mime</li></ol>You must install these before using this module.', array('%pear' => '<a href="http://pear.php.net/">PEAR</a>', '%file' => '<a href="http://pear.php.net/package/File_Archive">File_Archive</a>', '%mime' => '<a href="http://pear.php.net/package/MIME_Type">MIME_Type</a>')), 'error');
34 $disabled = true;
35 }
36
37 // Backups
38 $group = form_textfield(t('Email address'), 'fbu_email', variable_get('fbu_email', variable_get('site_mail', ini_get('sendmail_from'))), 45, 255, t('Email address to which backups will be sent.'));
39 $period = drupal_map_assoc(array(0, 600, 1800, 3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
40 $preiod[0] = t('disabled');
41 $group .= form_select(t('Automatically backup files every'), 'fbu_files_backup_interval', variable_get('fbu_files_backup_interval', 0), $period, t('Select how often you wish to have your files automatically backed up. Busy sites should choose more frequent backups. Requires crontab.'));
42 $backup_path = variable_get('fbu_auto_backup_path', FILE_DIRECTORY_TEMP);
43 if (variable_get('fbu_files_backup_interval', 0)) {
44 if (!file_check_directory($backup_path)) {
45 form_set_error('fbu_auto_backup_path', t('The automatic backup path does not exist, or is not writeable. Automatic backups will not begin until you fix this error.'));
46 }
47 else if ($test = tempnam($backup_path, 'fbu.')) {
48 file_delete($test);
49 }
50 else {
51 form_set_error('fbu_auto_backup_path', t('The automatic backup path exists, but is not writeable. Automatic backups will not begin until you fix this error.'));
52 }
53 }
54 else {
55 $attributes = array('disabled'=>'disabled');
56 }
57 $group .= form_textfield(t('Automatic backup path'), 'fbu_auto_backup_path', $backup_path, 30, 255, t('If automatic backups are enabled, you must specify a directory where you would like to store the backup files. The path must be absolute and for security reasons should not be accesible to the web.'), $attributes);
58 $group .= form_select(t('Compress and archive backups with'), 'fbu_archive_type', variable_get('fbu_archive_type', 'zip'), drupal_map_assoc(array('zip', 'tar', 'gz', 'bz2', 'tgz', 'tbz')), t('Which compression type do you prefer? See %url for the pros and cons of the different types.', array('%url' => '<a href="http://www.sitepoint.com/blogs/2005/08/06/file_archive/">here</a>')));
59
60 if (!count($radios)) {
61 $attributes['disabled'] = 'disabled';
62 }
63 else {
64 $group .= form_radios(t('Compress automatic backups'), 'fbu_auto_backup_compress', variable_get('fbu_auto_backup_compress', 0), $radios);
65 }
66
67 $size_options['0.5'] = t('%kb KB', array('%kb' => '512'));
68 $size_options[1] = t('%mb MB', array('%mb' => '1'));
69 $size_options[3] = t('%mb MB', array('%mb' => '3'));
70 $size_options[5] = t('%mb MB', array('%mb' => '5'));
71 $size_options[10] = t('%mb MB', array('%mb' => '10'));
72 $size_options[15] = t('%mb MB', array('%mb' => '15'));
73 $size_options[20] = t('%mb MB', array('%mb' => '20'));
74 $group .= form_select(t('Max email attachment size'), 'fbu_max_email', variable_get('fbu_max_email', 5), $size_options, t('Size is measured before compression, so emails will typically be somewhat smaller. Please note that the attachment can never be smaller than the largest attached file. If you have 10MB files on your server, the fbu module will attempt to send them as attachments.'));
75
76 $group .= form_radios(t('Complete backup or only the new files'), 'fbu_complete_only_new', variable_get('fbu_complete_only_new', 1), array(t('complete'), t('only new')), t('<em>Complete</em> backups will make copy of every file in your document root directory. <em>Only new</em> backups will only make a backup of those files that are new or modified since the last backup. It is worth noting that the very first time you make a backup using this module, the only <em>new mode</em> will function like complete.'));
77
78
79 $output = form_group(t('Filesystem backup'), $group);
80 $disabled = $disabled ? array('disabled' => 'disabled') : null;
81 $output .= form_submit(t('Run backup now'), 'op', $disabled);
82 return $output;
83 }
84
85 function fbu_cron() {
86 if ($interval = variable_get('fbu_files_backup_interval', 0)) {
87 // see if it's time for another auto-backup
88 if ((time() - $interval) >= variable_get('fbu_files_backup_interval', 0)) {
89 fbu_make_backup();
90 fbu_process_mail_queue();
91 }
92 }
93 }
94
95 function fbu_make_backup($manual = FALSE) {
96 global $fbu_time;
97
98 $fbu_time = time();
99
100 $tmpdir = variable_get('fbu_auto_backup_path', FILE_DIRECTORY_TEMP);
101 $scandir = $_SERVER['DOCUMENT_ROOT'];
102
103 // make sure we have permission to save our temp file
104 $archives = array();
105 if (file_check_directory($tmpdir)) {
106 $time = time();
107
108 $tasks = unserialize(variable_get('fbu_stored_tasks', serialize(array())));
109
110 // if there are no stored tasks, start over and read the whole directory.
111 if (!count($tasks)) {
112 // update the fbu_last_backup variable. This is the only place this occurs.
113 variable_set('fbu_last_backup', $time);
114
115 // Get all the files
116 $files = file_scan_directory($scandir, '$', array('.', '..', 'CVS'), 'fbu_get_filemtime');
117
118 while (count($files)) {
119 $task = array();
120 for ($i=0; $i<50; ++$i) {
121 $file = array_pop($files);
122 $task[$file->filename] = $file;
123 }
124 $tasks[] = $task;
125 }
126 }
127
128 $files = array_pop($tasks);
129
130 variable_set('fbu_stored_tasks', serialize($tasks));
131
132 // Filter the arrays by modified date
133 $files = array_filter($files, 'fbu_filter_by_modified');
134
135 // Sort the files by modified date
136 usort($files, "fbu_sort_by_modified");
137
138 $sets = fbu_get_included_files($files, $scandir);
139
140 $failure = false;
141 $mail_queue = array();
142 foreach ($sets as $set) {
143 $mail_queue[] = fbu_archive($scandir, $tmpdir, $set);
144 }
145
146 fbu_process_mail_queue($mail_queue, $manual, $tmpdir);
147 }
148 }
149
150
151 function fbu_get_included_files($files, $dir) {
152 $sets = array();
153
154 $maxsize = (int)(1048576 * (double)(variable_get('fbu_max_email', 5)));
155 $size = 0;
156 $count = 0;
157 $lastmodified = 0;
158 foreach ($files as $file) {
159 $size += filesize($file->filename);
160 if ($maxsize < $size) {
161 $size = 0;
162 $count++;
163 }
164 $sets[$count][] = str_replace($dir .'/', '', $file->filename);
165 }
166
167 foreach ($sets as $key => $set) {
168 $sets[$key] = '('. implode(')|(', $set). ')';
169 }
170
171 return $sets;
172 }
173
174 function fbu_archive($scandir, $tmpdir, $ereg) {
175 global $fbu_time;
176
177 // every backup made has a unique number
178 $count = db_next_id('fbu');
179 $path = variable_get('fbu_auto_backup_path', FILE_DIRECTORY_TEMP);
180 $filename = $count. '_'. format_date($fbu_time, 'custom', 'Ym-dHi_'). variable_get('site_name', 'drupal'). '.'. variable_get('fbu_archive_type', 'zip');
181
182 // PEAR Magic
183 require_once "File/Archive.php";
184 File_Archive::setOption("zipCompressionLevel", 9);
185
186 //Ask File_Archive to use the cache object we just created
187 File_Archive::setOption("cache", $cache);
188
189 // This writes the archive files. It filters based on the list of files in $ereg.
190 File_Archive::extract(
191 File_Archive::filter(
192 File_Archive::predEreg($ereg),
193 File_Archive::read($scandir)
194 ),
195 File_Archive::toArchive($tmpdir.'/'.$filename,
196 File_Archive::toFiles()
197 )
198 );
199 watchdog('fbu', "archive function returning $filename");
200 return $filename;
201 }
202
203 function fbu_process_mail_queue($mail_queue, $manual, $tmpdir) {
204 $failure = false;
205 foreach ($mail_queue as $filename) {
206 // The mail text
207 $text = "-- Drupal fbu.module files backup\n";
208 $text .= "--\n";
209 $text .= "-- Files:\n";
210 $text .= '---- '. $filename. "\n";
211 $text .= "-- Date: ". format_date(time(), 'large') ."\n\n";
212
213 // prepare the attachments for the mail
214 $attachment = new stdClass();
215 $attachment->path = $tmpdir ."/$filename";
216 $attachment->filename = $filename;
217
218 // mail it!
219 $sent = fbu_send_mail(array($attachment), $text, $manual);
220 if (!$sent) {
221 $failure = true;
222 }
223
224 // remove it.
225 unlink($tmpdir.'/'.$filename);
226 }
227 }
228
229
230 function fbu_send_mail($attachments, $text, $manual) {
231 // Send mail
232 $mail = new fbu_mail();
233 $mail->from = variable_get('fbu_email', variable_get('site_mail', ini_get('sendmail_from')));
234 $mail->headers = 'Errors-To: [EMAIL='. $mail->from. ']'. $mail->from. '[/EMAIL]';
235 $mail->to = $mail->from;
236 $mail->subject = t('Filesystem backup from %site', array('%site' => variable_get('site_name', 'drupal')));
237 $mail->body = $text;
238 $attached = array();
239 foreach ($attachments as $attachment) {
240 $file = fread(fopen($attachment->path, "r"), filesize($attachment->path));
241 $mail->add_attachment("$file", $attachment->filename, "Content-Transfer-Encoding: base64 /9j/4AAQSkZJRgABAgEASABIAAD/7QT+UGhvdG9zaG");
242 $attached[] = $attachment->filename;
243 }
244 $attached = implode(', ', $attached);
245 $message = '';
246
247 // send the mail, with attachments
248 $sent = $mail->send();
249
250 if ($sent) {
251 $message = t('File backup files sent to %mail: %files', array('%files' => $attached, '%mail' => $mail->to));
252 watchdog('fbu', $message);
253 }
254 else {
255 $message = t('File backup files sending <strong>FAILED</strong> to %mail: %files', array('%files' => $attached, '%mail' => $mail->to));
256 watchdog('fbu', $message, WATCHDOG_ERROR);
257 }
258 return $sent;
259 }
260
261 function fbu_sort_by_modified($a, $b) {
262 $a = fbu_get_filemtime($a->filename);
263 $b = fbu_get_filemtime($b->filename);
264
265 if ($a == $b) {
266 return 0;
267 }
268 return ($a < $b) ? -1 : 1;
269 }
270
271 function fbu_filter_by_modified($file) {
272 $time = variable_get('fbu_complete_only_new', 1) ? variable_get('fbu_last_backup', 0) : 0;
273 return(fbu_get_filemtime($file->filename) > $time);
274 }
275
276 function fbu_get_filemtime($filename) {
277 static $modtimes;
278 if (is_null($modtimes)) {
279 $modtimes = array();
280 }
281
282 if (is_null($modtimes[$filename])) {
283 $modtimes[$filename] = filemtime($filename);
284 }
285
286 return $modtimes[$filename];
287 }
288
289
290 /* Define a mail class to send mail with attachment. This is only here until we get a real mail backend.
291 * see http://www.php.net/function.mail
292 */
293 class fbu_mail {
294 var $parts;
295 var $to;
296 var $from;
297 var $headers;
298 var $subject;
299 var $body;
300
301 function mime_mail() {
302 $this->parts = array();
303 $this->to = "";
304 $this->from = "";
305 $this->subject = "";
306 $this->body = "";
307 $this->headers = "";
308 }
309
310 function add_attachment($message, $name = "", $ctype = "application/octet-stream") {
311 $this->parts [] = array (
312 "ctype" => $ctype,
313 "message" => $message,
314 "encode" => $encode,
315 "name" => $name
316 );
317 }
318
319
320 function build_message($part) {
321 $message = $part["message"];
322 $message = chunk_split(base64_encode($message));
323 $encoding = "base64";
324 return "Content-Type: ".$part["ctype"].($part["name"]? "; name = \"".$part["name"]."\"" : "")."\nContent-Transfer-Encoding: $encoding\n\n$message\n";
325 }
326
327 function build_multipart() {
328 $boundary = "b".md5(uniqid(time()));
329 $multipart = "Content-Type: multipart/mixed; boundary = $boundary\n\nThis is a MIME encoded message.\n\n--$boundary";
330 for($i = sizeof($this->parts)-1; $i>=0; $i--) $multipart .= "\n".$this->build_message($this->parts[$i]). "--$boundary";
331 return $multipart.= "--\n";
332 }
333
334
335 function send() {
336 $mime = "";
337 if (!empty($this->from)) $mime .= "From: ".$this->from. "\n";
338 if (!empty($this->headers)) $mime .= $this->headers. "\n";
339 if (!empty($this->body)) $this->add_attachment($this->body, "", "text/plain");
340 $mime .= "MIME-Version: 1.0\n".$this->build_multipart();
341 return mail($this->to, $this->subject, "", $mime);
342 }
343 }
344
345 ?>

  ViewVC Help
Powered by ViewVC 1.1.2