Handles file permissions. Protect against overwriting changes.
This commit is contained in:
parent
65c37abef9
commit
f7f19af816
4 changed files with 154 additions and 135 deletions
|
@ -28,13 +28,23 @@ require_once('../../../lib/base.php');
|
|||
OC_JSON::checkLoggedIn();
|
||||
|
||||
// Set the session key for the file we are about to edit.
|
||||
$path = isset($_GET['path']) ? $_GET['path'] : false;
|
||||
|
||||
if($path){
|
||||
$sessionname = md5('oc_file_hash_'.$path);
|
||||
$filecontents = OC_Filesystem::file_get_contents($path);
|
||||
OC_Filesystem::update_session_file_hash($sessionname,sha1(htmlspecialchars($filecontents)));
|
||||
OC_JSON::success();
|
||||
$dir = isset($_GET['dir']) ? $_GET['dir'] : '';
|
||||
$filename = isset($_GET['file']) ? $_GET['file'] : '';
|
||||
if(!empty($filename))
|
||||
{
|
||||
$path = $dir.'/'.$filename;
|
||||
if(OC_Filesystem::is_writeable($path))
|
||||
{
|
||||
$mtime = OC_Filesystem::filemtime($path);
|
||||
$filecontents = OC_Filesystem::file_get_contents($path);
|
||||
OC_JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'true', 'mtime' => $mtime)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$mtime = OC_Filesystem::filemtime($path);
|
||||
$filecontents = OC_Filesystem::file_get_contents($path);
|
||||
OC_JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'false', 'mtime' => $mtime)));
|
||||
}
|
||||
} else {
|
||||
OC_JSON::error();
|
||||
}
|
||||
OC_JSON::error(array('data' => array( 'message' => 'Invalid file path supplied.')));
|
||||
}
|
49
apps/files_texteditor/ajax/mtime.php
Normal file
49
apps/files_texteditor/ajax/mtime.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud - files_texteditor
|
||||
*
|
||||
* @author Tom Needham
|
||||
* @copyright 2011 Tom Needham contact@tomneedham.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Init owncloud
|
||||
require_once('../../../lib/base.php');
|
||||
|
||||
|
||||
// Check if we are a user
|
||||
OC_JSON::checkLoggedIn();
|
||||
|
||||
// Get the path from GET
|
||||
$path = isset($_GEt['path']) ? $_GET['path'] : '';
|
||||
|
||||
if($path != '')
|
||||
{
|
||||
// Find the mtime
|
||||
$mtime = OC_Filesystem::filemtime($path);
|
||||
if($mtime)
|
||||
{
|
||||
OC_JSON::success(array('data' => array('path' => $path, 'mtime' => $mtime)));
|
||||
}
|
||||
else
|
||||
{
|
||||
OC_JSON::error();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OC_JSON::error();
|
||||
}
|
|
@ -27,47 +27,36 @@ require_once('../../../lib/base.php');
|
|||
// Check if we are a user
|
||||
OC_JSON::checkLoggedIn();
|
||||
|
||||
// Save the file data
|
||||
// Get paramteres
|
||||
$filecontents = htmlspecialchars_decode($_POST['filecontents']);
|
||||
$file = $_POST['file'];
|
||||
$dir = $_POST['dir'];
|
||||
$path = $dir.'/'.$file;
|
||||
$force = isset($_POST['force']) ? $_POST['force'] : false;
|
||||
$sessionname = sha1('oc_file_hash_'.$path);
|
||||
$path = isset($_POST['path']) ? $_POST['path'] : '';
|
||||
$mtime = isset($_POST['mtime']) ? $_POST['mtime'] : '';
|
||||
|
||||
function do_save($path,$filecontents){
|
||||
$sessionname = md5('oc_file_hash_'.$path);
|
||||
OC_Filesystem::update_session_file_hash($sessionname,sha1(htmlspecialchars($filecontents)));
|
||||
OC_Filesystem::file_put_contents($path, $filecontents);
|
||||
}
|
||||
|
||||
// Check if file modified whilst editing?
|
||||
if(isset($_SESSION[$sessionname])){
|
||||
if(!empty($_SESSION[$sessionname])){
|
||||
// Compare to current hash of file.
|
||||
$savedfilecontents = htmlspecialchars(OC_Filesystem::file_get_contents($path));
|
||||
$hash = md5($savedfilecontents);
|
||||
$originalhash = $_SESSION[$sessionname];
|
||||
// Compare with hash taken when file was opened
|
||||
if($hash != $originalhash){
|
||||
// Someone has played with the file while you were editing
|
||||
// Force save?
|
||||
if($force){
|
||||
do_save($path, $filecontents);
|
||||
OC_JSON::success();
|
||||
} else {
|
||||
// No force
|
||||
OC_JSON::error(array('data' => array( 'message' => $l10n->t('The file has been edited since you opened it. Overwrite the file?'))));
|
||||
}
|
||||
} else {
|
||||
// No body has edited it whilst you were, so save the file
|
||||
// Update the session hash.
|
||||
do_save($path,$filecontents);
|
||||
OC_JSON::success();
|
||||
}
|
||||
if($path != '' && $mtime != '')
|
||||
{
|
||||
// Get file mtime
|
||||
$filemtime = OC_Filesystem::filemtime($path);
|
||||
if($mtime != $filemtime)
|
||||
{
|
||||
// Then the file has changed since opening
|
||||
OC_JSON::error();
|
||||
}
|
||||
else
|
||||
{
|
||||
// File same as when opened
|
||||
// Save file
|
||||
if(OC_Filesystem::is_writeable($path))
|
||||
{
|
||||
OC_Filesystem::file_put_contents($path, $filecontents);
|
||||
OC_JSON::success();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not writeable!
|
||||
OC_JSON::error(array('data' => array( 'message' => 'Insufficient permissions')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No session value set for soem reason, just save the file.
|
||||
do_save($path,$filecontents);
|
||||
OC_JSON::success();
|
||||
}
|
||||
OC_JSON::error(array('data' => array( 'message' => 'File path or mtime not supplied')));
|
||||
}
|
||||
|
|
|
@ -77,81 +77,42 @@ function editorIsShown(){
|
|||
return is_editor_shown;
|
||||
}
|
||||
|
||||
function updateSessionFileHash(path){
|
||||
$.get(OC.filePath('files_texteditor','ajax','loadfile.php'),
|
||||
{ path: path },
|
||||
function(jsondata){
|
||||
if(jsondata.status=='failure'){
|
||||
alert('Failed to update session file hash.');
|
||||
}
|
||||
}, "json");}
|
||||
|
||||
function doFileSave(){
|
||||
if(editorIsShown()){
|
||||
// Get file path
|
||||
var path = $('#editor').attr('data-dir')+'/'+$('#editor').attr('data-filename');
|
||||
// Get original mtime
|
||||
var mtime = $('#editor').attr('data-mtime');
|
||||
// Show saving spinner
|
||||
$("#editor_save").die('click',doFileSave);
|
||||
$('#editor_save').after('<img id="saving_icon" src="'+OC.filePath('core','img','loading.gif')+'"></img>');
|
||||
var filecontents = window.aceEditor.getSession().getValue();
|
||||
var dir = $('#editor').attr('data-dir');
|
||||
var file = $('#editor').attr('data-filename');
|
||||
$.post(OC.filePath('files_texteditor','ajax','savefile.php'), { filecontents: filecontents, file: file, dir: dir },function(jsondata){
|
||||
|
||||
if(jsondata.status == 'failure'){
|
||||
var answer = confirm(jsondata.data.message);
|
||||
if(answer){
|
||||
$.post(OC.filePath('files_texteditor','ajax','savefile.php'),{ filecontents: filecontents, file: file, dir: dir, force: 'true' },function(jsondata){
|
||||
if(jsondata.status =='success'){
|
||||
$('#saving_icon').remove();
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Saved!</p>')
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
else {
|
||||
// Save error
|
||||
$('#saving_icon').remove();
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Failed!</p>');
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
}, 'json');
|
||||
}
|
||||
else {
|
||||
// Don't save!
|
||||
$('#saving_icon').remove();
|
||||
// Temporary measure until we get a tick icon
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Saved!</p>');
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
else if(jsondata.status == 'success'){
|
||||
// Success
|
||||
$('#saving_icon').remove();
|
||||
// Temporary measure until we get a tick icon
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Saved!</p>');
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
}, 'json');
|
||||
giveEditorFocus();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
// Get the data
|
||||
var filecontents = window.aceEditor.getSession().getValue();
|
||||
// Send the data
|
||||
$.post(OC.filePath('files_texteditor','ajax','savefile.php'), { filecontents: filecontents, path: path, mtime: mtime },function(jsondata){
|
||||
if(jsondata.status!='success'){
|
||||
// Save failed
|
||||
$('#saving_icon').remove();
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Failed to save file</p>');
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
} else {
|
||||
// Save OK
|
||||
$('#saving_icon').remove();
|
||||
$('#editor_save').after('<p id="save_result" style="float: left">Saved</p>')
|
||||
setTimeout(function() {
|
||||
$('#save_result').fadeOut('slow',function(){
|
||||
$(this).remove();
|
||||
$("#editor_save").live('click',doFileSave);
|
||||
});
|
||||
}, 2000);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
};
|
||||
|
||||
function giveEditorFocus(){
|
||||
|
@ -162,24 +123,34 @@ function showFileEditor(dir,filename){
|
|||
if(!editorIsShown()){
|
||||
// Loads the file editor and display it.
|
||||
var data = $.ajax({
|
||||
url: OC.filePath('files','ajax','download.php')+'?files='+encodeURIComponent(filename)+'&dir='+encodeURIComponent(dir),
|
||||
url: OC.filePath('files_texteditor','ajax','loadfile.php'),
|
||||
data: 'file='+encodeURIComponent(filename)+'&dir='+encodeURIComponent(dir),
|
||||
complete: function(data){
|
||||
// Initialise the editor
|
||||
updateSessionFileHash(dir+'/'+filename);
|
||||
showControls(filename);
|
||||
$('table').fadeOut('slow', function() {
|
||||
$('#editor').text(data.responseText);
|
||||
// encodeURIComponenet?
|
||||
$('#editor').attr('data-dir', dir);
|
||||
$('#editor').attr('data-filename', filename);
|
||||
window.aceEditor = ace.edit("editor");
|
||||
aceEditor.setShowPrintMargin(false);
|
||||
setEditorSize();
|
||||
setSyntaxMode(getFileExtension(filename));
|
||||
OC.addScript('files_texteditor','aceeditor/theme-clouds', function(){
|
||||
window.aceEditor.setTheme("ace/theme/clouds");
|
||||
result = jQuery.parseJSON(data.responseText);
|
||||
if(result.status == 'success'){
|
||||
// Save mtime
|
||||
$('#editor').attr('data-mtime', result.data.mtime);
|
||||
// Initialise the editor
|
||||
showControls(filename);
|
||||
$('table').fadeOut('slow', function() {
|
||||
$('#editor').text(result.data.filecontents);
|
||||
$('#editor').attr('data-dir', dir);
|
||||
$('#editor').attr('data-filename', filename);
|
||||
window.aceEditor = ace.edit("editor");
|
||||
aceEditor.setShowPrintMargin(false);
|
||||
if(result.data.write=='false'){
|
||||
aceEditor.setReadOnly(true);
|
||||
}
|
||||
setEditorSize();
|
||||
setSyntaxMode(getFileExtension(filename));
|
||||
OC.addScript('files_texteditor','aceeditor/theme-clouds', function(){
|
||||
window.aceEditor.setTheme("ace/theme/clouds");
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Failed to get the file.
|
||||
alert(result.data.message);
|
||||
}
|
||||
// End success
|
||||
}
|
||||
// End ajax
|
||||
|
|
Loading…
Reference in a new issue