diff options
24 files changed, 882 insertions, 1035 deletions
diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 8c1aad8668c..d224e79d01b 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -77,6 +77,12 @@ if($source) { exit(); } else { $success = false; + if (!$content) { + $templateManager = OC_Helper::getFileTemplateManager(); + $mimeType = OC_Helper::getMimeType($target); + $content = $templateManager->getTemplate($mimeType); + } + if($content) { $success = \OC\Files\Filesystem::file_put_contents($target, $content); } else { @@ -87,9 +93,11 @@ if($source) { $meta = \OC\Files\Filesystem::getFileInfo($target); $id = $meta['fileid']; $mime = $meta['mimetype']; + $size = $meta['size']; OCP\JSON::success(array('data' => array( 'id' => $id, 'mime' => $mime, + 'size' => $size, 'content' => $content, ))); exit(); diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index 99739cb4cee..aa839b81d18 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -5,11 +5,11 @@ $l = OC_L10N::get('files'); OCP\App::registerAdmin('files', 'admin'); -OCP\App::addNavigationEntry( array( "id" => "files_index", - "order" => 0, - "href" => OCP\Util::linkTo( "files", "index.php" ), - "icon" => OCP\Util::imagePath( "core", "places/files.svg" ), - "name" => $l->t("Files") )); +OCP\App::addNavigationEntry(array("id" => "files_index", + "order" => 0, + "href" => OCP\Util::linkTo("files", "index.php"), + "icon" => OCP\Util::imagePath("core", "places/files.svg"), + "name" => $l->t("Files"))); OC_Search::registerProvider('OC_Search_Provider_File'); @@ -21,3 +21,7 @@ OC_Search::registerProvider('OC_Search_Provider_File'); \OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); \OCP\BackgroundJob::addRegularTask('\OC\Files\Cache\BackgroundWatcher', 'checkNext'); + +$templateManager = OC_Helper::getFileTemplateManager(); +$templateManager->registerTemplate('text/html', 'core/templates/filetemplates/template.html'); + diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 942a07dfccc..0eddd7e9cd7 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -1,343 +1,345 @@ $(document).ready(function() { - file_upload_param = { - dropZone: $('#content'), // restrict dropZone to content div - //singleFileUploads is on by default, so the data.files array will always have length 1 - add: function(e, data) { + file_upload_param = { + dropZone: $('#content'), // restrict dropZone to content div + //singleFileUploads is on by default, so the data.files array will always have length 1 + add: function(e, data) { - if(data.files[0].type === '' && data.files[0].size == 4096) - { - data.textStatus = 'dirorzero'; - data.errorThrown = t('files','Unable to upload your file as it is a directory or has 0 bytes'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - return true; //don't upload this file but go on with next in queue - } + if(data.files[0].type === '' && data.files[0].size == 4096) + { + data.textStatus = 'dirorzero'; + data.errorThrown = t('files','Unable to upload your file as it is a directory or has 0 bytes'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + return true; //don't upload this file but go on with next in queue + } - var totalSize=0; - $.each(data.originalFiles, function(i,file){ - totalSize+=file.size; - }); + var totalSize=0; + $.each(data.originalFiles, function(i,file){ + totalSize+=file.size; + }); - if(totalSize>$('#max_upload').val()){ - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files','Not enough space available'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - return false; //don't upload anything - } + if(totalSize>$('#max_upload').val()){ + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files','Not enough space available'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything + } - // start the actual file upload - var jqXHR = data.submit(); + // start the actual file upload + var jqXHR = data.submit(); - // remember jqXHR to show warning to user when he navigates away but an upload is still in progress - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - if(typeof uploadingFiles[dirName] === 'undefined') { - uploadingFiles[dirName] = {}; - } - uploadingFiles[dirName][data.files[0].name] = jqXHR; - } else { - uploadingFiles[data.files[0].name] = jqXHR; - } + // remember jqXHR to show warning to user when he navigates away but an upload is still in progress + if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { + var dirName = data.context.data('file'); + if(typeof uploadingFiles[dirName] === 'undefined') { + uploadingFiles[dirName] = {}; + } + uploadingFiles[dirName][data.files[0].name] = jqXHR; + } else { + uploadingFiles[data.files[0].name] = jqXHR; + } - //show cancel button - if($('html.lte9').length === 0 && data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').show(); - } - }, - /** - * called after the first add, does NOT have the data param - * @param e - */ - start: function(e) { - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - }, - fail: function(e, data) { - if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { - if (data.textStatus === 'abort') { - $('#notification').text(t('files', 'Upload cancelled.')); - } else { - // HTTP connection problem - $('#notification').text(data.errorThrown); - } - $('#notification').fadeIn(); - //hide notification after 5 sec - setTimeout(function() { - $('#notification').fadeOut(); - }, 5000); - } - delete uploadingFiles[data.files[0].name]; - }, - progress: function(e, data) { - // TODO: show nice progress bar in file row - }, - progressall: function(e, data) { - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } - var progress = (data.loaded/data.total)*100; - $('#uploadprogressbar').progressbar('value',progress); - }, - /** - * called for every successful upload - * @param e - * @param data - */ - done:function(e, data) { - // handle different responses (json or body from iframe for ie) - var response; - if (typeof data.result === 'string') { - response = data.result; - } else { - //fetch response from iframe - response = data.result[0].body.innerText; - } - var result=$.parseJSON(response); + //show cancel button + if($('html.lte9').length === 0 && data.dataType !== 'iframe') { + $('#uploadprogresswrapper input.stop').show(); + } + }, + /** + * called after the first add, does NOT have the data param + * @param e + */ + start: function(e) { + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + return; + } + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + }, + fail: function(e, data) { + if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { + if (data.textStatus === 'abort') { + $('#notification').text(t('files', 'Upload cancelled.')); + } else { + // HTTP connection problem + $('#notification').text(data.errorThrown); + } + $('#notification').fadeIn(); + //hide notification after 5 sec + setTimeout(function() { + $('#notification').fadeOut(); + }, 5000); + } + delete uploadingFiles[data.files[0].name]; + }, + progress: function(e, data) { + // TODO: show nice progress bar in file row + }, + progressall: function(e, data) { + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + return; + } + var progress = (data.loaded/data.total)*100; + $('#uploadprogressbar').progressbar('value',progress); + }, + /** + * called for every successful upload + * @param e + * @param data + */ + done:function(e, data) { + // handle different responses (json or body from iframe for ie) + var response; + if (typeof data.result === 'string') { + response = data.result; + } else { + //fetch response from iframe + response = data.result[0].body.innerText; + } + var result=$.parseJSON(response); - if(typeof result[0] !== 'undefined' && result[0].status === 'success') { - var file = result[0]; - } else { - data.textStatus = 'servererror'; - data.errorThrown = t('files', result.data.message); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } + if(typeof result[0] !== 'undefined' && result[0].status === 'success') { + var file = result[0]; + } else { + data.textStatus = 'servererror'; + data.errorThrown = t('files', result.data.message); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } - var filename = result[0].originalname; + var filename = result[0].originalname; - // delete jqXHR reference - if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { - var dirName = data.context.data('file'); - delete uploadingFiles[dirName][filename]; - if ($.assocArraySize(uploadingFiles[dirName]) == 0) { - delete uploadingFiles[dirName]; - } - } else { - delete uploadingFiles[filename]; - } + // delete jqXHR reference + if (typeof data.context !== 'undefined' && data.context.data('type') === 'dir') { + var dirName = data.context.data('file'); + delete uploadingFiles[dirName][filename]; + if ($.assocArraySize(uploadingFiles[dirName]) == 0) { + delete uploadingFiles[dirName]; + } + } else { + delete uploadingFiles[filename]; + } - }, - /** - * called after last upload - * @param e - * @param data - */ - stop: function(e, data) { - if(data.dataType !== 'iframe') { - $('#uploadprogresswrapper input.stop').hide(); - } + }, + /** + * called after last upload + * @param e + * @param data + */ + stop: function(e, data) { + if(data.dataType !== 'iframe') { + $('#uploadprogresswrapper input.stop').hide(); + } - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - return; - } + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + return; + } - $('#uploadprogressbar').progressbar('value',100); - $('#uploadprogressbar').fadeOut(); + $('#uploadprogressbar').progressbar('value',100); + $('#uploadprogressbar').fadeOut(); + } } - } - var file_upload_handler = function() { - $('#file_upload_start').fileupload(file_upload_param); - }; + var file_upload_handler = function() { + $('#file_upload_start').fileupload(file_upload_param); + }; - if ( document.getElementById('data-upload-form') ) { - $(file_upload_handler); - } - $.assocArraySize = function(obj) { - // http://stackoverflow.com/a/6700/11236 - var size = 0, key; - for (key in obj) { - if (obj.hasOwnProperty(key)) size++; + if ( document.getElementById('data-upload-form') ) { + $(file_upload_handler); } - return size; - }; - - // warn user not to leave the page while upload is in progress - $(window).bind('beforeunload', function(e) { - if ($.assocArraySize(uploadingFiles) > 0) - return t('files','File upload is in progress. Leaving the page now will cancel the upload.'); - }); + $.assocArraySize = function(obj) { + // http://stackoverflow.com/a/6700/11236 + var size = 0, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) size++; + } + return size; + }; - //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) - if(navigator.userAgent.search(/konqueror/i)==-1){ - $('#file_upload_start').attr('multiple','multiple') - } + // warn user not to leave the page while upload is in progress + $(window).bind('beforeunload', function(e) { + if ($.assocArraySize(uploadingFiles) > 0) + return t('files','File upload is in progress. Leaving the page now will cancel the upload.'); + }); - //if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder - var crumb=$('div.crumb').first(); - while($('div.controls').height()>40 && crumb.next('div.crumb').length>0){ - crumb.children('a').text('...'); - crumb=crumb.next('div.crumb'); - } - //if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent - var crumb=$('div.crumb').first(); - var next=crumb.next('div.crumb'); - while($('div.controls').height()>40 && next.next('div.crumb').length>0){ - crumb.remove(); - crumb=next; - next=crumb.next('div.crumb'); - } - //still not enough, start shorting down the current folder name - var crumb=$('div.crumb>a').last(); - while($('div.controls').height()>40 && crumb.text().length>6){ - var text=crumb.text() - text=text.substr(0,text.length-6)+'...'; - crumb.text(text); - } + //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) + if(navigator.userAgent.search(/konqueror/i)==-1){ + $('#file_upload_start').attr('multiple','multiple') + } - $(document).click(function(){ - $('#new>ul').hide(); - $('#new').removeClass('active'); - $('#new li').each(function(i,element){ - if($(element).children('p').length==0){ - $(element).children('form').remove(); - $(element).append('<p>'+$(element).data('text')+'</p>'); - } - }); - }); - $('#new li').click(function(){ - if($(this).children('p').length==0){ - return; + //if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder + var crumb=$('div.crumb').first(); + while($('div.controls').height()>40 && crumb.next('div.crumb').length>0){ + crumb.children('a').text('...'); + crumb=crumb.next('div.crumb'); + } + //if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent + var crumb=$('div.crumb').first(); + var next=crumb.next('div.crumb'); + while($('div.controls').height()>40 && next.next('div.crumb').length>0){ + crumb.remove(); + crumb=next; + next=crumb.next('div.crumb'); + } + //still not enough, start shorting down the current folder name + var crumb=$('div.crumb>a').last(); + while($('div.controls').height()>40 && crumb.text().length>6){ + var text=crumb.text() + text=text.substr(0,text.length-6)+'...'; + crumb.text(text); } - $('#new li').each(function(i,element){ - if($(element).children('p').length==0){ - $(element).children('form').remove(); - $(element).append('<p>'+$(element).data('text')+'</p>'); - } + $(document).click(function(){ + $('#new>ul').hide(); + $('#new').removeClass('active'); + $('#new li').each(function(i,element){ + if($(element).children('p').length==0){ + $(element).children('form').remove(); + $(element).append('<p>'+$(element).data('text')+'</p>'); + } + }); }); + $('#new li').click(function(){ + if($(this).children('p').length==0){ + return; + } - var type=$(this).data('type'); - var text=$(this).children('p').text(); - $(this).data('text',text); - $(this).children('p').remove(); - var form=$('<form></form>'); - var input=$('<input>'); - form.append(input); - $(this).append(form); - input.focus(); - form.submit(function(event){ - event.stopPropagation(); - event.preventDefault(); - var newname=input.val(); - if(type == 'web' && newname.length == 0) { - OC.Notification.show(t('files', 'URL cannot be empty.')); - return false; - } else if (type != 'web' && !Files.isFileNameValid(newname)) { - return false; - } else if( type == 'folder' && $('#dir').val() == '/' && newname == 'Shared') { - OC.Notification.show(t('files','Invalid folder name. Usage of \'Shared\' is reserved by ownCloud')); - return false; - } - if (FileList.lastAction) { - FileList.lastAction(); - } - var name = getUniqueName(newname); - if (newname != name) { - FileList.checkName(name, newname, true); - var hidden = true; - } else { - var hidden = false; - } - switch(type){ - case 'file': - $.post( - OC.filePath('files','ajax','newfile.php'), - {dir:$('#dir').val(),filename:name}, - function(result){ - if (result.status == 'success') { - var date=new Date(); - FileList.addFile(name,0,date,false,hidden); - var tr=$('tr').filterAttr('data-file',name); - tr.attr('data-mime',result.data.mime); - tr.attr('data-id', result.data.id); - getMimeIcon(result.data.mime,function(path){ - tr.find('td.filename').attr('style','background-image:url('+path+')'); - }); - } else { - OC.dialogs.alert(result.data.message, t('core', 'Error')); + $('#new li').each(function(i,element){ + if($(element).children('p').length==0){ + $(element).children('form').remove(); + $(element).append('<p>'+$(element).data('text')+'</p>'); + } + }); + + var type=$(this).data('type'); + var text=$(this).children('p').text(); + $(this).data('text',text); + $(this).children('p').remove(); + var form=$('<form></form>'); + var input=$('<input>'); + form.append(input); + $(this).append(form); + input.focus(); + form.submit(function(event){ + event.stopPropagation(); + event.preventDefault(); + var newname=input.val(); + if(type == 'web' && newname.length == 0) { + OC.Notification.show(t('files', 'URL cannot be empty.')); + return false; + } else if (type != 'web' && !Files.isFileNameValid(newname)) { + return false; + } else if( type == 'folder' && $('#dir').val() == '/' && newname == 'Shared') { + OC.Notification.show(t('files','Invalid folder name. Usage of \'Shared\' is reserved by ownCloud')); + return false; + } + if (FileList.lastAction) { + FileList.lastAction(); } - } - ); - break; - case 'folder': - $.post( - OC.filePath('files','ajax','newfolder.php'), - {dir:$('#dir').val(),foldername:name}, - function(result){ - if (result.status == 'success') { - var date=new Date(); - FileList.addDir(name,0,date,hidden); - var tr=$('tr').filterAttr('data-file',name); - tr.attr('data-id', result.data.id); + var name = getUniqueName(newname); + if (newname != name) { + FileList.checkName(name, newname, true); + var hidden = true; } else { - OC.dialogs.alert(result.data.message, t('core', 'Error')); + var hidden = false; } - } - ); - break; - case 'web': - if(name.substr(0,8)!='https://' && name.substr(0,7)!='http://'){ - name='http://'+name; - } - var localName=name; - if(localName.substr(localName.length-1,1)=='/'){//strip / - localName=localName.substr(0,localName.length-1) - } - if(localName.indexOf('/')){//use last part of url - localName=localName.split('/').pop(); - } else { //or the domain - localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); - } - localName = getUniqueName(localName); - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - } else { - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - } + switch(type){ + case 'file': + $.post( + OC.filePath('files','ajax','newfile.php'), + {dir:$('#dir').val(),filename:name}, + function(result){ + if (result.status == 'success') { + var date=new Date(); + FileList.addFile(name,0,date,false,hidden); + var tr=$('tr').filterAttr('data-file',name); + tr.attr('data-size',result.data.size); + tr.attr('data-mime',result.data.mime); + tr.attr('data-id', result.data.id); + tr.find('.filesize').text(humanFileSize(result.data.size)); + getMimeIcon(result.data.mime,function(path){ + tr.find('td.filename').attr('style','background-image:url('+path+')'); + }); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Error')); + } + } + ); + break; + case 'folder': + $.post( + OC.filePath('files','ajax','newfolder.php'), + {dir:$('#dir').val(),foldername:name}, + function(result){ + if (result.status == 'success') { + var date=new Date(); + FileList.addDir(name,0,date,hidden); + var tr=$('tr').filterAttr('data-file',name); + tr.attr('data-id', result.data.id); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Error')); + } + } + ); + break; + case 'web': + if(name.substr(0,8)!='https://' && name.substr(0,7)!='http://'){ + name='http://'+name; + } + var localName=name; + if(localName.substr(localName.length-1,1)=='/'){//strip / + localName=localName.substr(0,localName.length-1) + } + if(localName.indexOf('/')){//use last part of url + localName=localName.split('/').pop(); + } else { //or the domain + localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); + } + localName = getUniqueName(localName); + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + } else { + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + } - var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); - eventSource.listen('progress',function(progress){ - //IE < 10 does not fire the necessary events for the progress bar. - if($('html.lte9').length > 0) { - } else { - $('#uploadprogressbar').progressbar('value',progress); - } - }); - eventSource.listen('success',function(data){ - var mime=data.mime; - var size=data.size; - var id=data.id; - $('#uploadprogressbar').fadeOut(); - var date=new Date(); - FileList.addFile(localName,size,date,false,hidden); - var tr=$('tr').filterAttr('data-file',localName); - tr.data('mime',mime).data('id',id); - tr.attr('data-id', id); - getMimeIcon(mime,function(path){ - tr.find('td.filename').attr('style','background-image:url('+path+')'); - }); - }); - eventSource.listen('error',function(error){ - $('#uploadprogressbar').fadeOut(); - alert(error); + var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); + eventSource.listen('progress',function(progress){ + //IE < 10 does not fire the necessary events for the progress bar. + if($('html.lte9').length > 0) { + } else { + $('#uploadprogressbar').progressbar('value',progress); + } + }); + eventSource.listen('success',function(data){ + var mime=data.mime; + var size=data.size; + var id=data.id; + $('#uploadprogressbar').fadeOut(); + var date=new Date(); + FileList.addFile(localName,size,date,false,hidden); + var tr=$('tr').filterAttr('data-file',localName); + tr.data('mime',mime).data('id',id); + tr.attr('data-id', id); + getMimeIcon(mime,function(path){ + tr.find('td.filename').attr('style','background-image:url('+path+')'); + }); + }); + eventSource.listen('error',function(error){ + $('#uploadprogressbar').fadeOut(); + alert(error); + }); + break; + } + var li=form.parent(); + form.remove(); + li.append('<p>'+li.data('text')+'</p>'); + $('#new>a').click(); }); - break; - } - var li=form.parent(); - form.remove(); - li.append('<p>'+li.data('text')+'</p>'); - $('#new>a').click(); }); - }); }); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 53fc25f41b0..e1c53184dd1 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -365,7 +365,9 @@ $(document).ready(function() { FileList.addFile(name,0,date,false,hidden); var tr=$('tr').filterAttr('data-file',name); tr.attr('data-mime',result.data.mime); + tr.attr('data-size',result.data.size); tr.attr('data-id', result.data.id); + tr.find('.filesize').text(humanFileSize(result.data.size)); getMimeIcon(result.data.mime,function(path){ tr.find('td.filename').attr('style','background-image:url('+path+')'); }); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 07da839e8a2..a37bd5728c1 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -30,9 +30,6 @@ use OC\Files\Filesystem; */
class Hooks {
- // TODO: use passphrase for encrypting private key that is separate to
- // the login password
-
/**
* @brief Startup encryption backend upon user login
* @note This method should never be called for users using client side encryption
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index c3e88e5944e..3947b7d0c3b 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -25,7 +25,6 @@ namespace OCA\Encryption;
-//require_once '../3rdparty/Crypt_Blowfish/Blowfish.php';
require_once realpath(dirname(__FILE__) . '/../3rdparty/Crypt_Blowfish/Blowfish.php');
/**
@@ -86,7 +85,7 @@ class Crypt { * blocks with encryption alone, hence padding is added to achieve the
* required length.
*/
- public static function addPadding($data) {
+ private static function addPadding($data) {
$padded = $data . 'xx';
@@ -99,7 +98,7 @@ class Crypt { * @param string $padded padded data to remove padding from
* @return string unpadded data on success, false on error
*/
- public static function removePadding($padded) {
+ private static function removePadding($padded) {
if (substr($padded, -2) === 'xx') {
@@ -207,7 +206,7 @@ class Crypt { * @param string $passphrase
* @return string encrypted file content
*/
- public static function encrypt($plainContent, $iv, $passphrase = '') {
+ private static function encrypt($plainContent, $iv, $passphrase = '') {
if ($encryptedContent = openssl_encrypt($plainContent, 'AES-128-CFB', $passphrase, false, $iv)) {
return $encryptedContent;
@@ -228,7 +227,7 @@ class Crypt { * @throws \Exception
* @return string decrypted file content
*/
- public static function decrypt($encryptedContent, $iv, $passphrase) {
+ private static function decrypt($encryptedContent, $iv, $passphrase) {
if ($plainContent = openssl_decrypt($encryptedContent, 'AES-128-CFB', $passphrase, false, $iv)) {
@@ -248,7 +247,7 @@ class Crypt { * @param string $iv IV to be concatenated
* @returns string concatenated content
*/
- public static function concatIv($content, $iv) {
+ private static function concatIv($content, $iv) {
$combined = $content . '00iv00' . $iv;
@@ -261,7 +260,7 @@ class Crypt { * @param string $catFile concatenated data to be split
* @returns array keys: encrypted, iv
*/
- public static function splitIv($catFile) {
+ private static function splitIv($catFile) {
// Fetch encryption metadata from end of file
$meta = substr($catFile, -22);
@@ -378,34 +377,6 @@ class Crypt { }
-
- /**
- * @brief Creates symmetric keyfile content using a generated key
- * @param string $plainContent content to be encrypted
- * @returns array keys: key, encrypted
- * @note symmetricDecryptFileContent() can be used to decrypt files created using this method
- *
- * This function decrypts a file
- */
- public static function symmetricEncryptFileContentKeyfile($plainContent) {
-
- $key = self::generateKey();
-
- if ($encryptedContent = self::symmetricEncryptFileContent($plainContent, $key)) {
-
- return array(
- 'key' => $key,
- 'encrypted' => $encryptedContent
- );
-
- } else {
-
- return false;
-
- }
-
- }
-
/**
* @brief Create asymmetrically encrypted keyfile content using a generated key
* @param string $plainContent content to be encrypted
@@ -489,42 +460,10 @@ class Crypt { }
/**
- * @brief Asymetrically encrypt a string using a public key
- * @param $plainContent
- * @param $publicKey
- * @return string encrypted file
- */
- public static function keyEncrypt($plainContent, $publicKey) {
-
- openssl_public_encrypt($plainContent, $encryptedContent, $publicKey);
-
- return $encryptedContent;
-
- }
-
- /**
- * @brief Asymetrically decrypt a file using a private key
- * @param $encryptedContent
- * @param $privatekey
- * @return string decrypted file
- */
- public static function keyDecrypt($encryptedContent, $privatekey) {
-
- $result = @openssl_private_decrypt($encryptedContent, $plainContent, $privatekey);
-
- if ($result) {
- return $plainContent;
- }
-
- return $result;
-
- }
-
- /**
* @brief Generates a pseudo random initialisation vector
* @return String $iv generated IV
*/
- public static function generateIv() {
+ private static function generateIv() {
if ($random = openssl_random_pseudo_bytes(12, $strong)) {
@@ -550,7 +489,7 @@ class Crypt { }
/**
- * @brief Generate a pseudo random 1024kb ASCII key
+ * @brief Generate a pseudo random 1024kb ASCII key, used as file key
* @returns $key Generated key
*/
public static function generateKey() {
@@ -576,13 +515,13 @@ class Crypt { }
/**
- * @brief Get the blowfish encryption handeler for a key
+ * @brief Get the blowfish encryption handler for a key
* @param $key string (optional)
* @return \Crypt_Blowfish blowfish object
*
- * if the key is left out, the default handeler will be used
+ * if the key is left out, the default handler will be used
*/
- public static function getBlowfish($key = '') {
+ private static function getBlowfish($key = '') {
if ($key) {
@@ -597,38 +536,6 @@ class Crypt { }
/**
- * @param $passphrase
- * @return mixed
- */
- public static function legacyCreateKey($passphrase) {
-
- // Generate a random integer
- $key = mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999);
-
- // Encrypt the key with the passphrase
- $legacyEncKey = self::legacyEncrypt($key, $passphrase);
-
- return $legacyEncKey;
-
- }
-
- /**
- * @brief encrypts content using legacy blowfish system
- * @param string $content the cleartext message you want to encrypt
- * @param string $passphrase
- * @returns string encrypted content
- *
- * This function encrypts an content
- */
- public static function legacyEncrypt($content, $passphrase = '') {
-
- $bf = self::getBlowfish($passphrase);
-
- return $bf->encrypt($content);
-
- }
-
- /**
* @brief decrypts content using legacy blowfish system
* @param string $content the cleartext message you want to decrypt
* @param string $passphrase
@@ -665,4 +572,4 @@ class Crypt { }
}
-}
\ No newline at end of file +}
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 50e823585d7..c6fc134fe42 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -21,30 +21,6 @@ * */ -# Bugs -# ---- -# Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer -# Sharing all files to admin for recovery purposes still in progress -# Possibly public links are broken (not tested since last merge of master) - - -# Missing features -# ---------------- -# Make sure user knows if large files weren't encrypted - - -# Test -# ---- -# Test that writing files works when recovery is enabled, and sharing API is disabled -# Test trashbin support - - -// Old Todo: -// - Crypt/decrypt button in the userinterface -// - Setting if crypto should be on by default -// - Add a setting "Don´t encrypt files larger than xx because of performance -// reasons" - namespace OCA\Encryption; /** @@ -57,45 +33,6 @@ namespace OCA\Encryption; class Util { - // Web UI: - - //// DONE: files created via web ui are encrypted - //// DONE: file created & encrypted via web ui are readable in web ui - //// DONE: file created & encrypted via web ui are readable via webdav - - - // WebDAV: - - //// DONE: new data filled files added via webdav get encrypted - //// DONE: new data filled files added via webdav are readable via webdav - //// DONE: reading unencrypted files when encryption is enabled works via - //// webdav - //// DONE: files created & encrypted via web ui are readable via webdav - - - // Legacy support: - - //// DONE: add method to check if file is encrypted using new system - //// DONE: add method to check if file is encrypted using old system - //// DONE: add method to fetch legacy key - //// DONE: add method to decrypt legacy encrypted data - - - // Admin UI: - - //// DONE: changing user password also changes encryption passphrase - - //// TODO: add support for optional recovery in case of lost passphrase / keys - //// TODO: add admin optional required long passphrase for users - //// TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. - - - // Integration testing: - - //// TODO: test new encryption with versioning - //// DONE: test new encryption with sharing - //// TODO: test new encryption with proxies - const MIGRATION_COMPLETED = 1; // migration to new encryption completed const MIGRATION_IN_PROGRESS = -1; // migration is running const MIGRATION_OPEN = 0; // user still needs to be migrated @@ -878,46 +815,22 @@ class Util { } /** - * @brief Decrypt a keyfile without knowing how it was encrypted + * @brief Decrypt a keyfile * @param string $filePath - * @param string $fileOwner * @param string $privateKey * @return bool|string - * @note Checks whether file was encrypted with openssl_seal or - * openssl_encrypt, and decrypts accrdingly - * @note This was used when 2 types of encryption for keyfiles was used, - * but now we've switched to exclusively using openssl_seal() */ - public function decryptUnknownKeyfile($filePath, $fileOwner, $privateKey) { + private function decryptKeyfile($filePath, $privateKey) { // Get the encrypted keyfile - // NOTE: the keyfile format depends on how it was encrypted! At - // this stage we don't know how it was encrypted $encKeyfile = Keymanager::getFileKey($this->view, $this->userId, $filePath); - // We need to decrypt the keyfile - // Has the file been shared yet? - if ( - $this->userId === $fileOwner - && !Keymanager::getShareKey($this->view, $this->userId, $filePath) // NOTE: we can't use isShared() here because it's a post share hook so it always returns true - ) { - - // The file has no shareKey, and its keyfile must be - // decrypted conventionally - $plainKeyfile = Crypt::keyDecrypt($encKeyfile, $privateKey); + // The file has a shareKey and must use it for decryption + $shareKey = Keymanager::getShareKey($this->view, $this->userId, $filePath); - - } else { - - // The file has a shareKey and must use it for decryption - $shareKey = Keymanager::getShareKey($this->view, $this->userId, $filePath); - - $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); - - } + $plainKeyfile = Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey); return $plainKeyfile; - } /** @@ -956,7 +869,7 @@ class Util { $fileOwner = \OC\Files\Filesystem::getOwner($filePath); // Decrypt keyfile - $plainKeyfile = $this->decryptUnknownKeyfile($filePath, $fileOwner, $privateKey); + $plainKeyfile = $this->decryptKeyfile($filePath, $privateKey); // Re-enc keyfile to (additional) sharekeys $multiEncKey = Crypt::multiKeyEncrypt($plainKeyfile, $userPubKeys); diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 9b97df22d16..2330a45be84 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -115,130 +115,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { } - /** - * @large - * @return String - */ - function testGenerateIv() { - - $iv = Encryption\Crypt::generateIv(); - - $this->assertEquals(16, strlen($iv)); - - return $iv; - - } - - /** - * @large - * @depends testGenerateIv - */ - function testConcatIv($iv) { - - $catFile = Encryption\Crypt::concatIv($this->dataLong, $iv); - - // Fetch encryption metadata from end of file - $meta = substr($catFile, -22); - - $identifier = substr($meta, 0, 6); - - // Fetch IV from end of file - $foundIv = substr($meta, 6); - - $this->assertEquals('00iv00', $identifier); - - $this->assertEquals($iv, $foundIv); - - // Remove IV and IV identifier text to expose encrypted content - $data = substr($catFile, 0, -22); - - $this->assertEquals($this->dataLong, $data); - - return array( - 'iv' => $iv - , - 'catfile' => $catFile - ); - - } - - /** - * @medium - * @depends testConcatIv - */ - function testSplitIv($testConcatIv) { - - // Split catfile into components - $splitCatfile = Encryption\Crypt::splitIv($testConcatIv['catfile']); - - // Check that original IV and split IV match - $this->assertEquals($testConcatIv['iv'], $splitCatfile['iv']); - - // Check that original data and split data match - $this->assertEquals($this->dataLong, $splitCatfile['encrypted']); - - } - - /** - * @medium - * @return string padded - */ - function testAddPadding() { - - $padded = Encryption\Crypt::addPadding($this->dataLong); - - $padding = substr($padded, -2); - - $this->assertEquals('xx', $padding); - - return $padded; - - } - - /** - * @medium - * @depends testAddPadding - */ - function testRemovePadding($padded) { - - $noPadding = Encryption\Crypt::RemovePadding($padded); - - $this->assertEquals($this->dataLong, $noPadding); - - } - - /** - * @medium - */ - function testEncrypt() { - - $random = openssl_random_pseudo_bytes(13); - - $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht - - $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat'); - - $this->assertNotEquals($this->dataUrl, $crypted); - - } - - /** - * @medium - */ - function testDecrypt() { - - $random = openssl_random_pseudo_bytes(13); - - $iv = substr(base64_encode($random), 0, -4); // i.e. E5IG033j+mRNKrht - - $crypted = Encryption\Crypt::encrypt($this->dataUrl, $iv, 'hat'); - - $decrypt = Encryption\Crypt::decrypt($crypted, $iv, 'hat'); - - $this->assertEquals($this->dataUrl, $decrypt); - - } - function testDecryptPrivateKey() { // test successful decrypt @@ -364,14 +240,12 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { //print_r($r); // Join IVs and their respective data chunks - $e = array( - $r[0] . $r[1], - $r[2] . $r[3], - $r[4] . $r[5], - $r[6] . $r[7], - $r[8] . $r[9], - $r[10] . $r[11] - ); //.$r[11], $r[12].$r[13], $r[14] ); + $e = array(); + $i = 0; + while ($i < count($r)-1) { + $e[] = $r[$i] . $r[$i+1]; + $i = $i + 2; + } //print_r($e); @@ -469,24 +343,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium */ - function testSymmetricEncryptFileContentKeyfile() { - - # TODO: search in keyfile for actual content as IV will ensure this test always passes - - $crypted = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->dataUrl); - - $this->assertNotEquals($this->dataUrl, $crypted['encrypted']); - - - $decrypt = Encryption\Crypt::symmetricDecryptFileContent($crypted['encrypted'], $crypted['key']); - - $this->assertEquals($this->dataUrl, $decrypt); - - } - - /** - * @medium - */ function testIsEncryptedContent() { $this->assertFalse(Encryption\Crypt::isCatfileContent($this->dataUrl)); @@ -528,47 +384,11 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - */ - function testKeyEncrypt() { - - // Generate keypair - $pair1 = Encryption\Crypt::createKeypair(); - - // Encrypt data - $crypted = Encryption\Crypt::keyEncrypt($this->dataUrl, $pair1['publicKey']); - - $this->assertNotEquals($this->dataUrl, $crypted); - - // Decrypt data - $decrypt = Encryption\Crypt::keyDecrypt($crypted, $pair1['privateKey']); - - $this->assertEquals($this->dataUrl, $decrypt); - - } - - /** - * @medium - * @brief test encryption using legacy blowfish method - */ - function testLegacyEncryptShort() { - - $crypted = Encryption\Crypt::legacyEncrypt($this->dataShort, $this->pass); - - $this->assertNotEquals($this->dataShort, $crypted); - - # TODO: search inencrypted text for actual content to ensure it - # genuine transformation - - return $crypted; - - } - - /** - * @medium * @brief test decryption using legacy blowfish method - * @depends testLegacyEncryptShort */ - function testLegacyDecryptShort($crypted) { + function testLegacyDecryptShort() { + + $crypted = $this->legacyEncrypt($this->dataShort, $this->pass); $decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass); @@ -578,53 +398,15 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test encryption using legacy blowfish method - */ - function testLegacyEncryptLong() { - - $crypted = Encryption\Crypt::legacyEncrypt($this->dataLong, $this->pass); - - $this->assertNotEquals($this->dataLong, $crypted); - - # TODO: search inencrypted text for actual content to ensure it - # genuine transformation - - return $crypted; - - } - - /** - * @medium * @brief test decryption using legacy blowfish method - * @depends testLegacyEncryptLong */ - function testLegacyDecryptLong($crypted) { + function testLegacyDecryptLong() { + + $crypted = $this->legacyEncrypt($this->dataLong, $this->pass); $decrypted = Encryption\Crypt::legacyBlockDecrypt($crypted, $this->pass); $this->assertEquals($this->dataLong, $decrypted); - - $this->assertFalse(Encryption\Crypt::getBlowfish('')); - } - - /** - * @medium - * @brief test generation of legacy encryption key - * @depends testLegacyDecryptShort - */ - function testLegacyCreateKey() { - - // Create encrypted key - $encKey = Encryption\Crypt::legacyCreateKey($this->pass); - - // Decrypt key - $key = Encryption\Crypt::legacyBlockDecrypt($encKey, $this->pass); - - $this->assertTrue(is_numeric($key)); - - // Check that key is correct length - $this->assertEquals(20, strlen($key)); - } /** @@ -871,4 +653,20 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // tear down $view->unlink($filename); } + + + /** + * @brief encryption using legacy blowfish method + * @param $data string data to encrypt + * @param $passwd string password + * @return string + */ + function legacyEncrypt($data, $passwd) { + + $bf = new \Crypt_Blowfish($passwd); + $crypted = $bf->encrypt($data); + + return $crypted; + } + } diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index b644856d95d..13f8c3197c7 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -141,10 +141,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { */ function testSetFileKey() { - # NOTE: This cannot be tested until we are able to break out - # of the FileSystemView data directory root - - $key = Encryption\Crypt::symmetricEncryptFileContentKeyfile($this->randomKey, 'hat'); + $key = $this->randomKey; $file = 'unittest-' . time() . '.txt'; @@ -152,24 +149,17 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - $this->view->file_put_contents($this->userId . '/files/' . $file, $key['encrypted']); + $this->view->file_put_contents($this->userId . '/files/' . $file, $this->dataShort); - // Re-enable proxy - our work is done - \OC_FileProxy::$enabled = $proxyStatus; + Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key); - //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' ); - Encryption\Keymanager::setFileKey($this->view, $file, $this->userId, $key['key']); - - // enable encryption proxy - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = true; + $this->assertTrue($this->view->file_exists('/' . $this->userId . '/files_encryption/keyfiles/' . $file . '.key')); // cleanup $this->view->unlink('/' . $this->userId . '/files/' . $file); // change encryption proxy to previous state \OC_FileProxy::$enabled = $proxyStatus; - } /** diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 70b8f30be5c..0b4699dc5c0 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -48,14 +48,14 @@ class Storage { /** * get current size of all versions from a given user - * + * * @param $user user who owns the versions * @return mixed versions size or false if no versions size is stored */ private static function getVersionsSize($user) { $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*files_versions` WHERE `user`=?'); $result = $query->execute(array($user))->fetchAll(); - + if ($result) { return $result[0]['size']; } @@ -64,7 +64,7 @@ class Storage { /** * write to the database how much space is in use for versions - * + * * @param $user owner of the versions * @param $size size of the versions */ @@ -76,20 +76,20 @@ class Storage { } $query->execute(array($size, $user)); } - + /** * store a new version of a file. */ public static function store($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { - + // if the file gets streamed we need to remove the .part extension // to get the right target $ext = pathinfo($filename, PATHINFO_EXTENSION); if ($ext === 'part') { $filename = substr($filename, 0, strlen($filename)-5); } - + list($uid, $filename) = self::getUidAndFilename($filename); $files_view = new \OC\Files\View('/'.$uid .'/files'); @@ -104,17 +104,12 @@ class Storage { // we should have a source file to work with, and the file shouldn't // be empty $fileExists = $files_view->file_exists($filename); - $fileSize = $files_view->filesize($filename); - if ($fileExists === false || $fileSize === 0) { + if (!($fileExists && $files_view->filesize($filename) > 0)) { return false; } // create all parent folders - $info=pathinfo($filename); - $versionsFolderName=$versions_view->getLocalFolder(''); - if(!file_exists($versionsFolderName.'/'.$info['dirname'])) { - mkdir($versionsFolderName.'/'.$info['dirname'], 0750, true); - } + self::createMissingDirectories($filename, $users_view); $versionsSize = self::getVersionsSize($uid); if ( $versionsSize === false || $versionsSize < 0 ) { @@ -174,7 +169,7 @@ class Storage { list($uidn, $newpath) = self::getUidAndFilename($new_path); $versions_view = new \OC\Files\View('/'.$uid .'/files_versions'); $files_view = new \OC\Files\View('/'.$uid .'/files'); - + // if the file already exists than it was a upload of a existing file // over the web interface -> store() is the right function we need here if ($files_view->file_exists($newpath)) { @@ -183,13 +178,12 @@ class Storage { self::expire($newpath); - $abs_newpath = $versions_view->getLocalFile($newpath); - if ( $files_view->is_dir($oldpath) && $versions_view->is_dir($oldpath) ) { $versions_view->rename($oldpath, $newpath); } else if ( ($versions = Storage::getVersions($uid, $oldpath)) ) { - $info=pathinfo($abs_newpath); - if(!file_exists($info['dirname'])) mkdir($info['dirname'], 0750, true); + // create missing dirs if necessary + self::createMissingDirectories($newpath, new \OC\Files\View('/'. $uidn)); + foreach ($versions as $v) { $versions_view->rename($oldpath.'.v'.$v['version'], $newpath.'.v'.$v['version']); } @@ -435,7 +429,7 @@ class Storage { } else { $quota = \OCP\Util::computerFileSize($quota); } - + // make sure that we have the current size of the version history if ( $versionsSize === null ) { $versionsSize = self::getVersionsSize($uid); @@ -568,4 +562,21 @@ class Storage { return $size; } + /** + * @brief create recursively missing directories + * @param string $filename $path to a file + * @param \OC\Files\View $view view on data/user/ + */ + private static function createMissingDirectories($filename, $view) { + $dirname = \OC_Filesystem::normalizePath(dirname($filename)); + $dirParts = explode('/', $dirname); + $dir = "/files_versions"; + foreach ($dirParts as $part) { + $dir = $dir . '/' . $part; + if (!$view->file_exists($dir)) { + $view->mkdir($dir); + } + } + } + } diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css index 185952e14bb..4e0ee31c7c4 100644 --- a/apps/user_ldap/css/settings.css +++ b/apps/user_ldap/css/settings.css @@ -3,14 +3,20 @@ max-width: 200px; display: inline-block; vertical-align: top; + text-align: right; padding-top: 9px; + padding-right: 5px; } #ldap fieldset input, #ldap fieldset textarea { - width: 70%; + width: 60%; display: inline-block; } +#ldap fieldset p input[type=checkbox] { + vertical-align: bottom; +} + .ldapIndent { margin-left: 50px; } diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 52d5dbc48d9..b86aac6da67 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -176,6 +176,13 @@ $(document).ready(function() { $('#ldap_submit').effect('highlight', {'color':'#A8FA87'}, 5000, function() { $('#ldap_submit').css('background', bgcolor); }); + //update the Label in the config chooser + caption = $('#ldap_serverconfig_chooser option:selected:first').text(); + pretext = '. Server: '; + caption = caption.slice(0, caption.indexOf(pretext) + pretext.length); + caption = caption + $('#ldap_host').val(); + $('#ldap_serverconfig_chooser option:selected:first').text(caption); + } else { $('#ldap_submit').css('background', '#fff'); $('#ldap_submit').effect('highlight', {'color':'#E97'}, 5000, function() { diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 0372112f0e2..e5d9b4d5b40 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -80,7 +80,12 @@ class Connection { public function __construct($configPrefix = '', $configID = 'user_ldap') { $this->configPrefix = $configPrefix; $this->configID = $configID; - $this->cache = \OC_Cache::getGlobalCache(); + $memcache = new \OC\Memcache\Factory(); + if($memcache->isAvailable()) { + $this->cache = $memcache->create(); + } else { + $this->cache = \OC_Cache::getGlobalCache(); + } $this->config['hasPagedResultSupport'] = (function_exists('ldap_control_paged_result') && function_exists('ldap_control_paged_result_response')); } diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index f65f466789f..4c9dd07a12c 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -71,6 +71,34 @@ class Helper { } /** + * + * @brief determines the host for every configured connection + * @return an array with configprefix as keys + * + */ + static public function getServerConfigurationHosts() { + $referenceConfigkey = 'ldap_host'; + + $query = ' + SELECT DISTINCT `configkey`, `configvalue` + FROM `*PREFIX*appconfig` + WHERE `appid` = \'user_ldap\' + AND `configkey` LIKE ? + '; + $query = \OCP\DB::prepare($query); + $configHosts = $query->execute(array('%'.$referenceConfigkey))->fetchAll(); + $result = array(); + + foreach($configHosts as $configHost) { + $len = strlen($configHost['configkey']) - strlen($referenceConfigkey); + $prefix = substr($configHost['configkey'], 0, $len); + $result[$prefix] = $configHost['configvalue']; + } + + return $result; + } + + /** * @brief deletes a given saved LDAP/AD server configuration. * @param string the configuration prefix of the config to delete * @return bool true on success, false otherwise diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 22e2dac6d26..7169192a18e 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -44,7 +44,9 @@ OCP\Util::addstyle('user_ldap', 'settings'); $tmpl = new OCP\Template('user_ldap', 'settings'); $prefixes = \OCA\user_ldap\lib\Helper::getServerConfigurationPrefixes(); +$hosts = \OCA\user_ldap\lib\Helper::getServerConfigurationHosts(); $tmpl->assign('serverConfigurationPrefixes', $prefixes); +$tmpl->assign('serverConfigurationHosts', $hosts); // assign default values if(!isset($ldap)) { diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 95aa592594b..e214d57fb1d 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -24,7 +24,7 @@ $sel = ' selected'; foreach($_['serverConfigurationPrefixes'] as $prefix) { ?> - <option value="<?php p($prefix); ?>"<?php p($sel); ?>><?php p($i++); ?>. Server</option> + <option value="<?php p($prefix); ?>"<?php p($sel); $sel = ''; ?>><?php p($i++); ?>. Server: <?php p($_['serverConfigurationHosts'][$prefix]); ?></option> <?php } } @@ -51,18 +51,15 @@ <p><label for="ldap_login_filter"><?php p($l->t('User Login Filter'));?></label> <input type="text" id="ldap_login_filter" name="ldap_login_filter" data-default="<?php p($_['ldap_login_filter_default']); ?>" - title="<?php p($l->t('Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action.'));?>" /> - <br /><small><?php p($l->t('use %%uid placeholder, e.g. "uid=%%uid"'));?></small></p> + title="<?php p($l->t('Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: "uid=%%uid"'));?>" /></p> <p><label for="ldap_userlist_filter"><?php p($l->t('User List Filter'));?></label> <input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" data-default="<?php p($_['ldap_userlist_filter_default']); ?>" - title="<?php p($l->t('Defines the filter to apply, when retrieving users.'));?>" /> - <br /><small><?php p($l->t('without any placeholder, e.g. "objectClass=person".'));?></small></p> + title="<?php p($l->t('Defines the filter to apply, when retrieving users (no placeholders). Example: "objectClass=person"'));?>" /></p> <p><label for="ldap_group_filter"><?php p($l->t('Group Filter'));?></label> <input type="text" id="ldap_group_filter" name="ldap_group_filter" data-default="<?php p($_['ldap_group_filter_default']); ?>" - title="<?php p($l->t('Defines the filter to apply, when retrieving groups.'));?>" /> - <br /><small><?php p($l->t('without any placeholder, e.g. "objectClass=posixGroup".'));?></small></p> + title="<?php p($l->t('Defines the filter to apply, when retrieving groups (no placeholders). Example: "objectClass=posixGroup"'));?>" /></p> </fieldset> <fieldset id="ldapSettings-2"> <div id="ldapAdvancedAccordion"> @@ -75,7 +72,7 @@ <p><label for="ldap_override_main_server"><?php p($l->t('Disable Main Server'));?></label><input type="checkbox" id="ldap_override_main_server" name="ldap_override_main_server" value="1" data-default="<?php p($_['ldap_override_main_server_default']); ?>" title="<?php p($l->t('Only connect to the replica server.'));?>" /></p> <p><label for="ldap_tls"><?php p($l->t('Use TLS'));?></label><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1" data-default="<?php p($_['ldap_tls_default']); ?>" title="<?php p($l->t('Do not use it additionally for LDAPS connections, it will fail.'));?>" /></p> <p><label for="ldap_nocase"><?php p($l->t('Case insensitve LDAP server (Windows)'));?></label><input type="checkbox" id="ldap_nocase" name="ldap_nocase" data-default="<?php p($_['ldap_nocase_default']); ?>" value="1"<?php if (isset($_['ldap_nocase']) && ($_['ldap_nocase'])) p(' checked'); ?>></p> - <p><label for="ldap_turn_off_cert_check"><?php p($l->t('Turn off SSL certificate validation.'));?></label><input type="checkbox" id="ldap_turn_off_cert_check" name="ldap_turn_off_cert_check" title="<?php p($l->t('If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', $theme->getName() ));?>" data-default="<?php p($_['ldap_turn_off_cert_check_default']); ?>" value="1"><br/><small><?php p($l->t('Not recommended, use for testing only.'));?></small></p> + <p><label for="ldap_turn_off_cert_check"><?php p($l->t('Turn off SSL certificate validation.'));?></label><input type="checkbox" id="ldap_turn_off_cert_check" name="ldap_turn_off_cert_check" title="<?php p($l->t('Not recommended, use it for testing only! If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', $theme->getName() ));?>" data-default="<?php p($_['ldap_turn_off_cert_check_default']); ?>" value="1"><br/></p> <p><label for="ldap_cache_ttl"><?php p($l->t('Cache Time-To-Live'));?></label><input type="number" id="ldap_cache_ttl" name="ldap_cache_ttl" title="<?php p($l->t('in seconds. A change empties the cache.'));?>" data-default="<?php p($_['ldap_cache_ttl_default']); ?>" /></p> </div> <h3><?php p($l->t('Directory Settings'));?></h3> diff --git a/core/css/styles.css b/core/css/styles.css index 2f08b58c04f..becf0af9056 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -196,11 +196,12 @@ input[type="submit"].enabled { background:#66f866; border:1px solid #5e5; -moz-b #body-login #datadirContent label, #body-login form input[type="checkbox"]+label { text-align: center; - color: #000; + color: #ccc; text-shadow: 0 1px 0 rgba(255,255,255,.1); - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; - filter: alpha(opacity=80); - opacity: .8; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; + filter: alpha(opacity=60); + opacity: .6; + text-shadow: 0 -1px 0 rgba(0,0,0,.5); } #body-login div.buttons { text-align:center; } @@ -307,6 +308,31 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } #body-login form .errors { background:#fed7d7; border:1px solid #f00; list-style-indent:inside; margin:0 0 2em; padding:1em; } #body-login .success { background:#d7fed7; border:1px solid #0f0; width: 35%; margin: 30px auto; padding:1em; text-align: center;} +#body-login #remember_login:hover+label, +#body-login #remember_login:focus+label { + color: #fff !important; +} + +#body-login #showAdvanced > img { + height: 16px; + width: 16px; + padding: 4px; + box-sizing: border-box; +} + +#body-login p.info a, #body-login #showAdvanced { + color: #ccc; +} + +#body-login p.info a:hover, #body-login p.info a:focus { + color: #fff; +} + + +#body-login p.info{ + white-space: nowrap; +} + /* Show password toggle */ #show, #dbpassword { position: absolute; diff --git a/core/js/js.js b/core/js/js.js index c2b81ae3272..d580b6113e6 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -69,7 +69,7 @@ function initL10N(app) { var code = 'var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) };'; t.plural_function = new Function("n", code); } else { - console.log("Syntax error in language file. Plural-Forms header is invalid ["+plural_forms+"]"); + console.log("Syntax error in language file. Plural-Forms header is invalid ["+t.plural_forms+"]"); } } } diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index f4bc174b5eb..5cbc8359d52 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -117,10 +117,6 @@ var OCdialogs = { text: t('core', 'Choose'), click: functionToCall, defaultButton: true - }, - { - text: t('core', 'Cancel'), - click: function(){self.$filePicker.ocdialog('close'); } }]; self.$filePicker.ocdialog({ diff --git a/core/templates/filetemplates/template.html b/core/templates/filetemplates/template.html new file mode 100644 index 00000000000..f16e80cb7ef --- /dev/null +++ b/core/templates/filetemplates/template.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> + <head> + + </head> + <body> + + </body> +</html> diff --git a/core/templates/installation.php b/core/templates/installation.php index 77c455304d3..8b087706801 100644 --- a/core/templates/installation.php +++ b/core/templates/installation.php @@ -62,7 +62,7 @@ </fieldset> <fieldset id="datadirField"> - <legend><a id="showAdvanced"><?php p($l->t( 'Advanced' )); ?> <img class="svg" src="<?php print_unescaped(image_path('', 'actions/caret-dark.svg')); ?>" /></a></legend> + <legend><a id="showAdvanced"><?php p($l->t( 'Advanced' )); ?> <img class="svg" src="<?php print_unescaped(image_path('', 'actions/caret.svg')); ?>" /></a></legend> <div id="datadirContent"> <label for="directory"><?php p($l->t( 'Data folder' )); ?></label> <input type="text" name="directory" id="directory" diff --git a/lib/files/type/detection.php b/lib/files/type/detection.php new file mode 100644 index 00000000000..242a81cb5a4 --- /dev/null +++ b/lib/files/type/detection.php @@ -0,0 +1,121 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Type; + +/** + * Class Detection + * + * Mimetype detection + * + * @package OC\Files\Type + */ +class Detection { + protected $mimetypes = array(); + + /** + * add an extension -> mimetype mapping + * + * @param string $extension + * @param string $mimetype + */ + public function registerType($extension, $mimetype) { + $this->mimetypes[$extension] = $mimetype; + } + + /** + * add an array of extension -> mimetype mappings + * + * @param array $types + */ + public function registerTypeArray($types) { + $this->mimetypes = array_merge($this->mimetypes, $types); + } + + /** + * detect mimetype only based on filename, content of file is not used + * + * @param string $path + * @return string + */ + public function detectPath($path) { + if (strpos($path, '.')) { + //try to guess the type by the file extension + $extension = strtolower(strrchr(basename($path), ".")); + $extension = substr($extension, 1); //remove leading . + return (isset($this->mimetypes[$extension])) ? $this->mimetypes[$extension] : 'application/octet-stream'; + } else { + return 'application/octet-stream'; + } + } + + /** + * detect mimetype based on both filename and content + * + * @param string $path + * @return string + */ + public function detect($path) { + $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://'); + + if (@is_dir($path)) { + // directories are easy + return "httpd/unix-directory"; + } + + $mimeType = $this->detectPath($path); + + if ($mimeType === 'application/octet-stream' and function_exists('finfo_open') + and function_exists('finfo_file') and $finfo = finfo_open(FILEINFO_MIME) + ) { + $info = @strtolower(finfo_file($finfo, $path)); + if ($info) { + $mimeType = substr($info, 0, strpos($info, ';')); + } + finfo_close($finfo); + } + if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) { + // use mime magic extension if available + $mimeType = mime_content_type($path); + } + if (!$isWrapped and $mimeType === 'application/octet-stream' && \OC_Helper::canExecute("file")) { + // it looks like we have a 'file' command, + // lets see if it does have mime support + $path = escapeshellarg($path); + $fp = popen("file -b --mime-type $path 2>/dev/null", "r"); + $reply = fgets($fp); + pclose($fp); + + //trim the newline + $mimeType = trim($reply); + + } + return $mimeType; + } + + /** + * detect mimetype based on the content of a string + * + * @param string $data + * @return string + */ + public function detectString($data) { + if (function_exists('finfo_open') and function_exists('finfo_file')) { + $finfo = finfo_open(FILEINFO_MIME); + return finfo_buffer($finfo, $data); + } else { + $tmpFile = \OC_Helper::tmpFile(); + $fh = fopen($tmpFile, 'wb'); + fwrite($fh, $data, 8024); + fclose($fh); + $mime = $this->detect($tmpFile); + unset($tmpFile); + return $mime; + } + } +} diff --git a/lib/files/type/templatemanager.php b/lib/files/type/templatemanager.php new file mode 100644 index 00000000000..cd1536d2732 --- /dev/null +++ b/lib/files/type/templatemanager.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Type; + +class TemplateManager { + protected $templates = array(); + + public function registerTemplate($mimetype, $path) { + $this->templates[$mimetype] = $path; + } + + /** + * get the path of the template for a mimetype + * + * @param string $mimetype + * @return string | null + */ + public function getTemplatePath($mimetype) { + if (isset($this->templates[$mimetype])) { + return $this->templates[$mimetype]; + } else { + return null; + } + } + + /** + * get the template content for a mimetype + * + * @param string $mimetype + * @return string + */ + public function getTemplate($mimetype) { + $path = $this->getTemplatePath($mimetype); + if ($path) { + return file_get_contents($path); + } else { + return ''; + } + } +} diff --git a/lib/helper.php b/lib/helper.php index 31f0f1698d5..51165193623 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -25,9 +25,10 @@ * Collection of useful functions */ class OC_Helper { - private static $mimetypes=array(); - private static $tmpFiles=array(); + private static $tmpFiles = array(); private static $mimetypeIcons = array(); + private static $mimetypeDetector; + private static $templateManager; /** * @brief Creates an url using a defined route @@ -39,7 +40,7 @@ class OC_Helper { * * Returns a url to the given app and file. */ - public static function linkToRoute( $route, $parameters = array() ) { + public static function linkToRoute($route, $parameters = array()) { $urlLinkTo = OC::getRouter()->generate($route, $parameters); return $urlLinkTo; } @@ -49,38 +50,35 @@ class OC_Helper { * @param string $app app * @param string $file file * @param array $args array with param=>value, will be appended to the returned url - * The value of $args will be urlencoded + * The value of $args will be urlencoded * @return string the url * * Returns a url to the given app and file. */ - public static function linkTo( $app, $file, $args = array() ) { - if( $app != '' ) { + public static function linkTo($app, $file, $args = array()) { + if ($app != '') { $app_path = OC_App::getAppPath($app); // Check if the app is in the app folder - if( $app_path && file_exists( $app_path.'/'.$file )) { - if(substr($file, -3) == 'php' || substr($file, -3) == 'css') { - $urlLinkTo = OC::$WEBROOT . '/index.php/apps/' . $app; - $urlLinkTo .= ($file!='index.php') ? '/' . $file : ''; - }else{ - $urlLinkTo = OC_App::getAppWebPath($app) . '/' . $file; + if ($app_path && file_exists($app_path . '/' . $file)) { + if (substr($file, -3) == 'php' || substr($file, -3) == 'css') { + $urlLinkTo = OC::$WEBROOT . '/index.php/apps/' . $app; + $urlLinkTo .= ($file != 'index.php') ? '/' . $file : ''; + } else { + $urlLinkTo = OC_App::getAppWebPath($app) . '/' . $file; } + } else { + $urlLinkTo = OC::$WEBROOT . '/' . $app . '/' . $file; } - else{ - $urlLinkTo = OC::$WEBROOT . '/' . $app . '/' . $file; - } - } - else{ - if( file_exists( OC::$SERVERROOT . '/core/'. $file )) { - $urlLinkTo = OC::$WEBROOT . '/core/'.$file; - } - else{ - $urlLinkTo = OC::$WEBROOT . '/'.$file; + } else { + if (file_exists(OC::$SERVERROOT . '/core/' . $file)) { + $urlLinkTo = OC::$WEBROOT . '/core/' . $file; + } else { + $urlLinkTo = OC::$WEBROOT . '/' . $file; } } if ($args && $query = http_build_query($args, '', '&')) { - $urlLinkTo .= '?'.$query; + $urlLinkTo .= '?' . $query; } return $urlLinkTo; @@ -91,13 +89,13 @@ class OC_Helper { * @param string $app app * @param string $file file * @param array $args array with param=>value, will be appended to the returned url - * The value of $args will be urlencoded + * The value of $args will be urlencoded * @return string the url * * Returns a absolute url to the given app and file. */ - public static function linkToAbsolute( $app, $file, $args = array() ) { - $urlLinkTo = self::linkTo( $app, $file, $args ); + public static function linkToAbsolute($app, $file, $args = array()) { + $urlLinkTo = self::linkTo($app, $file, $args); return self::makeURLAbsolute($urlLinkTo); } @@ -108,9 +106,8 @@ class OC_Helper { * * Returns a absolute url to the given app and file. */ - public static function makeURLAbsolute( $url ) - { - return OC_Request::serverProtocol(). '://' . OC_Request::serverHost() . $url; + public static function makeURLAbsolute($url) { + return OC_Request::serverProtocol() . '://' . OC_Request::serverHost() . $url; } /** @@ -120,8 +117,8 @@ class OC_Helper { * * Returns a url to the given service. */ - public static function linkToRemoteBase( $service ) { - return self::linkTo( '', 'remote.php') . '/' . $service; + public static function linkToRemoteBase($service) { + return self::linkTo('', 'remote.php') . '/' . $service; } /** @@ -132,9 +129,9 @@ class OC_Helper { * * Returns a absolute url to the given service. */ - public static function linkToRemote( $service, $add_slash = true ) { + public static function linkToRemote($service, $add_slash = true) { return self::makeURLAbsolute(self::linkToRemoteBase($service)) - . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); + . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : ''); } /** @@ -146,8 +143,8 @@ class OC_Helper { * Returns a absolute url to the given service. */ public static function linkToPublic($service, $add_slash = false) { - return self::linkToAbsolute( '', 'public.php') . '?service=' . $service - . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); + return self::linkToAbsolute('', 'public.php') . '?service=' . $service + . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : ''); } /** @@ -158,25 +155,25 @@ class OC_Helper { * * Returns the path to the image. */ - public static function imagePath( $app, $image ) { + public static function imagePath($app, $image) { // Read the selected theme from the config file $theme = OC_Util::getTheme(); // Check if the app is in the app folder - if( file_exists( OC::$SERVERROOT."/themes/$theme/apps/$app/img/$image" )) { - return OC::$WEBROOT."/themes/$theme/apps/$app/img/$image"; - }elseif( file_exists(OC_App::getAppPath($app)."/img/$image" )) { - return OC_App::getAppWebPath($app)."/img/$image"; - }elseif( !empty( $app ) and file_exists( OC::$SERVERROOT."/themes/$theme/$app/img/$image" )) { - return OC::$WEBROOT."/themes/$theme/$app/img/$image"; - }elseif( !empty( $app ) and file_exists( OC::$SERVERROOT."/$app/img/$image" )) { - return OC::$WEBROOT."/$app/img/$image"; - }elseif( file_exists( OC::$SERVERROOT."/themes/$theme/core/img/$image" )) { - return OC::$WEBROOT."/themes/$theme/core/img/$image"; - }elseif( file_exists( OC::$SERVERROOT."/core/img/$image" )) { - return OC::$WEBROOT."/core/img/$image"; - }else{ - throw new RuntimeException('image not found: image:'.$image.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + if (file_exists(OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { + return OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image"; + } elseif (file_exists(OC_App::getAppPath($app) . "/img/$image")) { + return OC_App::getAppWebPath($app) . "/img/$image"; + } elseif (!empty($app) and file_exists(OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) { + return OC::$WEBROOT . "/themes/$theme/$app/img/$image"; + } elseif (!empty($app) and file_exists(OC::$SERVERROOT . "/$app/img/$image")) { + return OC::$WEBROOT . "/$app/img/$image"; + } elseif (file_exists(OC::$SERVERROOT . "/themes/$theme/core/img/$image")) { + return OC::$WEBROOT . "/themes/$theme/core/img/$image"; + } elseif (file_exists(OC::$SERVERROOT . "/core/img/$image")) { + return OC::$WEBROOT . "/core/img/$image"; + } else { + throw new RuntimeException('image not found: image:' . $image . ' webroot:' . OC::$WEBROOT . ' serverroot:' . OC::$SERVERROOT); } } @@ -197,28 +194,28 @@ class OC_Helper { } // Replace slash and backslash with a minus $icon = str_replace('/', '-', $mimetype); - $icon = str_replace( '\\', '-', $icon); + $icon = str_replace('\\', '-', $icon); // Is it a dir? if ($mimetype === 'dir') { - self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/folder.png'; - return OC::$WEBROOT.'/core/img/filetypes/folder.png'; + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/folder.png'; + return OC::$WEBROOT . '/core/img/filetypes/folder.png'; } // Icon exists? - if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$icon.'.png')) { - self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png'; - return OC::$WEBROOT.'/core/img/filetypes/'.$icon.'.png'; + if (file_exists(OC::$SERVERROOT . '/core/img/filetypes/' . $icon . '.png')) { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/' . $icon . '.png'; + return OC::$WEBROOT . '/core/img/filetypes/' . $icon . '.png'; } // Try only the first part of the filetype $mimePart = substr($icon, 0, strpos($icon, '-')); - if (file_exists(OC::$SERVERROOT.'/core/img/filetypes/'.$mimePart.'.png')) { - self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png'; - return OC::$WEBROOT.'/core/img/filetypes/'.$mimePart.'.png'; + if (file_exists(OC::$SERVERROOT . '/core/img/filetypes/' . $mimePart . '.png')) { + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/' . $mimePart . '.png'; + return OC::$WEBROOT . '/core/img/filetypes/' . $mimePart . '.png'; } else { - self::$mimetypeIcons[$mimetype] = OC::$WEBROOT.'/core/img/filetypes/file.png'; - return OC::$WEBROOT.'/core/img/filetypes/file.png'; + self::$mimetypeIcons[$mimetype] = OC::$WEBROOT . '/core/img/filetypes/file.png'; + return OC::$WEBROOT . '/core/img/filetypes/file.png'; } } @@ -229,25 +226,25 @@ class OC_Helper { * * Makes 2048 to 2 kB. */ - public static function humanFileSize( $bytes ) { - if( $bytes < 0 ) { + public static function humanFileSize($bytes) { + if ($bytes < 0) { $l = OC_L10N::get('lib'); return "?"; } - if( $bytes < 1024 ) { + if ($bytes < 1024) { return "$bytes B"; } - $bytes = round( $bytes / 1024, 1 ); - if( $bytes < 1024 ) { + $bytes = round($bytes / 1024, 1); + if ($bytes < 1024) { return "$bytes kB"; } - $bytes = round( $bytes / 1024, 1 ); - if( $bytes < 1024 ) { + $bytes = round($bytes / 1024, 1); + if ($bytes < 1024) { return "$bytes MB"; } // Wow, heavy duty for owncloud - $bytes = round( $bytes / 1024, 1 ); + $bytes = round($bytes / 1024, 1); return "$bytes GB"; } @@ -260,21 +257,21 @@ class OC_Helper { * * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418 */ - public static function computerFileSize( $str ) { - $str=strtolower($str); + public static function computerFileSize($str) { + $str = strtolower($str); $bytes_array = array( 'b' => 1, 'k' => 1024, 'kb' => 1024, 'mb' => 1024 * 1024, - 'm' => 1024 * 1024, + 'm' => 1024 * 1024, 'gb' => 1024 * 1024 * 1024, - 'g' => 1024 * 1024 * 1024, + 'g' => 1024 * 1024 * 1024, 'tb' => 1024 * 1024 * 1024 * 1024, - 't' => 1024 * 1024 * 1024 * 1024, + 't' => 1024 * 1024 * 1024 * 1024, 'pb' => 1024 * 1024 * 1024 * 1024 * 1024, - 'p' => 1024 * 1024 * 1024 * 1024 * 1024, + 'p' => 1024 * 1024 * 1024 * 1024 * 1024, ); $bytes = floatval($str); @@ -299,18 +296,17 @@ class OC_Helper { return chmod($path, $filemode); $dh = opendir($path); while (($file = readdir($dh)) !== false) { - if($file != '.' && $file != '..') { - $fullpath = $path.'/'.$file; - if(is_link($fullpath)) + if ($file != '.' && $file != '..') { + $fullpath = $path . '/' . $file; + if (is_link($fullpath)) return false; - elseif(!is_dir($fullpath) && !@chmod($fullpath, $filemode)) - return false; - elseif(!self::chmodr($fullpath, $filemode)) + elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode)) + return false; elseif (!self::chmodr($fullpath, $filemode)) return false; } } closedir($dh); - if(@chmod($path, $filemode)) + if (@chmod($path, $filemode)) return true; else return false; @@ -323,8 +319,8 @@ class OC_Helper { * */ static function copyr($src, $dest) { - if(is_dir($src)) { - if(!is_dir($dest)) { + if (is_dir($src)) { + if (!is_dir($dest)) { mkdir($dest); } $files = scandir($src); @@ -333,7 +329,7 @@ class OC_Helper { self::copyr("$src/$file", "$dest/$file"); } } - }elseif(file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) { + } elseif (file_exists($src) && !\OC\Files\Filesystem::isFileBlacklisted($src)) { copy($src, $dest); } } @@ -344,105 +340,74 @@ class OC_Helper { * @return bool */ static function rmdirr($dir) { - if(is_dir($dir)) { - $files=scandir($dir); - foreach($files as $file) { + if (is_dir($dir)) { + $files = scandir($dir); + foreach ($files as $file) { if ($file != "." && $file != "..") { self::rmdirr("$dir/$file"); } } rmdir($dir); - }elseif(file_exists($dir)) { + } elseif (file_exists($dir)) { unlink($dir); } - if(file_exists($dir)) { + if (file_exists($dir)) { return false; - }else{ + } else { return true; } } /** + * @return \OC\Files\Type\Detection + */ + static public function getMimetypeDetector() { + if (!self::$mimetypeDetector) { + self::$mimetypeDetector = new \OC\Files\Type\Detection(); + self::$mimetypeDetector->registerTypeArray(include 'mimetypes.list.php'); + } + return self::$mimetypeDetector; + } + + /** + * @return \OC\Files\Type\TemplateManager + */ + static public function getFileTemplateManager() { + if (!self::$templateManager) { + self::$templateManager = new \OC\Files\Type\TemplateManager(); + } + return self::$templateManager; + } + + /** * Try to guess the mimetype based on filename * * @param string $path * @return string */ - static public function getFileNameMimeType($path){ - if(strpos($path, '.')) { - //try to guess the type by the file extension - if(!self::$mimetypes || self::$mimetypes != include 'mimetypes.list.php') { - self::$mimetypes=include 'mimetypes.list.php'; - } - $extension=strtolower(strrchr(basename($path), ".")); - $extension=substr($extension, 1);//remove leading . - return (isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream'; - }else{ - return 'application/octet-stream'; - } + static public function getFileNameMimeType($path) { + return self::getMimetypeDetector()->detectPath($path); } /** * get the mimetype form a local file + * * @param string $path * @return string * does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead */ static function getMimeType($path) { - $isWrapped=(strpos($path, '://')!==false) and (substr($path, 0, 7)=='file://'); - - if (@is_dir($path)) { - // directories are easy - return "httpd/unix-directory"; - } - - $mimeType = self::getFileNameMimeType($path); - - if($mimeType=='application/octet-stream' and function_exists('finfo_open') - and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)) { - $info = @strtolower(finfo_file($finfo, $path)); - if($info) { - $mimeType=substr($info, 0, strpos($info, ';')); - } - finfo_close($finfo); - } - if (!$isWrapped and $mimeType=='application/octet-stream' && function_exists("mime_content_type")) { - // use mime magic extension if available - $mimeType = mime_content_type($path); - } - if (!$isWrapped and $mimeType=='application/octet-stream' && OC_Helper::canExecute("file")) { - // it looks like we have a 'file' command, - // lets see if it does have mime support - $path=escapeshellarg($path); - $fp = popen("file -b --mime-type $path 2>/dev/null", "r"); - $reply = fgets($fp); - pclose($fp); - - //trim the newline - $mimeType = trim($reply); - - } - return $mimeType; + return self::getMimetypeDetector()->detect($path); } /** * get the mimetype form a data string + * * @param string $data * @return string */ static function getStringMimeType($data) { - if(function_exists('finfo_open') and function_exists('finfo_file')) { - $finfo=finfo_open(FILEINFO_MIME); - return finfo_buffer($finfo, $data); - }else{ - $tmpFile=OC_Helper::tmpFile(); - $fh=fopen($tmpFile, 'wb'); - fwrite($fh, $data, 8024); - fclose($fh); - $mime=self::getMimeType($tmpFile); - unset($tmpFile); - return $mime; - } + return self::getMimetypeDetector()->detectString($data); } /** @@ -454,9 +419,9 @@ class OC_Helper { */ //FIXME: should also check for value validation (i.e. the email is an email). - public static function init_var($s, $d="") { + public static function init_var($s, $d = "") { $r = $d; - if(isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) { + if (isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) { $r = OC_Util::sanitizeHTML($_REQUEST[$s]); } @@ -466,12 +431,13 @@ class OC_Helper { /** * returns "checked"-attribute if request contains selected radio element * OR if radio element is the default one -- maybe? + * * @param string $s Name of radio-button element name * @param string $v Value of current radio-button element * @param string $d Value of default radio-button element */ public static function init_radio($s, $v, $d) { - if((isset($_REQUEST[$s]) && $_REQUEST[$s]==$v) || (!isset($_REQUEST[$s]) && $v == $d)) + if ((isset($_REQUEST[$s]) && $_REQUEST[$s] == $v) || (!isset($_REQUEST[$s]) && $v == $d)) print "checked=\"checked\" "; } @@ -503,17 +469,17 @@ class OC_Helper { $dirs = explode(PATH_SEPARATOR, $path); // WARNING : We have to check if open_basedir is enabled : $obd = ini_get('open_basedir'); - if($obd != "none") { + if ($obd != "none") { $obd_values = explode(PATH_SEPARATOR, $obd); - if(count($obd_values) > 0 and $obd_values[0]) { + if (count($obd_values) > 0 and $obd_values[0]) { // open_basedir is in effect ! // We need to check if the program is in one of these dirs : $dirs = $obd_values; } } - foreach($dirs as $dir) { - foreach($exts as $ext) { - if($check_fn("$dir/$name".$ext)) + foreach ($dirs as $dir) { + foreach ($exts as $ext) { + if ($check_fn("$dir/$name" . $ext)) return true; } } @@ -522,18 +488,19 @@ class OC_Helper { /** * copy the contents of one stream to another + * * @param resource $source * @param resource $target * @return int the number of bytes copied */ public static function streamCopy($source, $target) { - if(!$source or !$target) { + if (!$source or !$target) { return false; } $result = true; $count = 0; - while(!feof($source)) { - if ( ( $c = fwrite($target, fread($source, 8192)) ) === false) { + while (!feof($source)) { + if (($c = fwrite($target, fread($source, 8192))) === false) { $result = false; } else { $count += $c; @@ -544,37 +511,39 @@ class OC_Helper { /** * create a temporary file with an unique filename + * * @param string $postfix * @return string * * temporary files are automatically cleaned up after the script is finished */ - public static function tmpFile($postfix='') { - $file=get_temp_dir().'/'.md5(time().rand()).$postfix; - $fh=fopen($file, 'w'); + public static function tmpFile($postfix = '') { + $file = get_temp_dir() . '/' . md5(time() . rand()) . $postfix; + $fh = fopen($file, 'w'); fclose($fh); - self::$tmpFiles[]=$file; + self::$tmpFiles[] = $file; return $file; } /** * move a file to oc-noclean temp dir + * * @param string $filename * @return mixed * */ - public static function moveToNoClean($filename='') { + public static function moveToNoClean($filename = '') { if ($filename == '') { return false; } - $tmpDirNoClean=get_temp_dir().'/oc-noclean/'; + $tmpDirNoClean = get_temp_dir() . '/oc-noclean/'; if (!file_exists($tmpDirNoClean) || !is_dir($tmpDirNoClean)) { if (file_exists($tmpDirNoClean)) { unlink($tmpDirNoClean); } mkdir($tmpDirNoClean); } - $newname=$tmpDirNoClean.basename($filename); + $newname = $tmpDirNoClean . basename($filename); if (rename($filename, $newname)) { return $newname; } else { @@ -584,34 +553,35 @@ class OC_Helper { /** * create a temporary folder with an unique filename + * * @return string * * temporary files are automatically cleaned up after the script is finished */ public static function tmpFolder() { - $path=get_temp_dir().'/'.md5(time().rand()); + $path = get_temp_dir() . '/' . md5(time() . rand()); mkdir($path); - self::$tmpFiles[]=$path; - return $path.'/'; + self::$tmpFiles[] = $path; + return $path . '/'; } /** * remove all files created by self::tmpFile */ public static function cleanTmp() { - $leftoversFile=get_temp_dir().'/oc-not-deleted'; - if(file_exists($leftoversFile)) { - $leftovers=file($leftoversFile); - foreach($leftovers as $file) { + $leftoversFile = get_temp_dir() . '/oc-not-deleted'; + if (file_exists($leftoversFile)) { + $leftovers = file($leftoversFile); + foreach ($leftovers as $file) { self::rmdirr($file); } unlink($leftoversFile); } - foreach(self::$tmpFiles as $file) { - if(file_exists($file)) { - if(!self::rmdirr($file)) { - file_put_contents($leftoversFile, $file."\n", FILE_APPEND); + foreach (self::$tmpFiles as $file) { + if (file_exists($file)) { + if (!self::rmdirr($file)) { + file_put_contents($leftoversFile, $file . "\n", FILE_APPEND); } } } @@ -621,34 +591,34 @@ class OC_Helper { * remove all files in PHP /oc-noclean temp dir */ public static function cleanTmpNoClean() { - $tmpDirNoCleanFile=get_temp_dir().'/oc-noclean/'; - if(file_exists($tmpDirNoCleanFile)) { + $tmpDirNoCleanFile = get_temp_dir() . '/oc-noclean/'; + if (file_exists($tmpDirNoCleanFile)) { self::rmdirr($tmpDirNoCleanFile); } } /** - * Adds a suffix to the name in case the file exists - * - * @param $path - * @param $filename - * @return string - */ + * Adds a suffix to the name in case the file exists + * + * @param $path + * @param $filename + * @return string + */ public static function buildNotExistingFileName($path, $filename) { $view = \OC\Files\Filesystem::getView(); return self::buildNotExistingFileNameForView($path, $filename, $view); } /** - * Adds a suffix to the name in case the file exists - * - * @param $path - * @param $filename - * @return string - */ + * Adds a suffix to the name in case the file exists + * + * @param $path + * @param $filename + * @return string + */ public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) { - if($path==='/') { - $path=''; + if ($path === '/') { + $path = ''; } if ($pos = strrpos($filename, '.')) { $name = substr($filename, 0, $pos); @@ -660,10 +630,10 @@ class OC_Helper { $newpath = $path . '/' . $filename; if ($view->file_exists($newpath)) { - if(preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) { + if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) { //Replace the last "(number)" with "(number+1)" - $last_match = count($matches[0])-1; - $counter = $matches[1][$last_match][0]+1; + $last_match = count($matches[0]) - 1; + $counter = $matches[1][$last_match][0] + 1; $offset = $matches[0][$last_match][1]; $match_length = strlen($matches[0][$last_match][0]); } else { @@ -671,9 +641,9 @@ class OC_Helper { $offset = false; } do { - if($offset) { + if ($offset) { //Replace the last "(number)" with "(number+1)" - $newname = substr_replace($name, '('.$counter.')', $offset, $match_length); + $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length); } else { $newname = $name . ' (' . $counter . ')'; } @@ -700,17 +670,17 @@ class OC_Helper { } /** - * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. - * - * @param array $input The array to work on - * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default) - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @return array - * - * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. - * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715 - * - */ + * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. + * + * @param array $input The array to work on + * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default) + * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 + * @return array + * + * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. + * based on http://www.php.net/manual/en/function.array-change-key-case.php#107715 + * + */ public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') { $case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER; $ret = array(); @@ -736,26 +706,26 @@ class OC_Helper { $length = intval($length); $string = mb_substr($string, 0, $start, $encoding) . $replacement . - mb_substr($string, $start+$length, mb_strlen($string, 'UTF-8')-$start, $encoding); + mb_substr($string, $start + $length, mb_strlen($string, 'UTF-8') - $start, $encoding); return $string; } /** - * @brief Replace all occurrences of the search string with the replacement string - * - * @param string $search The value being searched for, otherwise known as the needle. - * @param string $replace The replacement - * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack. - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @param int $count If passed, this will be set to the number of replacements performed. - * @return string - * - */ + * @brief Replace all occurrences of the search string with the replacement string + * + * @param string $search The value being searched for, otherwise known as the needle. + * @param string $replace The replacement + * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack. + * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 + * @param int $count If passed, this will be set to the number of replacements performed. + * @return string + * + */ public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) { $offset = -1; $length = mb_strlen($search, $encoding); - while(($i = mb_strrpos($subject, $search, $offset, $encoding)) !== false ) { + while (($i = mb_strrpos($subject, $search, $offset, $encoding)) !== false) { $subject = OC_Helper::mb_substr_replace($subject, $replace, $i, $length); $offset = $i - mb_strlen($subject, $encoding); $count++; @@ -764,21 +734,21 @@ class OC_Helper { } /** - * @brief performs a search in a nested array - * @param array $haystack the array to be searched - * @param string $needle the search string - * @param string $index optional, only search this key name - * @return mixed the key of the matching field, otherwise false - * - * performs a search in a nested array - * - * taken from http://www.php.net/manual/en/function.array-search.php#97645 - */ + * @brief performs a search in a nested array + * @param array $haystack the array to be searched + * @param string $needle the search string + * @param string $index optional, only search this key name + * @return mixed the key of the matching field, otherwise false + * + * performs a search in a nested array + * + * taken from http://www.php.net/manual/en/function.array-search.php#97645 + */ public static function recursiveArraySearch($haystack, $needle, $index = null) { $aIt = new RecursiveArrayIterator($haystack); $it = new RecursiveIteratorIterator($aIt); - while($it->valid()) { + while ($it->valid()) { if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) { return $aIt->key(); } @@ -792,6 +762,7 @@ class OC_Helper { /** * Shortens str to maxlen by replacing characters in the middle with '...', eg. * ellipsis('a very long string with lots of useless info to make a better example', 14) becomes 'a very ...example' + * * @param string $str the string * @param string $maxlen the maximum length of the result * @return string with at most maxlen characters @@ -822,7 +793,7 @@ class OC_Helper { $maxUploadFilesize = min($upload_max_filesize, $post_max_size); } - if($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN){ + if ($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN) { $freeSpace = max($freeSpace, 0); return min($maxUploadFilesize, $freeSpace); @@ -833,6 +804,7 @@ class OC_Helper { /** * Checks if a function is available + * * @param string $function_name * @return bool */ @@ -861,7 +833,7 @@ class OC_Helper { $used = 0; } $free = \OC\Files\Filesystem::free_space(); - if ($free >= 0){ + if ($free >= 0) { $total = $free + $used; } else { $total = $free; //either unknown or unlimited @@ -869,7 +841,7 @@ class OC_Helper { if ($total == 0) { $total = 1; // prevent division by zero } - if ($total >= 0){ + if ($total >= 0) { $relative = round(($used / $total) * 10000) / 100; } else { $relative = 0; |