diff options
-rw-r--r-- | apps/files/index.php | 2 | ||||
-rwxr-xr-x | apps/files_encryption/tests/share.php | 6 | ||||
-rw-r--r-- | apps/files_external/templates/settings.php | 11 | ||||
-rw-r--r-- | apps/files_sharing/lib/cache.php | 58 | ||||
-rw-r--r-- | apps/files_sharing/tests/cache.php | 39 | ||||
-rw-r--r-- | core/css/apps.css | 8 | ||||
-rw-r--r-- | lib/private/connector/sabre/quotaplugin.php | 11 | ||||
-rw-r--r-- | lib/private/filechunking.php | 40 | ||||
-rw-r--r-- | lib/private/files/cache/cache.php | 18 | ||||
-rw-r--r-- | lib/private/files/view.php | 19 | ||||
-rw-r--r-- | lib/private/mail.php | 3 | ||||
-rw-r--r-- | settings/css/settings.css | 27 | ||||
-rw-r--r-- | settings/js/apps.js | 26 | ||||
-rw-r--r-- | settings/templates/apps.php | 49 | ||||
-rw-r--r-- | tests/lib/mail.php | 9 |
15 files changed, 241 insertions, 85 deletions
diff --git a/apps/files/index.php b/apps/files/index.php index 73601d26217..4d765b69e41 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -40,7 +40,7 @@ $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; $dir = \OC\Files\Filesystem::normalizePath($dir); $dirInfo = \OC\Files\Filesystem::getFileInfo($dir); // Redirect if directory does not exist -if (!$dirInfo->getType() === 'dir') { +if (!$dirInfo || !$dirInfo->getType() === 'dir') { header('Location: ' . OCP\Util::getScriptName() . ''); exit(); } diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index be56968ac09..1f57d7cb635 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -100,11 +100,11 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $this->filename = 'share-tmp.test'; - // we don't want to tests with app files_trashbin enabled - \OC_App::disable('files_trashbin'); - // remember files_trashbin state $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin'); + + // we don't want to tests with app files_trashbin enabled + \OC_App::disable('files_trashbin'); } function tearDown() { diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index a2bdbcf4632..e8815acaf16 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -9,7 +9,7 @@ <th><?php p($l->t('External storage')); ?></th> <th><?php p($l->t('Configuration')); ?></th> <!--<th><?php p($l->t('Options')); ?></th> --> - <?php if ($_['isAdminPage']) print_unescaped('<th>'.$l->t('Applicable').'</th>'); ?> + <?php if ($_['isAdminPage']) print_unescaped('<th>'.$l->t('Available for').'</th>'); ?> <th> </th> </tr> </thead> @@ -88,9 +88,12 @@ data-applicable-users='<?php if (isset($mount['applicable']['users'])) print_unescaped(json_encode($mount['applicable']['users'])); ?>'> <select class="chzn-select" - multiple style="width:20em;" - data-placeholder="<?php p($l->t('None set')); ?>"> - <option value="all" <?php if (isset($mount['applicable']['users']) && in_array('all', $mount['applicable']['users'])) print_unescaped('selected="selected"');?> ><?php p($l->t('All Users')); ?></option> + multiple style="width:20em;" + data-placeholder="<?php p($l->t('No user or group')); ?>"> + <option value="all" + <?php if (empty($mount['class']) || (isset($mount['applicable']['users']) && in_array('all', $mount['applicable']['users']))) print_unescaped('selected="selected"');?> > + <?php p($l->t('All Users')); ?> + </option> <optgroup label="<?php p($l->t('Groups')); ?>"> <?php foreach ($_['groups'] as $group): ?> <option value="<?php p($group); ?>(group)" diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 01db29d72e2..eeb62c3cce2 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -20,6 +20,7 @@ */ namespace OC\Files\Cache; + use OCP\Share_Backend_Collection; /** @@ -50,7 +51,7 @@ class Shared_Cache extends Cache { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); if (is_array($mount)) { - $fullPath = $mount[key($mount)]->getMountPoint().$source['path']; + $fullPath = $mount[key($mount)]->getMountPoint() . $source['path']; list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); if ($storage) { $this->files[$target] = $internalPath; @@ -75,7 +76,7 @@ class Shared_Cache extends Cache { /** * get the stored metadata of a file or folder * - * @param string/int $file + * @param string /int $file * @return array */ public function get($file) { @@ -95,8 +96,8 @@ class Shared_Cache extends Cache { } else { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,' - .' `size`, `mtime`, `encrypted`, `unencrypted_size`' - .' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + . ' `size`, `mtime`, `encrypted`, `unencrypted_size`' + . ' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); $result = $query->execute(array($file)); $data = $result->fetchRow(); $data['fileid'] = (int)$data['fileid']; @@ -288,8 +289,7 @@ class Shared_Cache extends Cache { foreach ($files as $file) { if ($file['mimetype'] === 'httpd/unix-directory') { $exploreDirs[] = ltrim($dir . '/' . $file['name'], '/'); - } - else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { + } else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { // usersPath not reliable //$file['path'] = $file['usersPath']; $file['path'] = ltrim($dir . '/' . $file['name'], '/'); @@ -344,8 +344,6 @@ class Shared_Cache extends Cache { if ($row['encrypted'] or ($row['unencrypted_size'] > 0 and $row['mimetype'] === 'httpd/unix-directory')) { $row['encrypted_size'] = $row['size']; $row['size'] = $row['unencrypted_size']; - } else { - $row['size'] = $row['size']; } $files[] = $row; } @@ -402,4 +400,48 @@ class Shared_Cache extends Cache { return false; } + /** + * get the path of a file on this storage by it's id + * + * @param int $id + * @param string $pathEnd (optional) used internally for recursive calls + * @return string | null + */ + public function getPathById($id, $pathEnd = '') { + // direct shares are easy + if ($path = $this->getShareById($id)) { + return $path . $pathEnd; + } else { + // if the item is a direct share we try and get the path of the parent and append the name of the item to it + list($parent, $name) = $this->getParentInfo($id); + if ($parent > 0) { + return $this->getPathById($parent, '/' . $name . $pathEnd); + } else { + return null; + } + } + } + + private function getShareById($id) { + $item = \OCP\Share::getItemSharedWithBySource('file', $id); + if ($item) { + return trim($item['file_target'], '/'); + } + $item = \OCP\Share::getItemSharedWithBySource('folder', $id); + if ($item) { + return trim($item['file_target'], '/'); + } + return null; + } + + private function getParentInfo($id) { + $sql = 'SELECT `parent`, `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?'; + $query = \OC_DB::prepare($sql); + $result = $query->execute(array($id)); + if ($row = $result->fetchRow()) { + return array($row['parent'], $row['name']); + } else { + return array(-1, ''); + } + } } diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php index a75e1860527..47969833ab5 100644 --- a/apps/files_sharing/tests/cache.php +++ b/apps/files_sharing/tests/cache.php @@ -246,4 +246,43 @@ class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base { } } + public function testGetPathByIdDirectShare() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::file_put_contents('test.txt', 'foo'); + $info = \OC\Files\Filesystem::getFileInfo('test.txt'); + \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, \OCP\PERMISSION_ALL); + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/test.txt')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/Shared/test.txt'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('test.txt', $sharedCache->getPathById($info->getId())); + } + + public function testGetPathByIdShareSubFolder() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::mkdir('foo'); + \OC\Files\Filesystem::mkdir('foo/bar'); + \OC\Files\Filesystem::touch('foo/bar/test.txt', 'bar'); + $folderInfo = \OC\Files\Filesystem::getFileInfo('foo'); + $fileInfo = \OC\Files\Filesystem::getFileInfo('foo/bar/test.txt'); + \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, \OCP\PERMISSION_ALL); + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/foo')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/Shared/foo'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('foo', $sharedCache->getPathById($folderInfo->getId())); + $this->assertEquals('foo/bar/test.txt', $sharedCache->getPathById($fileInfo->getId())); + } } diff --git a/core/css/apps.css b/core/css/apps.css index 8eb3bdd683e..ebf277faf46 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -29,10 +29,14 @@ -moz-box-sizing: border-box; box-sizing: border-box; } #app-navigation .active, -#app-navigation .active a, -#app-navigation li:hover > a { +#app-navigation .active a { background-color: #ddd; } +#app-navigation li:hover > a, +#app-navigation .selected, +#app-navigation .selected a { + background-color: #ccc; +} /* special rules for first-level entries and folders */ #app-navigation > ul > li { diff --git a/lib/private/connector/sabre/quotaplugin.php b/lib/private/connector/sabre/quotaplugin.php index 8099794f670..227e684741c 100644 --- a/lib/private/connector/sabre/quotaplugin.php +++ b/lib/private/connector/sabre/quotaplugin.php @@ -56,8 +56,19 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin { $uri='/'.$uri; } list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri); + $req = $this->server->httpRequest; + if ($req->getHeader('OC-Chunked')) { + $info = OC_FileChunking::decodeName($newName); + $chunkHandler = new OC_FileChunking($info); + // substract the already uploaded size to see whether + // there is still enough space for the remaining chunks + $length -= $chunkHandler->getCurrentSize(); + } $freeSpace = $this->getFreeSpace($parentUri); if ($freeSpace !== \OC\Files\SPACE_UNKNOWN && $length > $freeSpace) { + if (isset($chunkHandler)) { + $chunkHandler->cleanup(); + } throw new Sabre_DAV_Exception_InsufficientStorage(); } } diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php index be7f4e14a11..1da02fc81e3 100644 --- a/lib/private/filechunking.php +++ b/lib/private/filechunking.php @@ -64,20 +64,46 @@ class OC_FileChunking { return $parts == $this->info['chunkcount']; } + /** + * Assembles the chunks into the file specified by the path. + * Chunks are deleted afterwards. + * + * @param string $f target path + * + * @return assembled file size + * + * @throws \OC\InsufficientStorageException when file could not be fully + * assembled due to lack of free space + */ public function assemble($f) { $cache = $this->getCache(); $prefix = $this->getPrefix(); $count = 0; - for($i=0; $i < $this->info['chunkcount']; $i++) { + for ($i = 0; $i < $this->info['chunkcount']; $i++) { $chunk = $cache->get($prefix.$i); + // remove after reading to directly save space + $cache->remove($prefix.$i); $count += fwrite($f, $chunk); } - $this->cleanup(); return $count; } /** + * Returns the size of the chunks already present + * @return size in bytes + */ + public function getCurrentSize() { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + $total = 0; + for ($i = 0; $i < $this->info['chunkcount']; $i++) { + $total += $cache->size($prefix.$i); + } + return $total; + } + + /** * Removes all chunks which belong to this transmission */ public function cleanup() { @@ -128,7 +154,15 @@ class OC_FileChunking { } /** - * @param string $path + * Assembles the chunks into the file specified by the path. + * Also triggers the relevant hooks and proxies. + * + * @param string $path target path + * + * @return assembled file size or false if file could not be created + * + * @throws \OC\InsufficientStorageException when file could not be fully + * assembled due to lack of free space */ public function file_assemble($path) { $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path)); diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index abc11e76470..1c9de56f8c5 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -594,7 +594,25 @@ class Cache { } /** + * get the path of a file on this storage by it's id + * + * @param int $id + * @return string | null + */ + public function getPathById($id) { + $sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ? AND `storage` = ?'; + $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId())); + if ($row = $result->fetchRow()) { + return $row['path']; + } else { + return null; + } + } + + /** * get the storage id of the storage for a file and the internal path of the file + * unlike getPathById this does not limit the search to files on this storage and + * instead does a global search in the cache table * * @param int $id * @return array, first element holding the storage id, second the path diff --git a/lib/private/files/view.php b/lib/private/files/view.php index f06c2fcd66c..90b0da09c37 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -1129,15 +1129,22 @@ class View { * @return string */ public function getPath($id) { - list($storage, $internalPath) = Cache\Cache::getById($id); - $mounts = Filesystem::getMountByStorageId($storage); + $manager = Filesystem::getMountManager(); + $mounts = $manager->findIn($this->fakeRoot); + $mounts[] = $manager->find($this->fakeRoot); + // reverse the array so we start with the storage this view is in + // which is the most likely to contain the file we're looking for + $mounts = array_reverse($mounts); foreach ($mounts as $mount) { /** - * @var \OC\Files\Mount $mount + * @var \OC\Files\Mount\Mount $mount */ - $fullPath = $mount->getMountPoint() . $internalPath; - if (!is_null($path = $this->getRelativePath($fullPath))) { - return $path; + $cache = $mount->getStorage()->getCache(); + if ($internalPath = $cache->getPathById($id)) { + $fullPath = $mount->getMountPoint() . $internalPath; + if (!is_null($path = $this->getRelativePath($fullPath))) { + return $path; + } } } return null; diff --git a/lib/private/mail.php b/lib/private/mail.php index 79f51609631..f9083cc4e64 100644 --- a/lib/private/mail.php +++ b/lib/private/mail.php @@ -137,6 +137,9 @@ class OC_Mail { * @return string */ public static function buildAsciiEmail($emailAddress) { + if (!function_exists('idn_to_ascii')) { + return $emailAddress; + } list($name, $domain) = explode('@', $emailAddress, 2); $domain = idn_to_ascii($domain); diff --git a/settings/css/settings.css b/settings/css/settings.css index 5dd41256918..b2c09571404 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -57,13 +57,7 @@ tr:hover>td.password>span, tr:hover>td.displayName>span { margin:0; cursor:point tr:hover>td.remove>a, tr:hover>td.password>img,tr:hover>td.displayName>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; } tr:hover>td.remove>a { float:right; } -li.selected, -#leftcontent li.selected { - background-color: #ddd; -} - table.grid { width:100%; } -#rightcontent { padding-left: 10px; } div.quota { float: right; display: block; @@ -101,30 +95,21 @@ select.quota.active { background: #fff; } /* APPS */ .appinfo { margin: 1em 40px; } h3 { font-size: 1.4em; font-weight: bold; } -ul.applist a { - height: 2.2em; - padding: 0.2em 0.2em 0.2em 0.8em !important; +#app-navigation { + padding-bottom: 0px; } -ul.applist .app-external { - width: 100%; -} -li { color:#888; } -li.active { color:#000; } -#leftcontent .appwarning { +#app-navigation .appwarning { background: #fcc; } -#leftcontent .appwarning:hover { +#app-navigation.appwarning:hover { background: #fbb; } small.externalapp { color:#FFF; background-color:#BBB; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 4px;} -small.externalapp.list { float: right; } small.recommendedapp { color:#FFF; background-color:#888; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 4px;} -small.recommendedapp.list { float: right; } +small.externalapp.list, small.recommendedapp.list { position: absolute; right: 10px; top: 12px; } span.version { margin-left:1em; margin-right:1em; color:#555; } -.app { position: relative; display: inline-block; padding: 0.2em 0 0.2em 0 !important; text-overflow: hidden; overflow: hidden; white-space: nowrap; /*transition: .2s max-width linear; -o-transition: .2s max-width linear; -moz-transition: .2s max-width linear; -webkit-transition: .2s max-width linear; -ms-transition: .2s max-width linear;*/ } -.app.externalapp { max-width: 12.5em; } -.app.recommendedapp { max-width: 12.5em; } + /* Transition to complete width! */ .app:hover, .app:active { max-width: inherit; } diff --git a/settings/js/apps.js b/settings/js/apps.js index 3dbc8a2f7c2..05db4c9a048 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -8,7 +8,7 @@ OC.Settings = OC.Settings || {}; OC.Settings.Apps = OC.Settings.Apps || { loadApp:function(app) { - var page = $('#rightcontent'); + var page = $('#app-content'); page.find('p.license').show(); page.find('span.name').text(app.name); page.find('small.externalapp').text(app.internallabel); @@ -82,16 +82,16 @@ OC.Settings.Apps = OC.Settings.Apps || { page.find('p.appslink').hide(); page.find('span.score').hide(); } - if (typeof($('#leftcontent li[data-id="'+app.id+'"]').data('errormsg')) !== "undefined") { + if (typeof($('#app-navigation ul li[data-id="'+app.id+'"]').data('errormsg')) !== "undefined") { page.find(".warning").show(); - page.find(".warning").text($('#leftcontent li[data-id="'+app.id+'"]').data('errormsg')); + page.find(".warning").text($('#app-navigation ul li[data-id="'+app.id+'"]').data('errormsg')); } else { page.find(".warning").hide(); } }, enableApp:function(appid, active, element) { console.log('enableApp:', appid, active, element); - var appitem=$('#leftcontent li[data-id="'+appid+'"]'); + var appitem=$('#app-navigation ul li[data-id="'+appid+'"]'); element.val(t('settings','Please wait....')); if(active) { $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) { @@ -160,7 +160,7 @@ OC.Settings.Apps = OC.Settings.Apps || { }, insertApp:function(appdata) { - var applist = $('#leftcontent li'); + var applist = $('#app-navigation ul li'); var app = $('<li data-id="' + appdata.id + '" data-type="external" data-installed="0">' + '<a class="app externalapp" href="' + OC.filePath('settings', 'apps', 'index.php') + '&appid=' + appdata.id+'">' @@ -242,30 +242,30 @@ OC.Settings.Apps = OC.Settings.Apps || { }; $(document).ready(function(){ - $('#leftcontent li').each(function(index,li){ + $('#app-navigation ul li').each(function(index,li){ var app = OC.get('appData_'+$(li).data('id')); $(li).data('app',app); $(this).find('span.hidden').remove(); }); - $('#leftcontent li').keydown(function(event) { + $('#app-navigation ul li').keydown(function(event) { if (event.which === 13 || event.which === 32) { $(event.target).click(); } return false; }); - $(document).on('click', '#leftcontent', function(event){ + $(document).on('click', '#app-navigation', function(event){ var tgt = $(event.target); if (tgt.is('li') || tgt.is('a')) { var item = tgt.is('li') ? $(tgt) : $(tgt).parent(); var app = item.data('app'); OC.Settings.Apps.loadApp(app); - $('#leftcontent .selected').removeClass('selected'); + $('#app-navigation .selected').removeClass('selected'); item.addClass('selected'); } return false; }); - $('#rightcontent input.enable').click(function(){ + $('#app-content input.enable').click(function(){ var element = $(this); var appid=$(this).data('appid'); var active=$(this).data('active'); @@ -273,7 +273,7 @@ $(document).ready(function(){ OC.Settings.Apps.enableApp(appid, active, element); } }); - $('#rightcontent input.update').click(function(){ + $('#app-content input.update').click(function(){ var element = $(this); var appid=$(this).data('appid'); if(appid) { @@ -282,11 +282,11 @@ $(document).ready(function(){ }); if(appid) { - var item = $('#leftcontent li[data-id="'+appid+'"]'); + var item = $('#app-navigation ul li[data-id="'+appid+'"]'); if(item) { item.trigger('click'); item.addClass('active'); - $('#leftcontent').animate({scrollTop: $(item).offset().top-70}, 'slow','swing'); + $('#app-navigation').animate({scrollTop: $(item).offset().top-70}, 'slow','swing'); } } }); diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 4c77c62f511..b7f3b6121ad 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -7,32 +7,33 @@ src="<?php print_unescaped(OC_Helper::linkToRoute('apps_custom'));?>?appid=<?php p($_['appid']); ?>"></script> <script type="text/javascript" src="<?php print_unescaped(OC_Helper::linkTo('settings/js', 'apps.js'));?>"></script> +<div id="app-navigation"> + <ul class="applist"> + <?php if(OC_Config::getValue('appstoreenabled', true) === true): ?> + <li> + <a class="app-external" target="_blank" href="http://owncloud.org/dev"><?php p($l->t('Add your App'));?> …</a> + </li> + <?php endif; ?> -<ul id="leftcontent" class="applist"> - <?php if(OC_Config::getValue('appstoreenabled', true) === true): ?> - <li> - <a class="app-external" target="_blank" href="http://owncloud.org/dev"><?php p($l->t('Add your App'));?> …</a> - </li> - <?php endif; ?> + <?php foreach($_['apps'] as $app):?> + <li <?php if($app['active']) print_unescaped('class="active"')?> data-id="<?php p($app['id']) ?>" + <?php if ( isset( $app['ocs_id'] ) ) { print_unescaped("data-id-ocs=\"{".OC_Util::sanitizeHTML($app['ocs_id'])."}\""); } ?> + data-type="<?php p($app['internal'] ? 'internal' : 'external') ?>" data-installed="1"> + <a class="app<?php if(!$app['internal']) p(' externalapp') ?>" + href="?appid=<?php p($app['id']) ?>"><?php p($app['name']) ?></a> + <?php if(!$app['internal']) + print_unescaped('<small class="'.OC_Util::sanitizeHTML($app['internalclass']).' list">'.OC_Util::sanitizeHTML($app['internallabel']).'</small>') ?> + </li> + <?php endforeach;?> - <?php foreach($_['apps'] as $app):?> - <li <?php if($app['active']) print_unescaped('class="active"')?> data-id="<?php p($app['id']) ?>" - <?php if ( isset( $app['ocs_id'] ) ) { print_unescaped("data-id-ocs=\"{".OC_Util::sanitizeHTML($app['ocs_id'])."}\""); } ?> - data-type="<?php p($app['internal'] ? 'internal' : 'external') ?>" data-installed="1"> - <a class="app<?php if(!$app['internal']) p(' externalapp') ?>" - href="?appid=<?php p($app['id']) ?>"><?php p($app['name']) ?></a> - <?php if(!$app['internal']) - print_unescaped('<small class="'.OC_Util::sanitizeHTML($app['internalclass']).' list">'.OC_Util::sanitizeHTML($app['internallabel']).'</small>') ?> - </li> - <?php endforeach;?> - - <?php if(OC_Config::getValue('appstoreenabled', true) === true): ?> - <li> - <a class="app-external" target="_blank" href="http://apps.owncloud.com"><?php p($l->t('More Apps'));?> …</a> - </li> - <?php endif; ?> -</ul> -<div id="rightcontent"> + <?php if(OC_Config::getValue('appstoreenabled', true) === true): ?> + <li> + <a class="app-external" target="_blank" href="http://apps.owncloud.com"><?php p($l->t('More Apps'));?> …</a> + </li> + <?php endif; ?> + </ul> +</div> +<div id="app-content"> <div class="appinfo"> <h3><strong><span class="name"><?php p($l->t('Select an App'));?></span></strong><span class="version"></span><small class="externalapp" style="visibility:hidden;"></small></h3> diff --git a/tests/lib/mail.php b/tests/lib/mail.php index a88a9d797ae..3cc9868e25e 100644 --- a/tests/lib/mail.php +++ b/tests/lib/mail.php @@ -8,6 +8,15 @@ class Test_Mail extends PHPUnit_Framework_TestCase { + protected function setUp() + { + if (!function_exists('idn_to_ascii')) { + $this->markTestSkipped( + 'The intl extension is not available.' + ); + } + } + /** * @dataProvider buildAsciiEmailProvider * @param $expected |