1 | <?php |
---|
2 | /** |
---|
3 | * PEdit:: provides a mechanism to store text in php variables |
---|
4 | * which will be printed to the client browser under normal |
---|
5 | * circumstances, but an authenticated user can 'edit' the document-- |
---|
6 | * data stored in vars will be shown in html form elements to be editied |
---|
7 | * and saved. On save, a mass search and replace is complated to inssert the new |
---|
8 | * data into the old file. A copy of the previous version is saved with the unix |
---|
9 | * timestamp as part of the filename. This allows reverting to previous versions. |
---|
10 | * |
---|
11 | * To use, include this file, initialize variables, |
---|
12 | * and call printing/editing functions where you want data and forms to |
---|
13 | * show up. Below is an example of use: |
---|
14 | * |
---|
15 | * // Initialize. |
---|
16 | * require_once 'codebase/lib/PEdit.inc.php'; |
---|
17 | * $p = new PEdit($auth->hasClearance('pedit')); |
---|
18 | * |
---|
19 | * $title = <<<P_E_D_I_T_title |
---|
20 | * Using Burritos to Improve Student Learnin' |
---|
21 | * P_E_D_I_T_title; |
---|
22 | * $p->set($title, 'title', 'textbox'); |
---|
23 | * |
---|
24 | * // Begin content. Include a header or something right here. |
---|
25 | * $p->printContent('title'); |
---|
26 | * |
---|
27 | * // Prints beginning form tags and special hidden forms. (Only happens if page is NOT a archived version.) |
---|
28 | * $p->formBegin(); |
---|
29 | * |
---|
30 | * // Print editing form elements. (Only happens if op == Edit.) |
---|
31 | * $p->printForm('title'); |
---|
32 | * |
---|
33 | * // Print versions list. (Only happens if op == Versions.) |
---|
34 | * $p->printVersions(); |
---|
35 | * |
---|
36 | * // Prints ending form tags and command buttons.(Only happens if page is NOT a archived version.) |
---|
37 | * $p->formEnd(); |
---|
38 | * |
---|
39 | * @author Quinn Comendant <quinn@strangecode.com> |
---|
40 | * @concept Beau Smith <beau@beausmith.com> |
---|
41 | * @version 1.1 |
---|
42 | */ |
---|
43 | class PEdit |
---|
44 | { |
---|
45 | var $_data = array(); // Array to store editable data. |
---|
46 | var $_filename = ''; // Full file path to current file. |
---|
47 | var $_authorized = false; // User is authenticated to see extended functions. |
---|
48 | var $versions_min_qty = 20; // Keep at least this many versions of each file. |
---|
49 | var $versions_min_days = 10;// Keep ALL versions within this many days, even if MORE than versions_min_qty. |
---|
50 | |
---|
51 | // Tags that are not stripped from the POSTed data. |
---|
52 | var $allowed_tags = '<p><h1><h2><h3><h4><h5><h6><div><br><hr><a><img><i><em><b><strong><small><blockquote><ul><ol><li><dl><dt><dd><map><area><table><tr><td>'; |
---|
53 | |
---|
54 | |
---|
55 | /** |
---|
56 | * Constructs a new PEdit object. Initializes what file is being operated on |
---|
57 | * (SCRIPT_FILENAME) and what that operation is. The two |
---|
58 | * operations that actually modify data (save, restore) are treated differently |
---|
59 | * than view operations (versions, '' - default). They die redirect so you see |
---|
60 | * the page you just modified. |
---|
61 | * |
---|
62 | * @access public |
---|
63 | * |
---|
64 | * @param optional array $params A hash containing connection parameters. |
---|
65 | */ |
---|
66 | function PEdit($authorized=false) |
---|
67 | { |
---|
68 | if ($authorized === true) { |
---|
69 | $this->_authorized = true; |
---|
70 | } |
---|
71 | |
---|
72 | $this->_filename = $_SERVER['SCRIPT_FILENAME']; |
---|
73 | if (empty($this->_filename)) { |
---|
74 | App::logMsg(sprintf('PEdit error: server variable SCRIPT_FILENAME must be defined.', null), LOG_WARNING, __FILE__, __LINE__); |
---|
75 | die; |
---|
76 | } |
---|
77 | |
---|
78 | $this->op = getFormData('op'); |
---|
79 | |
---|
80 | switch ($this->op) { |
---|
81 | case 'Save' : |
---|
82 | if ($this->_writeData()) { |
---|
83 | App::dieURL($_SERVER['PHP_SELF']); |
---|
84 | } |
---|
85 | break; |
---|
86 | case 'Restore' : |
---|
87 | if ($this->_restoreVersion(getFormData('with_file'))) { |
---|
88 | App::dieURL($_SERVER['PHP_SELF']); |
---|
89 | } |
---|
90 | break; |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | /** |
---|
95 | * Stores a variable in the pedit data array with the content name, and type of form. |
---|
96 | * |
---|
97 | * @access public |
---|
98 | * |
---|
99 | * @param string $content The variable containing the text to store. |
---|
100 | * @param string $name The name of the variable. |
---|
101 | * @param string $type The type of form element to use. |
---|
102 | * @param optional int $form_size The size of the form element. |
---|
103 | */ |
---|
104 | function set($content, $name, $type, $form_size=null) |
---|
105 | { |
---|
106 | $this->_data[$name] = array( |
---|
107 | 'type' => $type, |
---|
108 | 'content' => $content, |
---|
109 | 'form_size' => $form_size |
---|
110 | ); |
---|
111 | } |
---|
112 | |
---|
113 | /** |
---|
114 | * Stores a checkbox variable in the pedit data array with the content name, and type of form. |
---|
115 | * |
---|
116 | * @access public |
---|
117 | * |
---|
118 | * @param string $content The variable containing the text to store. |
---|
119 | * @param string $name The name of the variable. |
---|
120 | * @param string $corresponding_text The text that corresponds to this checkbox. |
---|
121 | */ |
---|
122 | function setCheckbox($content, $name, $corresponding_text) |
---|
123 | { |
---|
124 | if (isset($content) && isset($name) && isset($corresponding_text)) { |
---|
125 | $this->_data[$name] = array( |
---|
126 | 'type' => 'checkbox', |
---|
127 | 'content' => $content, |
---|
128 | 'corresponding_text' => $corresponding_text |
---|
129 | ); |
---|
130 | } |
---|
131 | } |
---|
132 | |
---|
133 | /** |
---|
134 | * Tests if we are should display page contents. |
---|
135 | * |
---|
136 | * @access public |
---|
137 | * |
---|
138 | * @return bool true if we are displaying page normally, false if editing page, or viewing versions. |
---|
139 | */ |
---|
140 | function displayMode() |
---|
141 | { |
---|
142 | if ($this->op != 'Edit' && $this->op != 'Versions' && isset($this->_data[$name]['content'])) { |
---|
143 | return true; |
---|
144 | } |
---|
145 | } |
---|
146 | |
---|
147 | |
---|
148 | /** |
---|
149 | * Prints an HTML list of versions of current file, with the filesize |
---|
150 | * and links to view and restore the file. |
---|
151 | * |
---|
152 | * @access public |
---|
153 | */ |
---|
154 | function printVersions() |
---|
155 | { |
---|
156 | if ($this->_authorized && $this->op == 'Versions') { |
---|
157 | // Print versions and commands to view/restore. |
---|
158 | $versions = $this->_getVersions(); |
---|
159 | ?><h1><?php printf(_("%s saved versions of %s"), sizeof($versions), basename($this->_filename)); ?></h1><?php |
---|
160 | if (is_array($versions) && !empty($versions)) { |
---|
161 | ?><table border="0" cellspacing="0" cellpadding="4"><?php |
---|
162 | foreach ($versions as $v) { |
---|
163 | ?> |
---|
164 | <tr> |
---|
165 | <td valign="top" nowrap="nowrap"><p><?php echo date('r', $v['unixtime']); ?></p></td> |
---|
166 | <td valign="top" nowrap="nowrap"><p> <?php printf(_("%s bytes"), $v['filesize']); ?></p></td> |
---|
167 | <td valign="top" nowrap="nowrap"><p> [<a href="<?php echo App::oHREF(dirname($_SERVER['PHP_SELF']) . (preg_match('!/$!', dirname($_SERVER['PHP_SELF'])) ? '' : '/') . $v['filename']); ?>" target="_blank"><?php echo _("view"); ?></a>]</p></td> |
---|
168 | <td valign="top" nowrap="nowrap"><p> [<a href="<?php echo App::oHREF($_SERVER['PHP_SELF'] . '?op=Restore&with_file=' . $v['filename'] . '&file_hash=' . md5('frog_guts' . $this->_filename)); ?>"><?php echo _("restore"); ?></a>]</p></td> |
---|
169 | </tr> |
---|
170 | <?php |
---|
171 | } |
---|
172 | ?></table><?php |
---|
173 | ?><div class="help"><?php printf(_("When there are more than %s versions, those over %s days old are deleted."), $this->versions_min_qty, $this->versions_min_days); ?></div><?php |
---|
174 | } |
---|
175 | } |
---|
176 | } |
---|
177 | |
---|
178 | /** |
---|
179 | * Returns the contents of a data variable. The variable must first be 'set'. |
---|
180 | * |
---|
181 | * @access public |
---|
182 | * |
---|
183 | * @param string $name The name of the variable to return. |
---|
184 | * |
---|
185 | * @return string The trimmed content of the named data. |
---|
186 | */ |
---|
187 | function getContent($name, $preserve_html=true) |
---|
188 | { |
---|
189 | if ($this->op != 'Edit' && $this->op != 'Versions' && isset($this->_data[$name]['content'])) { |
---|
190 | // Print content. |
---|
191 | switch ($this->_data[$name]['type']) { |
---|
192 | case 'checkbox' : |
---|
193 | return 'off' == $this->_data[$name]['content'] ? '' : oTxt($this->_data[$name]['corresponding_text'], $preserve_html); |
---|
194 | default : |
---|
195 | return trim(oTxt($this->_data[$name]['content'], $preserve_html)); |
---|
196 | } |
---|
197 | } |
---|
198 | } |
---|
199 | |
---|
200 | /** |
---|
201 | * Prints the contents of a data variable. The variable must first be 'set'. |
---|
202 | * |
---|
203 | * @access public |
---|
204 | * |
---|
205 | * @param string $name The name of the variable to print. |
---|
206 | */ |
---|
207 | function printContent($name, $preserve_html=true) |
---|
208 | { |
---|
209 | echo $this->getContent($name, $preserve_html); |
---|
210 | } |
---|
211 | |
---|
212 | /** |
---|
213 | * Prints the HTML forms corresponding to pedit variables. Each variable |
---|
214 | * must first be 'set'. |
---|
215 | * |
---|
216 | * @access public |
---|
217 | * |
---|
218 | * @param string $name The name of the variable. |
---|
219 | */ |
---|
220 | function printForm($name) |
---|
221 | { |
---|
222 | if ($this->_authorized && $this->op == 'Edit' && isset($this->_data[$name]['type'])) { |
---|
223 | // Print edit form. |
---|
224 | switch ($this->_data[$name]['type']) { |
---|
225 | case 'textbox' : |
---|
226 | $rows = is_numeric($this->_data[$name]['form_size']) ? $this->_data[$name]['form_size'] : 50; |
---|
227 | echo '<input class="monospaced" style="width: 100%;" type="text" name="data[' . $name . ']" value="' . oTxt($this->_data[$name]['content']) . '" size="' . $rows . '" /><br />'; |
---|
228 | break; |
---|
229 | case 'textarea' : |
---|
230 | $rows = is_numeric($this->_data[$name]['form_size']) ? $this->_data[$name]['form_size'] : 20; |
---|
231 | echo '<textarea class="monospaced" style="width: 100%;" rows="' . $rows . '" cols="60" name="data[' . $name . ']">' . oTxt($this->_data[$name]['content']) . '</textarea><br />'; |
---|
232 | break; |
---|
233 | case 'checkbox' : |
---|
234 | $checked = ('off' == $this->_data[$name]['content']) ? '' : 'checked="checked" '; |
---|
235 | // Note hidden form below. If the checkbox is not checked, the hidden variable will send "off" as the variable, |
---|
236 | // otherwise if the form is not posted for that checkbox the update will not occur. |
---|
237 | ?> |
---|
238 | <table border="0" cellspacing="0" cellpadding="2"><tr> |
---|
239 | <td valign="top"><input type="hidden" name="data[<?php echo $name; ?>]" value="off" /><input type="checkbox" name="data[<?php echo $name; ?>]" <?php echo $checked; ?>/></td> |
---|
240 | <td valign="top"><?php echo oTxt($this->_data[$name]['corresponding_text']); ?></td> |
---|
241 | </tr></table> |
---|
242 | <?php |
---|
243 | break; |
---|
244 | } |
---|
245 | } |
---|
246 | } |
---|
247 | |
---|
248 | /** |
---|
249 | * Loops through the PEdit data array and prints all the HTML forms corresponding |
---|
250 | * to all pedit variables, in the order in which they were 'set'. |
---|
251 | * |
---|
252 | * @access public |
---|
253 | */ |
---|
254 | function printAllForms() |
---|
255 | { |
---|
256 | if ($this->_authorized && $this->op == 'Edit' && is_array($this->_data) && !empty($this->_data)) { |
---|
257 | foreach ($this->_data as $name=>$d) { |
---|
258 | $this->printForm($name); |
---|
259 | } |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * Prints the beginning <form> HTML tag, as well as hidden input forms. |
---|
265 | * |
---|
266 | * @return bool False if unauthorized or current page is a version. |
---|
267 | */ |
---|
268 | function formBegin() |
---|
269 | { |
---|
270 | if (!$this->_authorized || preg_match('/\.php__/', $this->_filename)) { |
---|
271 | // Don't show form elements for versioned documents. |
---|
272 | return false; |
---|
273 | } |
---|
274 | ?> |
---|
275 | <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> |
---|
276 | <input type="hidden" name="filename" value="<?php echo $this->_filename; ?>" /> |
---|
277 | <input type="hidden" name="file_hash" value="<?php echo md5('frog_guts' . $this->_filename); ?>" /> |
---|
278 | <?php |
---|
279 | App::printHiddenSession(); |
---|
280 | switch ($this->op) { |
---|
281 | case 'Edit' : |
---|
282 | ?> |
---|
283 | <div class="pedit_buttons"> |
---|
284 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Save"); ?>" /> |
---|
285 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Cancel"); ?>" /> |
---|
286 | </div> |
---|
287 | <?php |
---|
288 | break; |
---|
289 | } |
---|
290 | } |
---|
291 | |
---|
292 | /** |
---|
293 | * Prints the endig </form> HTML tag, as well as buttons used during |
---|
294 | * different operations. |
---|
295 | * |
---|
296 | * @return bool False if unauthorized or current page is a version. |
---|
297 | */ |
---|
298 | function formEnd() |
---|
299 | { |
---|
300 | if (!$this->_authorized || preg_match('/\.php__/', $this->_filename)) { |
---|
301 | // Don't show form elements for versioned documents. |
---|
302 | return false; |
---|
303 | } |
---|
304 | switch ($this->op) { |
---|
305 | case 'Edit' : |
---|
306 | ?> |
---|
307 | <div class="pedit_buttons"> |
---|
308 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Save"); ?>" /> |
---|
309 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Cancel"); ?>" /> |
---|
310 | </div> |
---|
311 | </form> |
---|
312 | <?php |
---|
313 | break; |
---|
314 | case 'Versions' : |
---|
315 | ?> |
---|
316 | <div class="pedit_buttons"> |
---|
317 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Cancel"); ?>" /> |
---|
318 | </div> |
---|
319 | </form> |
---|
320 | <?php |
---|
321 | break; |
---|
322 | default : |
---|
323 | ?> |
---|
324 | <div class="pedit_buttons"> |
---|
325 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Edit"); ?>" /> |
---|
326 | <input class="formsubmitbutton" type="submit" name="op" value="<?php echo _("Versions"); ?>" /> |
---|
327 | </div> |
---|
328 | </form> |
---|
329 | <?php |
---|
330 | } |
---|
331 | } |
---|
332 | |
---|
333 | /** |
---|
334 | * Saves the POSTed data by overwriting the pedit variables in the |
---|
335 | * current file. |
---|
336 | * |
---|
337 | * @access private |
---|
338 | * |
---|
339 | * @return bool False if unauthorized or on failure. True on success. |
---|
340 | */ |
---|
341 | function _writeData() |
---|
342 | { |
---|
343 | if (!$this->_authorized) { |
---|
344 | return false; |
---|
345 | } |
---|
346 | if (md5('frog_guts' . $this->_filename) != getFormData('file_hash')) { |
---|
347 | // Posted data is NOT for this file! |
---|
348 | trigger_error('PEdit error: file_hash does not match current file.', E_USER_WARNING); |
---|
349 | return false; |
---|
350 | } |
---|
351 | $whole_file = file_get_contents($this->_filename); |
---|
352 | $new_data = getFormData('data'); |
---|
353 | $search = array(); |
---|
354 | $replace = array(); |
---|
355 | if (is_array($new_data) && !empty($new_data)) { |
---|
356 | foreach ($new_data as $name=>$d) { |
---|
357 | if ('' != $d && !preg_match('/P_E_D_I_T_/', $d)) { |
---|
358 | // If the new posted data is not empty, and the heredoc identifer is not in it. |
---|
359 | $block_identifier = 'P_E_D_I_T_' . preg_quote($name); |
---|
360 | if (substr_count($whole_file, $block_identifier) != 2) { |
---|
361 | App::logMsg(sprintf('PEdit error: more than one %s heredoc identifier found.', $block_identifier), LOG_NOTICE, __FILE__, __LINE__); |
---|
362 | return false; |
---|
363 | } |
---|
364 | // Strip extra linefeeds. For some reason POST data has double EOL chars when writing to a unix file. |
---|
365 | $d = preg_replace("/[\n\r]{2,}/", "\n", $d); |
---|
366 | $search[] = "/$block_identifier.*?\n$block_identifier;/s"; |
---|
367 | $replace[] = "$block_identifier\n" . strip_tags($d, $this->allowed_tags) . "\n$block_identifier;"; |
---|
368 | } |
---|
369 | } |
---|
370 | |
---|
371 | // Search and replace all blocks. |
---|
372 | $whole_file = preg_replace($search, $replace, $whole_file); |
---|
373 | |
---|
374 | // Probably unnecessary, testing if resulting file is empty or smaller than input. |
---|
375 | if (strlen($whole_file) < strlen(strip_tags(serialize($new_data), $this->allowed_tags))) { |
---|
376 | App::logMsg(sprintf('PEdit error: saved file size (%s) is less than input data size (%s).', strlen($whole_file), strlen(strip_tags(serialize($new_data), $this->allowed_tags))), LOG_NOTICE, __FILE__, __LINE__); |
---|
377 | return false; |
---|
378 | } |
---|
379 | |
---|
380 | // Make certain a version is created. |
---|
381 | if (! $this->_createVersion()) { |
---|
382 | App::logMsg(sprintf('PEdit error: failed creating new version of file.', null), LOG_NOTICE, __FILE__, __LINE__); |
---|
383 | return false; |
---|
384 | } |
---|
385 | |
---|
386 | // Open file for writing and truncate to zero length. |
---|
387 | if (is_writable($this->_filename) && $fp = fopen($this->_filename, 'w')) { |
---|
388 | if (flock($fp, LOCK_EX)) { |
---|
389 | fwrite($fp, $whole_file, strlen($whole_file)); |
---|
390 | flock($fp, LOCK_UN); |
---|
391 | } else { |
---|
392 | App::logMsg(sprintf('PEdit error: could not lock file for writing: %s', $this->_filename), LOG_NOTICE, __FILE__, __LINE__); |
---|
393 | return false; |
---|
394 | } |
---|
395 | fclose($fp); |
---|
396 | // Success! |
---|
397 | return true; |
---|
398 | } else { |
---|
399 | App::logMsg(sprintf('PEdit error: could not open file for writing: %s', $this->_filename), LOG_NOTICE, __FILE__, __LINE__); |
---|
400 | return false; |
---|
401 | } |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | /** |
---|
406 | * Makes a copy of the current file with the unix timestamp appended to the |
---|
407 | * filename. Deletes old versions based on threshold of age and qty. |
---|
408 | * |
---|
409 | * @access private |
---|
410 | * |
---|
411 | * @param optional boolean $do_cleanup Set to false to turn off the |
---|
412 | * cleanup routine. |
---|
413 | * |
---|
414 | * @return bool False if unauthorized or on failure. True on success. |
---|
415 | */ |
---|
416 | function _createVersion($do_cleanup=true) |
---|
417 | { |
---|
418 | if (!$this->_authorized) { |
---|
419 | return false; |
---|
420 | } |
---|
421 | if (md5('frog_guts' . $this->_filename) != getFormData('file_hash')) { |
---|
422 | // Posted data is NOT for this file! |
---|
423 | trigger_error('PEdit error: file_hash does not match current file.', E_USER_WARNING); |
---|
424 | return false; |
---|
425 | } |
---|
426 | $versions = $this->_getVersions(); |
---|
427 | |
---|
428 | // Clean up old versions. |
---|
429 | if (is_array($versions) && sizeof($versions) > $this->versions_min_qty && $do_cleanup) { |
---|
430 | // Pop oldest ones off bottom of array. |
---|
431 | $oldest = array_pop($versions); |
---|
432 | // Loop while minimum X qty && minimum X days worth but never more than 100 qty. |
---|
433 | while ((sizeof($versions) > $this->versions_min_qty |
---|
434 | && $oldest['unixtime'] < mktime(date('H'),date('i'),date('s'),date('m'),date('d')-$this->versions_min_days,date('Y'))) |
---|
435 | || sizeof($versions) > 100) { |
---|
436 | unlink(dirname($this->_filename) . '/' . $oldest['filename']); |
---|
437 | $oldest = array_pop($versions); |
---|
438 | } |
---|
439 | } |
---|
440 | |
---|
441 | // Do the actual copy. File naming scheme must be consistent! |
---|
442 | if (!copy($this->_filename, $this->_filename . '__' . time() . '.php')) { |
---|
443 | trigger_error('PEdit error: failed copying new version. Check file and directory permissions.', E_USER_WARNING); |
---|
444 | return false; |
---|
445 | } |
---|
446 | |
---|
447 | return true; |
---|
448 | } |
---|
449 | |
---|
450 | /** |
---|
451 | * Returns an array of all archived versions of the current file, |
---|
452 | * sorted with newest versions at the top of the array. |
---|
453 | * |
---|
454 | * @access private |
---|
455 | * |
---|
456 | * @return array Array of versions. |
---|
457 | */ |
---|
458 | function _getVersions() |
---|
459 | { |
---|
460 | $versions = array(); |
---|
461 | $dir_handle = opendir(dirname($this->_filename)); |
---|
462 | while ($dir_handle && ($version = readdir($dir_handle)) !== false) { |
---|
463 | if (!preg_match('/^\./', $version) && !is_dir($version) && preg_match('/^' . preg_quote(basename($this->_filename)) . '__.*/', $version)) { |
---|
464 | preg_match('/.+__(\d+)\.php/', $version, $time); |
---|
465 | $versions[] = array( |
---|
466 | 'filename' => $version, |
---|
467 | 'unixtime' => $time[1], |
---|
468 | 'filesize' => filesize(dirname($this->_filename) . '/' . $version) |
---|
469 | ); |
---|
470 | } |
---|
471 | } |
---|
472 | |
---|
473 | if (is_array($versions) && !empty($versions)) { |
---|
474 | array_multisort($versions, SORT_DESC); |
---|
475 | return $versions; |
---|
476 | } else { |
---|
477 | return array(); |
---|
478 | } |
---|
479 | } |
---|
480 | |
---|
481 | /** |
---|
482 | * Makes a version backup of the current file, then copies the specified |
---|
483 | * archived version over the current file. |
---|
484 | * |
---|
485 | * @access private |
---|
486 | * |
---|
487 | * @param string $with_file Filename of archived version to restore. |
---|
488 | * |
---|
489 | * @return bool False if unauthorized. True on success. |
---|
490 | */ |
---|
491 | function _restoreVersion($with_file) |
---|
492 | { |
---|
493 | if (!$this->_authorized) { |
---|
494 | return false; |
---|
495 | } |
---|
496 | |
---|
497 | if (is_writable($this->_filename)) { |
---|
498 | // Make certain a version is created. |
---|
499 | if (! $this->_createVersion(false)) { |
---|
500 | App::logMsg(sprintf('PEdit error: failed creating new version of file.', null), LOG_NOTICE, __FILE__, __LINE__); |
---|
501 | return false; |
---|
502 | } |
---|
503 | |
---|
504 | // Do the actual copy. |
---|
505 | if (!copy(dirname($this->_filename) . '/' . $with_file, $this->_filename)) { |
---|
506 | App::logMsg(sprintf('PEdit error: failed copying old version: %s', $with_file), LOG_NOTICE, __FILE__, __LINE__); |
---|
507 | return false; |
---|
508 | } |
---|
509 | |
---|
510 | // Success! |
---|
511 | return true; |
---|
512 | } else { |
---|
513 | App::logMsg(sprintf('PEdit error: could not open file for writing: %s', $this->_filename), LOG_NOTICE, __FILE__, __LINE__); |
---|
514 | return false; |
---|
515 | } |
---|
516 | } |
---|
517 | |
---|
518 | } // End class. |
---|
519 | |
---|
520 | ?> |
---|