diff options
27 files changed, 635 insertions, 72 deletions
diff --git a/.gitignore b/.gitignore index 09af6808d64..40d6e6ca0fe 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ nbproject # Cloud9IDE .settings.xml +.c9revisions # vim ex mode .vimrc diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index c30f1bcddd8..af3fc483910 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -115,6 +115,8 @@ var FileActions = { // NOTE: Temporary fix to allow unsharing of files in root of Shared folder if ($('#dir').val() == '/Shared') { var html = '<a href="#" original-title="' + t('files', 'Unshare') + '" class="action delete" />'; + } else if (typeof trashBinApp !== 'undefined' && trashBinApp) { + var html = '<a href="#" original-title="' + t('files', 'Delete permanently') + '" class="action delete" />'; } else { var html = '<a href="#" original-title="' + t('files', 'Delete') + '" class="action delete" />'; } diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index e426f237bbe..f83109a18ea 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -12,7 +12,7 @@ OC_FileProxy::register( new OCA\Encryption\Proxy() ); // User-related hooks OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' ); -OCP\Util::connectHook( 'OC_User', 'post_setPassword','OCA\Encryption\Hooks', 'setPassphrase' ); +OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'setPassphrase' ); // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 065ef9d2410..8bdeee0937b 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -38,12 +38,15 @@ class Hooks { */
public static function login( $params ) {
+ // Manually initialise Filesystem{} singleton with correct
+ // fake root path, in order to avoid fatal webdav errors
\OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' );
$view = new \OC_FilesystemView( '/' );
$util = new Util( $view, $params['uid'] );
+ // Check files_encryption infrastructure is ready for action
if ( ! $util->ready() ) {
\OC_Log::write( 'Encryption library', 'User account "' . $params['uid'] . '" is not ready for encryption; configuration started', \OC_Log::DEBUG );
@@ -104,14 +107,16 @@ class Hooks { * @param array $params keys: uid, password
*/
public static function setPassphrase( $params ) {
-
+
// Only attempt to change passphrase if server-side encryption
// is in use (client-side encryption does not have access to
// the necessary keys)
if ( Crypt::mode() == 'server' ) {
+ $session = new Session();
+
// Get existing decrypted private key
- $privateKey = $_SESSION['privateKey'];
+ $privateKey = $session->getPrivateKey();
// Encrypt private key with new user pwd as passphrase
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $privateKey, $params['password'] );
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index e3ffacabc9a..d00f71b6141 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -45,24 +45,6 @@ class Crypt { * @return string 'client' or 'server'
*/
public static function mode( $user = null ) {
-
-// $mode = \OC_Appconfig::getValue( 'files_encryption', 'mode', 'none' );
-//
-// if ( $mode == 'user') {
-// if ( !$user ) {
-// $user = \OCP\User::getUser();
-// }
-// $mode = 'none';
-// if ( $user ) {
-// $query = \OC_DB::prepare( "SELECT mode FROM *PREFIX*encryption WHERE uid = ?" );
-// $result = $query->execute(array($user));
-// if ($row = $result->fetchRow()){
-// $mode = $row['mode'];
-// }
-// }
-// }
-//
-// return $mode;
return 'server';
@@ -133,12 +115,6 @@ class Crypt { * @note see also OCA\Encryption\Util->isEncryptedPath()
*/
public static function isCatfile( $content ) {
-
- if ( !$content ) {
-
- return false;
-
- }
$noPadding = self::removePadding( $content );
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 355ffb90ef0..52bc74db27a 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -69,11 +69,6 @@ class Util { //// DONE: add method to fetch legacy key //// DONE: add method to decrypt legacy encrypted data - //// TODO: add method to encrypt all user files using new system - //// TODO: add method to decrypt all user files using new system - //// TODO: add method to encrypt all user files using old system - //// TODO: add method to decrypt all user files using old system - // Admin UI: @@ -93,7 +88,6 @@ class Util { // Integration testing: - //// TODO: test new encryption with webdav //// TODO: test new encryption with versioning //// TODO: test new encryption with sharing //// TODO: test new encryption with proxies @@ -278,7 +272,7 @@ class Util { // will eat server resources :( if ( Keymanager::getFileKey( $this->view, $this->userId, $file ) - && Crypt::isCatfile( $filePath ) + && Crypt::isCatfile( $data ) ) { $found['encrypted'][] = array( 'name' => $file, 'path' => $filePath ); @@ -391,7 +385,6 @@ class Util { } - // FIXME: Legacy recrypting here isn't finished yet // Encrypt legacy encrypted files if ( ! empty( $legacyPassphrase ) @@ -437,6 +430,11 @@ class Util { } + /** + * @brief Return important encryption related paths + * @param string $pathName Name of the directory to return the path of + * @return string path + */ public function getPath( $pathName ) { switch ( $pathName ) { diff --git a/apps/files_trashbin/ajax/delete.php b/apps/files_trashbin/ajax/delete.php new file mode 100644 index 00000000000..a166ce55c88 --- /dev/null +++ b/apps/files_trashbin/ajax/delete.php @@ -0,0 +1,24 @@ +<?php + +OCP\JSON::checkLoggedIn(); +OCP\JSON::callCheck(); + +$file = $_REQUEST['file']; + +$path_parts = pathinfo($file); +if ($path_parts['dirname'] == '.') { + $delimiter = strrpos($file, '.d'); + $filename = substr($file, 0, $delimiter); + $timestamp = substr($file, $delimiter+2); +} else { + $filename = $file; + $timestamp = null; +} + +if (OCA_Trash\Trashbin::delete($filename, $timestamp)) { + error_log("feinifeini"); + OCP\JSON::success(array("data" => array("filename" => $file))); +} else { + OCP\JSON::error(array("data" => array("message" => "Couldn't delete ".$file. " permanently"))); +} + diff --git a/apps/files_trashbin/js/disableDefaultActions.js b/apps/files_trashbin/js/disableDefaultActions.js index 56b95407dd3..27c3e13db4d 100644 --- a/apps/files_trashbin/js/disableDefaultActions.js +++ b/apps/files_trashbin/js/disableDefaultActions.js @@ -1,3 +1,4 @@ /* disable download and sharing actions */
var disableDownloadActions = true;
var disableSharing = true;
+var trashBinApp = true;
\ No newline at end of file diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index f1241fce51e..6c810e4c2bd 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -22,6 +22,31 @@ $(document).ready(function() { }); }; + FileActions.register('all', 'Delete', OC.PERMISSION_READ, function () { + return OC.imagePath('core', 'actions/delete'); + }, function (filename) { + $('.tipsy').remove(); + + var tr=$('tr').filterAttr('data-file', filename); + var deleteAction = $('tr').filterAttr('data-file',filename).children("td.date").children(".action.delete"); + var oldHTML = deleteAction[0].outerHTML; + var newHTML = '<img class="move2trash" data-action="Delete" title="'+t('files', 'delete file permanently')+'" src="'+ OC.imagePath('core', 'loading.gif') +'"></a>'; + deleteAction[0].outerHTML = newHTML; + + $.post(OC.filePath('files_trashbin','ajax','delete.php'), + {file:tr.attr('data-file') }, + function(result){ + if ( result.status == 'success' ) { + var row = document.getElementById(result.data.filename); + row.parentNode.removeChild(row); + } else { + deleteAction[0].outerHTML = oldHTML; + OC.dialogs.alert(result.data.message, 'Error'); + } + }); + + }); + // Sets the select_all checkbox behaviour : $('#select_all').click(function() { if($(this).attr('checked')){ diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index a7eff3d44e0..e41dcb096c9 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -151,6 +151,45 @@ class Trashbin { } /**
+ * delete file from trash bin permanently
+ * @param $filename path to the file + * @param $timestamp of deletion time
+ * @return true/false
+ */
+ public static function delete($filename, $timestamp=null) {
+
+ $user = \OCP\User::getUser();
+ $view = new \OC_FilesystemView('/'.$user);
+
+ if ( $timestamp ) {
+ $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?');
+ $query->execute(array($user,$filename,$timestamp));
+ $file = $filename.'.d'.$timestamp; + } else { + $file = $filename; + } + + if ( \OCP\App::isEnabled('files_versions') ) { + if ($view->is_dir('versions_trashbin/'.$file)) { + $view->unlink('versions_trashbin/'.$file); + } else if ( $versions = self::getVersionsFromTrash($file, $timestamp) ) { + foreach ($versions as $v) { + if ($timestamp ) { + $view->unlink('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp); + } else { + $view->unlink('versions_trashbin/'.$file.'.v'.$v); + } + } + } + }
+ + $view->unlink('/files_trashbin/'.$file); +
+ return true;
+ } + + + /**
* clean up the trash bin
*/
private static function expire() { diff --git a/apps/files_versions/ajax/getVersions.php b/apps/files_versions/ajax/getVersions.php index 600e69cf798..53fc04625c6 100644 --- a/apps/files_versions/ajax/getVersions.php +++ b/apps/files_versions/ajax/getVersions.php @@ -5,7 +5,7 @@ $userDirectory = "/".OCP\USER::getUser()."/files"; $source = $_GET['source']; $count = 5; //show the newest revisions -if( ($versions = OCA_Versions\Storage::getVersions( $source, $count)) ) { +if( ($versions = OCA\Files_Versions\Storage::getVersions( $source, $count)) ) { $versionsFormatted = array(); diff --git a/apps/files_versions/ajax/rollbackVersion.php b/apps/files_versions/ajax/rollbackVersion.php index f2c211d9c1e..dc5a59cb4af 100644 --- a/apps/files_versions/ajax/rollbackVersion.php +++ b/apps/files_versions/ajax/rollbackVersion.php @@ -8,7 +8,7 @@ $userDirectory = "/".OCP\USER::getUser()."/files"; $file = $_GET['file']; $revision=(int)$_GET['revision']; -if(OCA_Versions\Storage::rollback( $file, $revision )) { +if(OCA\Files_Versions\Storage::rollback( $file, $revision )) { OCP\JSON::success(array("data" => array( "revision" => $revision, "file" => $file ))); }else{ OCP\JSON::error(array("data" => array( "message" => "Could not revert:" . $file ))); diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php index edd0a2f7022..f7c6989ce2d 100644 --- a/apps/files_versions/appinfo/app.php +++ b/apps/files_versions/appinfo/app.php @@ -1,8 +1,8 @@ <?php //require_once 'files_versions/versions.php'; -OC::$CLASSPATH['OCA_Versions\Storage'] = 'apps/files_versions/lib/versions.php'; -OC::$CLASSPATH['OCA_Versions\Hooks'] = 'apps/files_versions/lib/hooks.php'; +OC::$CLASSPATH['OCA\Files_Versions\Storage'] = 'apps/files_versions/lib/versions.php'; +OC::$CLASSPATH['OCA\Files_Versions\Hooks'] = 'apps/files_versions/lib/hooks.php'; OCP\App::registerAdmin('files_versions', 'settings'); OCP\App::registerPersonal('files_versions', 'settings-personal'); @@ -10,7 +10,7 @@ OCP\App::registerPersonal('files_versions', 'settings-personal'); OCP\Util::addscript('files_versions', 'versions'); // Listen to write signals -OCP\Util::connectHook('OC_Filesystem', 'write', "OCA_Versions\Hooks", "write_hook"); +OCP\Util::connectHook('OC_Filesystem', 'write', "OCA\Files_Versions\Hooks", "write_hook"); // Listen to delete and rename signals -OCP\Util::connectHook('OC_Filesystem', 'post-delete', "OCA_Versions\Hooks", "remove_hook"); -OCP\Util::connectHook('OC_Filesystem', 'rename', "OCA_Versions\Hooks", "rename_hook");
\ No newline at end of file +OCP\Util::connectHook('OC_Filesystem', 'post-delete', "OCA\Files_Versions\Hooks", "remove_hook"); +OCP\Util::connectHook('OC_Filesystem', 'rename', "OCA\Files_Versions\Hooks", "rename_hook"); diff --git a/apps/files_versions/history.php b/apps/files_versions/history.php index 6071240e583..1bd5cde44be 100644 --- a/apps/files_versions/history.php +++ b/apps/files_versions/history.php @@ -29,7 +29,7 @@ if ( isset( $_GET['path'] ) ) { $path = $_GET['path']; $tmpl->assign( 'path', $path ); - $versions = new OCA_Versions\Storage(); + $versions = new OCA\Files_Versions\Storage(); // roll back to old version if button clicked if( isset( $_GET['revert'] ) ) { @@ -52,7 +52,7 @@ if ( isset( $_GET['path'] ) ) { // show the history only if there is something to show $count = 999; //show the newest revisions - if( ($versions = OCA_Versions\Storage::getVersions( $path, $count)) ) { + if( ($versions = OCA\Files_Versions\Storage::getVersions( $path, $count)) ) { $tmpl->assign( 'versions', array_reverse( $versions ) ); diff --git a/apps/files_versions/lib/hooks.php b/apps/files_versions/lib/hooks.php index 5cefc532895..dc02c605c44 100644 --- a/apps/files_versions/lib/hooks.php +++ b/apps/files_versions/lib/hooks.php @@ -10,7 +10,7 @@ * This class contains all hooks. */ -namespace OCA_Versions; +namespace OCA\Files_Versions; class Hooks { diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 5063ef3e21c..b54bc4a4422 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -13,7 +13,7 @@ * A class to handle the versioning of files. */ -namespace OCA_Versions; +namespace OCA\Files_Versions; class Storage { @@ -195,6 +195,7 @@ class Storage { $files_view = new \OC_FilesystemView('/'.$uid.'/files'); $local_file = $files_view->getLocalFile($filename); + $local_file_md5 = \md5_file( $local_file ); foreach( $matches as $ma ) { $parts = explode( '.v', $ma ); @@ -206,7 +207,7 @@ class Storage { $versions[$key]['size'] = $versions_fileview->filesize($filename.'.v'.$version); // if file with modified date exists, flag it in array as currently enabled version - ( \md5_file( $ma ) == \md5_file( $local_file ) ? $versions[$key]['fileMatch'] = 1 : $versions[$key]['fileMatch'] = 0 ); + ( \md5_file( $ma ) == $local_file_md5 ? $versions[$key]['fileMatch'] = 1 : $versions[$key]['fileMatch'] = 0 ); } diff --git a/autotest.cmd b/autotest.cmd new file mode 100644 index 00000000000..053860db547 --- /dev/null +++ b/autotest.cmd @@ -0,0 +1,117 @@ +:: +:: ownCloud +:: +:: @author Thomas Müller +:: @author Tobias Ramforth (translated into Windows batch file) +:: +:: @copyright 2012 Thomas Müller thomas.mueller@tmit.eu +:: +@echo off + +set DATADIR=data-autotest +set BASEDIR=%~dp0 + +:: create autoconfig for sqlite, mysql and postgresql +echo ^<?php > .\tests\autoconfig-sqlite.php +echo $AUTOCONFIG ^= array ^( >> .\tests\autoconfig-sqlite.php +echo 'installed' ^=^> false^, >> .\tests\autoconfig-sqlite.php +echo 'dbtype' ^=^> 'sqlite'^, >> .\tests\autoconfig-sqlite.php +echo 'dbtableprefix' ^=^> 'oc_'^, >> .\tests\autoconfig-sqlite.php +echo 'adminlogin' ^=^> 'admin'^, >> .\tests\autoconfig-sqlite.php +echo 'adminpass' ^=^> 'admin'^, >> .\tests\autoconfig-sqlite.php +echo 'directory' ^=^> '%BASEDIR%%DATADIR%'^, >> .\tests\autoconfig-sqlite.php +echo ^)^; >> .\tests\autoconfig-sqlite.php + +echo ^<?php > .\tests\autoconfig-mysql.php +echo $AUTOCONFIG ^= array ^( >> .\tests\autoconfig-mysql.php +echo 'installed' ^=^> false^, >> .\tests\autoconfig-mysql.php +echo 'dbtype' ^=^> 'mysql'^, >> .\tests\autoconfig-mysql.php +echo 'dbtableprefix' ^=^> 'oc_'^, >> .\tests\autoconfig-mysql.php +echo 'adminlogin' ^=^> 'admin'^, >> .\tests\autoconfig-mysql.php +echo 'adminpass' ^=^> 'admin'^, >> .\tests\autoconfig-mysql.php +echo 'directory' ^=^> '%BASEDIR%%DATADIR%'^, >> .\tests\autoconfig-mysql.php +echo 'dbuser' ^=^> 'oc_autotest'^, >> .\tests\autoconfig-mysql.php +echo 'dbname' ^=^> 'oc_autotest'^, >> .\tests\autoconfig-mysql.php +echo 'dbhost' ^=^> 'localhost'^, >> .\tests\autoconfig-mysql.php +echo 'dbpass' ^=^> 'owncloud'^, >> .\tests\autoconfig-mysql.php +echo ^)^; >> .\tests\autoconfig-mysql.php + +echo ^<?php > .\tests\autoconfig-pgsql.php +echo $AUTOCONFIG ^= array ^( >> .\tests\autoconfig-pgsql.php +echo 'installed' ^=^> false^, >> .\tests\autoconfig-pgsql.php +echo 'dbtype' ^=^> 'pgsql'^, >> .\tests\autoconfig-pgsql.php +echo 'dbtableprefix' ^=^> 'oc_'^, >> .\tests\autoconfig-pgsql.php +echo 'adminlogin' ^=^> 'admin'^, >> .\tests\autoconfig-pgsql.php +echo 'adminpass' ^=^> 'admin'^, >> .\tests\autoconfig-pgsql.php +echo 'directory' ^=^> '%BASEDIR%%DATADIR%'^, >> .\tests\autoconfig-pgsql.php +echo 'dbuser' ^=^> 'oc_autotest'^, >> .\tests\autoconfig-pgsql.php +echo 'dbname' ^=^> 'oc_autotest'^, >> .\tests\autoconfig-pgsql.php +echo 'dbhost' ^=^> 'localhost'^, >> .\tests\autoconfig-pgsql.php +echo 'dbpass' ^=^> 'owncloud'^, >> .\tests\autoconfig-pgsql.php +echo ^)^; >> .\tests\autoconfig-pgsql.php + +echo localhost:5432:*:oc_autotest:owncloud > %APPDATA%\postgresql\pgpass.conf + +:: +:: start test execution +:: +::call:execute_tests "sqlite" +call:execute_tests "mysql" +::call:execute_tests "mssql" +::call:execute_tests "ora" +::call:execute_tests "pgsql" + +goto:eof + +:execute_tests + echo "Setup environment for %~1 testing ..." + :: back to root folder + cd %BASEDIR% + + :: revert changes to tests\data + git checkout tests\data\* + + :: reset data directory + rmdir /s /q %DATADIR% + md %DATADIR% + + :: remove the old config file + :: del /q /f config\config.php + copy /y tests\preseed-config.php config\config.php + + :: drop database + if "%~1" == "mysql" mysql -u oc_autotest -powncloud -e "DROP DATABASE oc_autotest" + + if "%~1" == "pgsql" dropdb -h localhost -p 5432 -U oc_autotest -w oc_autotest + + :: copy autoconfig + copy /y %BASEDIR%\tests\autoconfig-%~1.php %BASEDIR%\config\autoconfig.php + + :: trigger installation + php -f index.php + + ::test execution + echo "Testing with %~1 ..." + cd tests + rmdir /s /q coverage-html-%~1 + md coverage-html-%~1 + php -f enable_all.php + ::phpunit --log-junit autotest-results-%~1.xml --coverage-clover autotest-clover-%~1.xml --coverage-html coverage-html-%~1 + ::phpunit --bootstrap bootstrap.php --configuration phpunit.xml + php win32-phpunit.php --bootstrap bootstrap.php --configuration phpunit.xml --log-junit autotest-results-%~1.xml --coverage-clover autotest-clover-%~1.xml --coverage-html coverage-html-%~1 + echo "Done with testing %~1 ..." + cd %BASEDIR% +goto:eof + +:: +:: NOTES on mysql: +:: - CREATE USER 'oc_autotest'@'localhost' IDENTIFIED BY 'owncloud'; +:: - grant access permissions: grant all on oc_autotest.* to 'oc_autotest'@'localhost'; +:: +:: NOTES on pgsql: +:: - su - postgres +:: - createuser -P (enter username and password and enable superuser) +:: - to enable dropdb I decided to add following line to pg_hba.conf (this is not the safest way but I don't care for the testing machine): +:: local all all trust +:: + diff --git a/core/css/styles.css b/core/css/styles.css index 6182655893f..268040525bf 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -199,7 +199,7 @@ input[name="password-clone"] { padding-left:1.8em; width:11.7em !important; } /* NEEDED FOR INFIELD LABELS */ p.infield { position:relative; } label.infield { cursor:text !important; top:1.05em; left:.85em; } -#login form label.infield { position:absolute; font-size:19px; color:#aaa; white-space:nowrap; padding-left:1.2em; } +#login form label.infield { position:absolute; font-size:19px; color:#aaa; white-space:nowrap; padding-left:1.4em; } #login form input[type="checkbox"]+label { position:relative; margin:0; font-size:1em; text-shadow:#fff 0 1px 0; } #login form .errors { background:#fed7d7; border:1px solid #f00; list-style-indent:inside; margin:0 0 2em; padding:1em; } diff --git a/core/templates/login.php b/core/templates/login.php index ed9aaba8a4c..e66d27f6d69 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -48,9 +48,9 @@ <fieldset> <legend><?php echo $l->t('Alternative Logins') ?></legend> <ul> - <? foreach($_['alt_login'] as $login): ?> + <?php foreach($_['alt_login'] as $login): ?> <li><a class="button" href="<?php echo $login['href']; ?>" ><?php echo $login['name']; ?></a></li> - <?php endforeach; ?> + <?php endforeach; ?> </ul> </fieldset> </form> diff --git a/lib/hook.php b/lib/hook.php index 4da331bb5d8..e30aefb5e18 100644 --- a/lib/hook.php +++ b/lib/hook.php @@ -20,19 +20,22 @@ class OC_Hook{ * TODO: write example */ static public function connect( $signalclass, $signalname, $slotclass, $slotname ) { - // Create the data structure + // If we're trying to connect to an emitting class that isn't + // yet registered, register it if( !array_key_exists( $signalclass, self::$registered )) { self::$registered[$signalclass] = array(); } - if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { + // If we're trying to connect to an emitting method that isn't + // yet registered, register it with the emitting class + if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { self::$registered[$signalclass][$signalname] = array(); } - - // register hook + + // Connect the hook handler to the requested emitter self::$registered[$signalclass][$signalname][] = array( "class" => $slotclass, "name" => $slotname ); - + // No chance for failure ;-) return true; } @@ -49,14 +52,19 @@ class OC_Hook{ * TODO: write example */ static public function emit( $signalclass, $signalname, $params = array()) { - // Return false if there are no slots + + // Return false if no hook handlers are listening to this + // emitting class if( !array_key_exists( $signalclass, self::$registered )) { return false; } + + // Return false if no hook handlers are listening to this + // emitting method if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { return false; } - + // Call all slots foreach( self::$registered[$signalclass][$signalname] as $i ) { try { diff --git a/lib/public/contacts.php b/lib/public/contacts.php index 44d82c37908..88d812e735a 100644 --- a/lib/public/contacts.php +++ b/lib/public/contacts.php @@ -149,14 +149,14 @@ namespace OCP { /** * @param \OCP\IAddressBook $address_book */ - public static function registerAddressBook($address_book) { + public static function registerAddressBook(\OCP\IAddressBook $address_book) { self::$address_books[$address_book->getKey()] = $address_book; } /** * @param \OCP\IAddressBook $address_book */ - public static function unregisterAddressBook($address_book) { + public static function unregisterAddressBook(\OCP\IAddressBook $address_book) { unset(self::$address_books[$address_book->getKey()]); } diff --git a/lib/util.php b/lib/util.php index 5983c34e761..faa1a549e64 100755 --- a/lib/util.php +++ b/lib/util.php @@ -535,6 +535,14 @@ class OC_Util { } /** + * Check if the PHP module fileinfo is loaded. + * @return bool + */ + public static function fileInfoLoaded() { + return function_exists('finfo_open'); + } + + /** * Check if the ownCloud server can connect to the internet */ public static function isinternetconnectionworking() { diff --git a/settings/admin.php b/settings/admin.php index 4d9685ab920..7cca7165153 100755 --- a/settings/admin.php +++ b/settings/admin.php @@ -31,6 +31,7 @@ $tmpl->assign('entriesremain', $entriesremain); $tmpl->assign('htaccessworking', $htaccessworking); $tmpl->assign('internetconnectionworking', OC_Util::isinternetconnectionworking()); $tmpl->assign('islocaleworking', OC_Util::issetlocaleworking()); +$tmpl->assign('has_fileinfo', OC_Util::fileInfoLoaded()); $tmpl->assign('backgroundjobs_mode', OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax')); $tmpl->assign('shareAPIEnabled', OC_Appconfig::getValue('core', 'shareapi_enabled', 'yes')); diff --git a/settings/ajax/changepassword.php b/settings/ajax/changepassword.php index 8d45e62e4d8..ceb4bbeecb0 100644 --- a/settings/ajax/changepassword.php +++ b/settings/ajax/changepassword.php @@ -4,6 +4,9 @@ OCP\JSON::callCheck(); OC_JSON::checkLoggedIn(); +// Manually load apps to ensure hooks work correctly (workaround for issue 1503) +OC_APP::loadApps(); + $username = isset($_POST["username"]) ? $_POST["username"] : OC_User::getUser(); $password = $_POST["password"]; $oldPassword=isset($_POST["oldpassword"])?$_POST["oldpassword"]:''; @@ -15,14 +18,8 @@ if(OC_User::isAdminUser(OC_User::getUser())) { if(OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username)) { $userstatus = 'subadmin'; } -if(OC_User::getUser() === $username) { - if (OC_User::checkPassword($username, $oldPassword)) { - $userstatus = 'user'; - } else { - if (!OC_Util::isUserVerified()) { - $userstatus = null; - } - } +if(OC_User::getUser() === $username && OC_User::checkPassword($username, $oldPassword)) { + $userstatus = 'user'; } if(is_null($userstatus)) { diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 0097489743f..9a9a691dcbf 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -22,7 +22,20 @@ if (!$_['htaccessworking']) { <?php } -// is locale working ? +// if module fileinfo available? +if (!$_['has_fileinfo']) { + ?> +<fieldset class="personalblock"> + <legend><strong><?php echo $l->t('Module \'fileinfo\' missing');?></strong></legend> + + <span class="connectionwarning"> + <?php echo $l->t('The PHP module \'fileinfo\' is missing. We strongly recommend to enable this module to get best results with mime-type detection.'); ?> + </span> + +</fieldset> +<?php +} + if (!$_['islocaleworking']) { ?> <fieldset class="personalblock"> diff --git a/tests/lib/public/contacts.php b/tests/lib/public/contacts.php index 23994667a26..ce5d762226b 100644 --- a/tests/lib/public/contacts.php +++ b/tests/lib/public/contacts.php @@ -39,7 +39,7 @@ class Test_Contacts extends PHPUnit_Framework_TestCase public function testEnabledAfterRegister() { // create mock for the addressbook - $stub = $this->getMock("SimpleAddressBook", array('getKey')); + $stub = $this->getMockForAbstractClass("OCP\IAddressBook", array('getKey')); // we expect getKey to be called twice: // first time on register @@ -65,7 +65,7 @@ class Test_Contacts extends PHPUnit_Framework_TestCase public function testAddressBookEnumeration() { // create mock for the addressbook - $stub = $this->getMock("SimpleAddressBook", array('getKey', 'getDisplayName')); + $stub = $this->getMockForAbstractClass("OCP\IAddressBook", array('getKey', 'getDisplayName')); // setup return for method calls $stub->expects($this->any()) @@ -85,8 +85,8 @@ class Test_Contacts extends PHPUnit_Framework_TestCase public function testSearchInAddressBook() { // create mock for the addressbook - $stub1 = $this->getMock("SimpleAddressBook1", array('getKey', 'getDisplayName', 'search')); - $stub2 = $this->getMock("SimpleAddressBook2", array('getKey', 'getDisplayName', 'search')); + $stub1 = $this->getMockForAbstractClass("OCP\IAddressBook", array('getKey', 'getDisplayName', 'search')); + $stub2 = $this->getMockForAbstractClass("OCP\IAddressBook", array('getKey', 'getDisplayName', 'search')); $searchResult1 = array( array('id' => 0, 'FN' => 'Frank Karlitschek', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), diff --git a/tests/win32-phpunit.php b/tests/win32-phpunit.php new file mode 100644 index 00000000000..ac8f95efcbf --- /dev/null +++ b/tests/win32-phpunit.php @@ -0,0 +1,347 @@ +<?php +OC_PHPUnit_Loader::checkIncludePath(); +OC_PHPUnit_Loader::detectPHPUnitVersionId(); + +//load PHPUnit +switch (OC_PHPUnit_Loader::$PHPUnitVersionId) { + case "36": { + OC_PHPUnit_Loader::load36(); + break; + } + case "37": { + OC_PHPUnit_Loader::load37(); + break; + } +} + +//load custom implementation of the PHPUnit_TextUI_ResultPrinter +switch (OC_PHPUnit_Loader::$PHPUnitVersionId) { + case "36": + case "37": { + class OC_PHPUnit_TextUI_ResultPrinter extends PHPUnit_TextUI_ResultPrinter + { + function __construct() + { + parent::__construct('php://stderr'); + } + + public function printResult(PHPUnit_Framework_TestResult $result) + { + $this->printHeader(); + $this->printFooter($result); + } + + protected function writeProgress($progress) + { + //ignore + } + } + break; + } +} + +//loading of OC_PHPUnit_TextUI_Command +switch (OC_PHPUnit_Loader::$PHPUnitVersionId) { + case "36": + case "37": { + class OC_PHPUnit_TextUI_Command extends PHPUnit_TextUI_Command + { + + public static function main($exit = TRUE) + { + $command = new OC_PHPUnit_TextUI_Command(); + $command->run($_SERVER['argv'], $exit); + } + + protected function handleArguments(array $argv) + { + parent::handleArguments($argv); + $this->arguments['listeners'][] = new OC_PHPUnit_Framework_TestListener(); + $this->arguments['printer'] = new OC_PHPUnit_TextUI_ResultPrinter(); + } + + protected function createRunner() + { + $coverage_Filter = new PHP_CodeCoverage_Filter(); + $coverage_Filter->addFileToBlacklist(__FILE__); + $runner = new PHPUnit_TextUI_TestRunner($this->arguments['loader'], $coverage_Filter); + return $runner; + } + } + break; + } +} + +class OC_PHPUnit_Loader +{ + + const SUCCESS_EXIT = 0; + const FAILURE_EXIT = 1; + const EXCEPTION_EXIT = 2; + + public static $PHPUnitVersionId; + + /** + * @return void + */ + public static function checkIncludePath() + { + //check include path + $PHPUnitParentDirectory = self::getPHPUnitParentDirectory(); + if (is_null($PHPUnitParentDirectory)) { + echo "Cannot find PHPUnit in include path (" . ini_get('include_path') . ")"; + exit(OC_PHPUnit_Loader::FAILURE_EXIT); + } + } + + /** + * @return null | string + */ + private static function getPHPUnitParentDirectory() + { + $pathArray = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($pathArray as $path) + { + if (file_exists($path . DIRECTORY_SEPARATOR . 'PHPUnit/')) { + return $path; + } + } + return null; + } + + /** + * @return void + */ + public static function detectPHPUnitVersionId() + { + require_once 'PHPUnit/Runner/Version.php'; + + $PHPUnitVersion = PHPUnit_Runner_Version::id(); + + if ($PHPUnitVersion === "@package_version@") { + + self::$PHPUnitVersionId = "37"; + } + else if (version_compare($PHPUnitVersion, '3.7.0') >= 0) { + + self::$PHPUnitVersionId = "37"; + } + else if (version_compare($PHPUnitVersion, '3.6.0') >= 0) { + + self::$PHPUnitVersionId = "36"; + } + else if (version_compare($PHPUnitVersion, '3.6.0') >= 0) { + + echo "unsupported PHPUnit version: $PHPUnitVersion"; + exit(OC_PHPUnit_Loader::FAILURE_EXIT); + } + } + + /** + * @return void + */ + public static function load37() + { + + require 'PHPUnit/Autoload.php'; + + } + + + /** + * @return void + */ + public static function load36() + { + define('PHPUnit_MAIN_METHOD', 'OC_PHPUnit_TextUI_Command::main'); + + require 'PHPUnit/Autoload.php'; + + } +} + +class OC_PHPUnit_Framework_TestListener implements PHPUnit_Framework_TestListener +{ + + private $isSummaryTestCountPrinted = false; + + public static function printEvent($eventName, $params = array()) + { + self::printText("\n[$eventName"); + foreach ($params as $key => $value) { + self::printText(" $key='$value'"); + } + self::printText("]\n"); + } + + public static function printText($text) + { + file_put_contents('php://stderr', $text); + } + + private static function getMessage(Exception $e) + { + $message = ""; + if (strlen(get_class($e)) != 0) { + $message = $message . get_class($e); + } + if (strlen($message) != 0 && strlen($e->getMessage()) != 0) { + $message = $message . " : "; + } + $message = $message . $e->getMessage(); + return self::escapeValue($message); + } + + private static function getDetails(Exception $e) + { + return self::escapeValue($e->getTraceAsString()); + } + + public static function getValueAsString($value) + { + if (is_null($value)) { + return "null"; + } + else if (is_bool($value)) { + return $value == true ? "true" : "false"; + } + else if (is_array($value) || is_string($value)) { + $valueAsString = print_r($value, true); + if (strlen($valueAsString) > 10000) { + return null; + } + return $valueAsString; + } + else if (is_scalar($value)){ + return print_r($value, true); + } + return null; + } + + private static function escapeValue($text) { + $text = str_replace("|", "||", $text); + $text = str_replace("'", "|'", $text); + $text = str_replace("\n", "|n", $text); + $text = str_replace("\r", "|r", $text); + $text = str_replace("]", "|]", $text); + return $text; + } + + public static function getFileName($className) + { + $reflectionClass = new ReflectionClass($className); + $fileName = $reflectionClass->getFileName(); + return $fileName; + } + + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + self::printEvent("testFailed", array( + "name" => $test->getName(), + "message" => self::getMessage($e), + "details" => self::getDetails($e) + )); + } + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $params = array( + "name" => $test->getName(), + "message" => self::getMessage($e), + "details" => self::getDetails($e) + ); + if ($e instanceof PHPUnit_Framework_ExpectationFailedException) { + $comparisonFailure = $e->getComparisonFailure(); + if ($comparisonFailure instanceof PHPUnit_Framework_ComparisonFailure) { + $actualResult = $comparisonFailure->getActual(); + $expectedResult = $comparisonFailure->getExpected(); + $actualString = self::getValueAsString($actualResult); + $expectedString = self::getValueAsString($expectedResult); + if (!is_null($actualString) && !is_null($expectedString)) { + $params['actual'] = self::escapeValue($actualString); + $params['expected'] = self::escapeValue($expectedString); + } + } + } + self::printEvent("testFailed", $params); + } + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + self::printEvent("testIgnored", array( + "name" => $test->getName(), + "message" => self::getMessage($e), + "details" => self::getDetails($e) + )); + } + + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + self::printEvent("testIgnored", array( + "name" => $test->getName(), + "message" => self::getMessage($e), + "details" => self::getDetails($e) + )); + } + + public function startTest(PHPUnit_Framework_Test $test) + { + $testName = $test->getName(); + $params = array( + "name" => $testName + ); + if ($test instanceof PHPUnit_Framework_TestCase) { + $className = get_class($test); + $fileName = self::getFileName($className); + $params['locationHint'] = "php_qn://$fileName::\\$className::$testName"; + } + self::printEvent("testStarted", $params); + } + + public function endTest(PHPUnit_Framework_Test $test, $time) + { + self::printEvent("testFinished", array( + "name" => $test->getName(), + "duration" => (int)(round($time, 2) * 1000) + )); + } + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + if (!$this->isSummaryTestCountPrinted) { + $this->isSummaryTestCountPrinted = true; + //print tests count + self::printEvent("testCount", array( + "count" => count($suite) + )); + } + + $suiteName = $suite->getName(); + if (empty($suiteName)) { + return; + } + $params = array( + "name" => $suiteName, + ); + if (class_exists($suiteName, false)) { + $fileName = self::getFileName($suiteName); + $params['locationHint'] = "php_qn://$fileName::\\$suiteName"; + } + self::printEvent("testSuiteStarted", $params); + } + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $suiteName = $suite->getName(); + if (empty($suiteName)) { + return; + } + self::printEvent("testSuiteFinished", + array( + "name" => $suite->getName() + )); + } + +} + +OC_PHPUnit_TextUI_Command::main(); |