@@ -4,9 +4,9 @@ discard block |
||
| 4 | 4 | <meta charset="utf-8"> |
| 5 | 5 | <title> |
| 6 | 6 | <?php |
| 7 | - p(!empty($_['application'])?$_['application'].' - ':''); |
|
| 8 | - p($theme->getTitle()); |
|
| 9 | - ?> |
|
| 7 | + p(!empty($_['application'])?$_['application'].' - ':''); |
|
| 8 | + p($theme->getTitle()); |
|
| 9 | + ?> |
|
| 10 | 10 | </title> |
| 11 | 11 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| 12 | 12 | <meta name="referrer" content="never"> |
@@ -116,9 +116,9 @@ discard block |
||
| 116 | 116 | </li> |
| 117 | 117 | <?php endforeach; ?> |
| 118 | 118 | <?php |
| 119 | - /* show "More apps" link to app administration directly in app navigation, as last entry */ |
|
| 120 | - if(OC_User::isAdminUser(OC_User::getUser())): |
|
| 121 | - ?> |
|
| 119 | + /* show "More apps" link to app administration directly in app navigation, as last entry */ |
|
| 120 | + if(OC_User::isAdminUser(OC_User::getUser())): |
|
| 121 | + ?> |
|
| 122 | 122 | <li class="apps-management"> |
| 123 | 123 | <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" |
| 124 | 124 | <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> |
@@ -4,7 +4,7 @@ discard block |
||
| 4 | 4 | <meta charset="utf-8"> |
| 5 | 5 | <title> |
| 6 | 6 | <?php |
| 7 | - p(!empty($_['application'])?$_['application'].' - ':''); |
|
| 7 | + p(!empty($_['application']) ? $_['application'].' - ' : ''); |
|
| 8 | 8 | p($theme->getTitle()); |
| 9 | 9 | ?> |
| 10 | 10 | </title> |
@@ -14,16 +14,16 @@ discard block |
||
| 14 | 14 | <meta name="apple-itunes-app" content="app-id=<?php p($theme->getiTunesAppId()); ?>"> |
| 15 | 15 | <meta name="apple-mobile-web-app-capable" content="yes"> |
| 16 | 16 | <meta name="apple-mobile-web-app-status-bar-style" content="black"> |
| 17 | - <meta name="apple-mobile-web-app-title" content="<?php p((!empty($_['application']) && $_['appid']!='files')? $_['application']:$theme->getTitle()); ?>"> |
|
| 17 | + <meta name="apple-mobile-web-app-title" content="<?php p((!empty($_['application']) && $_['appid'] != 'files') ? $_['application'] : $theme->getTitle()); ?>"> |
|
| 18 | 18 | <meta name="mobile-web-app-capable" content="yes"> |
| 19 | 19 | <meta name="theme-color" content="<?php p($theme->getMailHeaderColor()); ?>"> |
| 20 | 20 | <link rel="icon" href="<?php print_unescaped(image_path($_['appid'], 'favicon.ico')); /* IE11+ supports png */ ?>"> |
| 21 | 21 | <link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path($_['appid'], 'favicon-touch.png')); ?>"> |
| 22 | 22 | <link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path($_['appid'], 'favicon-mask.svg')); ?>" color="#0082c9"> |
| 23 | - <?php foreach($_['cssfiles'] as $cssfile): ?> |
|
| 23 | + <?php foreach ($_['cssfiles'] as $cssfile): ?> |
|
| 24 | 24 | <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>"> |
| 25 | 25 | <?php endforeach; ?> |
| 26 | - <?php foreach($_['printcssfiles'] as $cssfile): ?> |
|
| 26 | + <?php foreach ($_['printcssfiles'] as $cssfile): ?> |
|
| 27 | 27 | <link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> |
| 28 | 28 | <?php endforeach; ?> |
| 29 | 29 | <?php if (isset($_['inline_ocjs'])): ?> |
@@ -31,12 +31,12 @@ discard block |
||
| 31 | 31 | <?php print_unescaped($_['inline_ocjs']); ?> |
| 32 | 32 | </script> |
| 33 | 33 | <?php endif; ?> |
| 34 | - <?php foreach($_['jsfiles'] as $jsfile): ?> |
|
| 34 | + <?php foreach ($_['jsfiles'] as $jsfile): ?> |
|
| 35 | 35 | <script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" src="<?php print_unescaped($jsfile); ?>"></script> |
| 36 | 36 | <?php endforeach; ?> |
| 37 | 37 | <?php print_unescaped($_['headers']); ?> |
| 38 | 38 | </head> |
| 39 | - <body id="<?php p($_['bodyid']);?>"> |
|
| 39 | + <body id="<?php p($_['bodyid']); ?>"> |
|
| 40 | 40 | <?php include('layout.noscript.warning.php'); ?> |
| 41 | 41 | <div id="notification-container"> |
| 42 | 42 | <div id="notification"></div> |
@@ -54,7 +54,7 @@ discard block |
||
| 54 | 54 | |
| 55 | 55 | <a href="#" class="header-appname-container menutoggle" tabindex="2"> |
| 56 | 56 | <h1 class="header-appname"> |
| 57 | - <?php p(!empty($_['application'])?$_['application']: $l->t('Apps')); ?> |
|
| 57 | + <?php p(!empty($_['application']) ? $_['application'] : $l->t('Apps')); ?> |
|
| 58 | 58 | </h1> |
| 59 | 59 | <div class="icon-caret"></div> |
| 60 | 60 | </a> |
@@ -62,11 +62,11 @@ discard block |
||
| 62 | 62 | <div id="appmenu"> |
| 63 | 63 | <ul> |
| 64 | 64 | <?php $headerIconCount = 8; ?> |
| 65 | - <?php foreach($_['headernavigation'] as $entry): ?> |
|
| 65 | + <?php foreach ($_['headernavigation'] as $entry): ?> |
|
| 66 | 66 | <li data-id="<?php p($entry['id']); ?>"> |
| 67 | 67 | <a href="<?php print_unescaped($entry['href']); ?>" tabindex="3" |
| 68 | - <?php if( $entry['active'] ): ?> class="active"<?php endif; ?>> |
|
| 69 | - <img src="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" class="app-icon" /> |
|
| 68 | + <?php if ($entry['active']): ?> class="active"<?php endif; ?>> |
|
| 69 | + <img src="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>" class="app-icon" /> |
|
| 70 | 70 | <div class="icon-loading-dark" style="display:none;"></div> |
| 71 | 71 | <span> |
| 72 | 72 | <?php p($entry['name']); ?> |
@@ -74,17 +74,17 @@ discard block |
||
| 74 | 74 | </a> |
| 75 | 75 | </li> |
| 76 | 76 | <?php endforeach; ?> |
| 77 | - <li id="more-apps" class="menutoggle<?php if (!(count($_['navigation']) > $headerIconCount || (OC_User::isAdminUser(OC_User::getUser()) && count($_['navigation'])>=$headerIconCount))): ?> hidden<?php endif; ?>"> |
|
| 77 | + <li id="more-apps" class="menutoggle<?php if (!(count($_['navigation']) > $headerIconCount || (OC_User::isAdminUser(OC_User::getUser()) && count($_['navigation']) >= $headerIconCount))): ?> hidden<?php endif; ?>"> |
|
| 78 | 78 | <a href="#"> |
| 79 | 79 | <div class="icon-more-white"></div> |
| 80 | 80 | <span><?php p($l->t('More apps')); ?></span> |
| 81 | 81 | </a> |
| 82 | 82 | </li> |
| 83 | - <?php if(OC_User::isAdminUser(OC_User::getUser())): ?> |
|
| 84 | - <li <?php if(count($_['navigation'])>$headerIconCount-1): ?> class="hidden apps-management"<?php else: ?> class="apps-management" <?php endif; ?>> |
|
| 83 | + <?php if (OC_User::isAdminUser(OC_User::getUser())): ?> |
|
| 84 | + <li <?php if (count($_['navigation']) > $headerIconCount - 1): ?> class="hidden apps-management"<?php else: ?> class="apps-management" <?php endif; ?>> |
|
| 85 | 85 | <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" |
| 86 | - <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> |
|
| 87 | - <img src="<?php print_unescaped(image_path('settings', 'apps.svg') . '?v=' . $_['versionHash']); ?>" /> |
|
| 86 | + <?php if ($_['appsmanagement_active']): ?> class="active"<?php endif; ?>> |
|
| 87 | + <img src="<?php print_unescaped(image_path('settings', 'apps.svg').'?v='.$_['versionHash']); ?>" /> |
|
| 88 | 88 | <div class="icon-loading-dark" style="display:none;"></div> |
| 89 | 89 | <span><?php p($l->t('Apps')); ?></span> |
| 90 | 90 | </a> |
@@ -96,17 +96,17 @@ discard block |
||
| 96 | 96 | <nav role="navigation"><div id="navigation"> |
| 97 | 97 | <div id="apps"> |
| 98 | 98 | <ul> |
| 99 | - <?php foreach($_['navigation'] as $entry): ?> |
|
| 100 | - <?php if($entry['showInHeader']): ?> |
|
| 99 | + <?php foreach ($_['navigation'] as $entry): ?> |
|
| 100 | + <?php if ($entry['showInHeader']): ?> |
|
| 101 | 101 | <li data-id="<?php p($entry['id']); ?>" class="in-header"> |
| 102 | 102 | <?php else: ?> |
| 103 | 103 | <li data-id="<?php p($entry['id']); ?>"> |
| 104 | 104 | <?php endif; ?> |
| 105 | 105 | <a href="<?php print_unescaped($entry['href']); ?>" tabindex="3" |
| 106 | - <?php if( $entry['active'] ): ?> class="active"<?php endif; ?>> |
|
| 106 | + <?php if ($entry['active']): ?> class="active"<?php endif; ?>> |
|
| 107 | 107 | <svg width="32" height="32" viewBox="0 0 32 32"> |
| 108 | 108 | <defs><filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix></filter></defs> |
| 109 | - <image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" class="app-icon"></image> |
|
| 109 | + <image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>" class="app-icon"></image> |
|
| 110 | 110 | </svg> |
| 111 | 111 | <div class="icon-loading-dark" style="display:none;"></div> |
| 112 | 112 | <span> |
@@ -117,14 +117,14 @@ discard block |
||
| 117 | 117 | <?php endforeach; ?> |
| 118 | 118 | <?php |
| 119 | 119 | /* show "More apps" link to app administration directly in app navigation, as last entry */ |
| 120 | - if(OC_User::isAdminUser(OC_User::getUser())): |
|
| 120 | + if (OC_User::isAdminUser(OC_User::getUser())): |
|
| 121 | 121 | ?> |
| 122 | 122 | <li class="apps-management"> |
| 123 | 123 | <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" |
| 124 | - <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> |
|
| 124 | + <?php if ($_['appsmanagement_active']): ?> class="active"<?php endif; ?>> |
|
| 125 | 125 | <svg width="32" height="32" viewBox="0 0 32 32" class="app-icon"> |
| 126 | 126 | <defs><filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix></filter></defs> |
| 127 | - <image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="<?php print_unescaped(image_path('settings', 'apps.svg') . '?v=' . $_['versionHash']); ?>"></image> |
|
| 127 | + <image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="<?php print_unescaped(image_path('settings', 'apps.svg').'?v='.$_['versionHash']); ?>"></image> |
|
| 128 | 128 | </svg> |
| 129 | 129 | <div class="icon-loading-dark" style="display:none;"></div> |
| 130 | 130 | <span> |
@@ -143,7 +143,7 @@ discard block |
||
| 143 | 143 | <div id="header-right"> |
| 144 | 144 | <form class="searchbox" action="#" method="post" role="search" novalidate> |
| 145 | 145 | <label for="searchbox" class="hidden-visually"> |
| 146 | - <?php p($l->t('Search'));?> |
|
| 146 | + <?php p($l->t('Search')); ?> |
|
| 147 | 147 | </label> |
| 148 | 148 | <input id="searchbox" type="search" name="query" |
| 149 | 149 | value="" required |
@@ -155,8 +155,8 @@ discard block |
||
| 155 | 155 | <div class="avatardiv<?php if ($_['userAvatarSet']) { print_unescaped(' avatardiv-shown'); } else { print_unescaped('" style="display: none'); } ?>"> |
| 156 | 156 | <?php if ($_['userAvatarSet']): ?> |
| 157 | 157 | <img alt="" width="32" height="32" |
| 158 | - src="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 32, 'v' => $_['userAvatarVersion']]));?>" |
|
| 159 | - srcset="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 64, 'v' => $_['userAvatarVersion']]));?> 2x, <?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 128, 'v' => $_['userAvatarVersion']]));?> 4x" |
|
| 158 | + src="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 32, 'v' => $_['userAvatarVersion']])); ?>" |
|
| 159 | + srcset="<?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 64, 'v' => $_['userAvatarVersion']])); ?> 2x, <?php p(\OC::$server->getURLGenerator()->linkToRoute('core.avatar.getAvatar', ['userId' => $_['user_uid'], 'size' => 128, 'v' => $_['userAvatarVersion']])); ?> 4x" |
|
| 160 | 160 | > |
| 161 | 161 | <?php endif; ?> |
| 162 | 162 | </div> |
@@ -165,19 +165,19 @@ discard block |
||
| 165 | 165 | </div> |
| 166 | 166 | <div id="expanddiv"> |
| 167 | 167 | <ul> |
| 168 | - <?php foreach($_['settingsnavigation'] as $entry):?> |
|
| 168 | + <?php foreach ($_['settingsnavigation'] as $entry):?> |
|
| 169 | 169 | <li> |
| 170 | 170 | <a href="<?php print_unescaped($entry['href']); ?>" |
| 171 | - <?php if( $entry["active"] ): ?> class="active"<?php endif; ?>> |
|
| 172 | - <img alt="" src="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>"> |
|
| 171 | + <?php if ($entry["active"]): ?> class="active"<?php endif; ?>> |
|
| 172 | + <img alt="" src="<?php print_unescaped($entry['icon'].'?v='.$_['versionHash']); ?>"> |
|
| 173 | 173 | <?php p($entry['name']) ?> |
| 174 | 174 | </a> |
| 175 | 175 | </li> |
| 176 | 176 | <?php endforeach; ?> |
| 177 | 177 | <li> |
| 178 | 178 | <a id="logout" <?php print_unescaped(OC_User::getLogoutAttribute()); ?>> |
| 179 | - <img alt="" src="<?php print_unescaped(image_path('', 'actions/logout.svg') . '?v=' . $_['versionHash']); ?>"> |
|
| 180 | - <?php p($l->t('Log out'));?> |
|
| 179 | + <img alt="" src="<?php print_unescaped(image_path('', 'actions/logout.svg').'?v='.$_['versionHash']); ?>"> |
|
| 180 | + <?php p($l->t('Log out')); ?> |
|
| 181 | 181 | </a> |
| 182 | 182 | </li> |
| 183 | 183 | </ul> |
@@ -81,7 +81,10 @@ discard block |
||
| 81 | 81 | </a> |
| 82 | 82 | </li> |
| 83 | 83 | <?php if(OC_User::isAdminUser(OC_User::getUser())): ?> |
| 84 | - <li <?php if(count($_['navigation'])>$headerIconCount-1): ?> class="hidden apps-management"<?php else: ?> class="apps-management" <?php endif; ?>> |
|
| 84 | + <li <?php if(count($_['navigation'])>$headerIconCount-1): ?> class="hidden apps-management"<?php else { |
|
| 85 | + : ?> class="apps-management" <?php endif; |
|
| 86 | +} |
|
| 87 | +?>> |
|
| 85 | 88 | <a href="<?php print_unescaped(\OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')); ?>" tabindex="4" |
| 86 | 89 | <?php if( $_['appsmanagement_active'] ): ?> class="active"<?php endif; ?>> |
| 87 | 90 | <img src="<?php print_unescaped(image_path('settings', 'apps.svg') . '?v=' . $_['versionHash']); ?>" /> |
@@ -99,8 +102,11 @@ discard block |
||
| 99 | 102 | <?php foreach($_['navigation'] as $entry): ?> |
| 100 | 103 | <?php if($entry['showInHeader']): ?> |
| 101 | 104 | <li data-id="<?php p($entry['id']); ?>" class="in-header"> |
| 102 | - <?php else: ?> |
|
| 103 | - <li data-id="<?php p($entry['id']); ?>"> |
|
| 105 | + <?php else { |
|
| 106 | + : ?> |
|
| 107 | + <li data-id="<?php p($entry['id']); |
|
| 108 | +} |
|
| 109 | +?>"> |
|
| 104 | 110 | <?php endif; ?> |
| 105 | 111 | <a href="<?php print_unescaped($entry['href']); ?>" tabindex="3" |
| 106 | 112 | <?php if( $entry['active'] ): ?> class="active"<?php endif; ?>> |
@@ -41,397 +41,397 @@ |
||
| 41 | 41 | */ |
| 42 | 42 | class SystemTagManager implements ISystemTagManager { |
| 43 | 43 | |
| 44 | - const TAG_TABLE = 'systemtag'; |
|
| 45 | - const TAG_GROUP_TABLE = 'systemtag_group'; |
|
| 46 | - |
|
| 47 | - /** @var IDBConnection */ |
|
| 48 | - protected $connection; |
|
| 49 | - |
|
| 50 | - /** @var EventDispatcherInterface */ |
|
| 51 | - protected $dispatcher; |
|
| 52 | - |
|
| 53 | - /** @var IGroupManager */ |
|
| 54 | - protected $groupManager; |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * Prepared query for selecting tags directly |
|
| 58 | - * |
|
| 59 | - * @var \OCP\DB\QueryBuilder\IQueryBuilder |
|
| 60 | - */ |
|
| 61 | - private $selectTagQuery; |
|
| 62 | - |
|
| 63 | - /** |
|
| 64 | - * Constructor. |
|
| 65 | - * |
|
| 66 | - * @param IDBConnection $connection database connection |
|
| 67 | - * @param EventDispatcherInterface $dispatcher |
|
| 68 | - */ |
|
| 69 | - public function __construct( |
|
| 70 | - IDBConnection $connection, |
|
| 71 | - IGroupManager $groupManager, |
|
| 72 | - EventDispatcherInterface $dispatcher |
|
| 73 | - ) { |
|
| 74 | - $this->connection = $connection; |
|
| 75 | - $this->groupManager = $groupManager; |
|
| 76 | - $this->dispatcher = $dispatcher; |
|
| 77 | - |
|
| 78 | - $query = $this->connection->getQueryBuilder(); |
|
| 79 | - $this->selectTagQuery = $query->select('*') |
|
| 80 | - ->from(self::TAG_TABLE) |
|
| 81 | - ->where($query->expr()->eq('name', $query->createParameter('name'))) |
|
| 82 | - ->andWhere($query->expr()->eq('visibility', $query->createParameter('visibility'))) |
|
| 83 | - ->andWhere($query->expr()->eq('editable', $query->createParameter('editable'))); |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - /** |
|
| 87 | - * {@inheritdoc} |
|
| 88 | - */ |
|
| 89 | - public function getTagsByIds($tagIds) { |
|
| 90 | - if (!is_array($tagIds)) { |
|
| 91 | - $tagIds = [$tagIds]; |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - $tags = []; |
|
| 95 | - |
|
| 96 | - // note: not all databases will fail if it's a string or starts with a number |
|
| 97 | - foreach ($tagIds as $tagId) { |
|
| 98 | - if (!is_numeric($tagId)) { |
|
| 99 | - throw new \InvalidArgumentException('Tag id must be integer'); |
|
| 100 | - } |
|
| 101 | - } |
|
| 102 | - |
|
| 103 | - $query = $this->connection->getQueryBuilder(); |
|
| 104 | - $query->select('*') |
|
| 105 | - ->from(self::TAG_TABLE) |
|
| 106 | - ->where($query->expr()->in('id', $query->createParameter('tagids'))) |
|
| 107 | - ->addOrderBy('name', 'ASC') |
|
| 108 | - ->addOrderBy('visibility', 'ASC') |
|
| 109 | - ->addOrderBy('editable', 'ASC') |
|
| 110 | - ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY); |
|
| 111 | - |
|
| 112 | - $result = $query->execute(); |
|
| 113 | - while ($row = $result->fetch()) { |
|
| 114 | - $tags[$row['id']] = $this->createSystemTagFromRow($row); |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - $result->closeCursor(); |
|
| 118 | - |
|
| 119 | - if (count($tags) !== count($tagIds)) { |
|
| 120 | - throw new TagNotFoundException( |
|
| 121 | - 'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags)) |
|
| 122 | - ); |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - return $tags; |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * {@inheritdoc} |
|
| 130 | - */ |
|
| 131 | - public function getAllTags($visibilityFilter = null, $nameSearchPattern = null) { |
|
| 132 | - $tags = []; |
|
| 133 | - |
|
| 134 | - $query = $this->connection->getQueryBuilder(); |
|
| 135 | - $query->select('*') |
|
| 136 | - ->from(self::TAG_TABLE); |
|
| 137 | - |
|
| 138 | - if (!is_null($visibilityFilter)) { |
|
| 139 | - $query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter))); |
|
| 140 | - } |
|
| 141 | - |
|
| 142 | - if (!empty($nameSearchPattern)) { |
|
| 143 | - $query->andWhere( |
|
| 144 | - $query->expr()->like( |
|
| 145 | - 'name', |
|
| 146 | - $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($nameSearchPattern). '%') |
|
| 147 | - ) |
|
| 148 | - ); |
|
| 149 | - } |
|
| 150 | - |
|
| 151 | - $query |
|
| 152 | - ->addOrderBy('name', 'ASC') |
|
| 153 | - ->addOrderBy('visibility', 'ASC') |
|
| 154 | - ->addOrderBy('editable', 'ASC'); |
|
| 155 | - |
|
| 156 | - $result = $query->execute(); |
|
| 157 | - while ($row = $result->fetch()) { |
|
| 158 | - $tags[$row['id']] = $this->createSystemTagFromRow($row); |
|
| 159 | - } |
|
| 160 | - |
|
| 161 | - $result->closeCursor(); |
|
| 162 | - |
|
| 163 | - return $tags; |
|
| 164 | - } |
|
| 165 | - |
|
| 166 | - /** |
|
| 167 | - * {@inheritdoc} |
|
| 168 | - */ |
|
| 169 | - public function getTag($tagName, $userVisible, $userAssignable) { |
|
| 170 | - $userVisible = (int)$userVisible; |
|
| 171 | - $userAssignable = (int)$userAssignable; |
|
| 172 | - |
|
| 173 | - $result = $this->selectTagQuery |
|
| 174 | - ->setParameter('name', $tagName) |
|
| 175 | - ->setParameter('visibility', $userVisible) |
|
| 176 | - ->setParameter('editable', $userAssignable) |
|
| 177 | - ->execute(); |
|
| 178 | - |
|
| 179 | - $row = $result->fetch(); |
|
| 180 | - $result->closeCursor(); |
|
| 181 | - if (!$row) { |
|
| 182 | - throw new TagNotFoundException( |
|
| 183 | - 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') does not exist' |
|
| 184 | - ); |
|
| 185 | - } |
|
| 186 | - |
|
| 187 | - return $this->createSystemTagFromRow($row); |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - /** |
|
| 191 | - * {@inheritdoc} |
|
| 192 | - */ |
|
| 193 | - public function createTag($tagName, $userVisible, $userAssignable) { |
|
| 194 | - $userVisible = (int)$userVisible; |
|
| 195 | - $userAssignable = (int)$userAssignable; |
|
| 196 | - |
|
| 197 | - $query = $this->connection->getQueryBuilder(); |
|
| 198 | - $query->insert(self::TAG_TABLE) |
|
| 199 | - ->values([ |
|
| 200 | - 'name' => $query->createNamedParameter($tagName), |
|
| 201 | - 'visibility' => $query->createNamedParameter($userVisible), |
|
| 202 | - 'editable' => $query->createNamedParameter($userAssignable), |
|
| 203 | - ]); |
|
| 204 | - |
|
| 205 | - try { |
|
| 206 | - $query->execute(); |
|
| 207 | - } catch (UniqueConstraintViolationException $e) { |
|
| 208 | - throw new TagAlreadyExistsException( |
|
| 209 | - 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists', |
|
| 210 | - 0, |
|
| 211 | - $e |
|
| 212 | - ); |
|
| 213 | - } |
|
| 214 | - |
|
| 215 | - $tagId = $query->getLastInsertId(); |
|
| 216 | - |
|
| 217 | - $tag = new SystemTag( |
|
| 218 | - (int)$tagId, |
|
| 219 | - $tagName, |
|
| 220 | - (bool)$userVisible, |
|
| 221 | - (bool)$userAssignable |
|
| 222 | - ); |
|
| 223 | - |
|
| 224 | - $this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent( |
|
| 225 | - ManagerEvent::EVENT_CREATE, $tag |
|
| 226 | - )); |
|
| 227 | - |
|
| 228 | - return $tag; |
|
| 229 | - } |
|
| 230 | - |
|
| 231 | - /** |
|
| 232 | - * {@inheritdoc} |
|
| 233 | - */ |
|
| 234 | - public function updateTag($tagId, $tagName, $userVisible, $userAssignable) { |
|
| 235 | - $userVisible = (int)$userVisible; |
|
| 236 | - $userAssignable = (int)$userAssignable; |
|
| 237 | - |
|
| 238 | - try { |
|
| 239 | - $tags = $this->getTagsByIds($tagId); |
|
| 240 | - } catch (TagNotFoundException $e) { |
|
| 241 | - throw new TagNotFoundException( |
|
| 242 | - 'Tag does not exist', 0, null, [$tagId] |
|
| 243 | - ); |
|
| 244 | - } |
|
| 245 | - |
|
| 246 | - $beforeUpdate = array_shift($tags); |
|
| 247 | - $afterUpdate = new SystemTag( |
|
| 248 | - (int) $tagId, |
|
| 249 | - $tagName, |
|
| 250 | - (bool) $userVisible, |
|
| 251 | - (bool) $userAssignable |
|
| 252 | - ); |
|
| 253 | - |
|
| 254 | - $query = $this->connection->getQueryBuilder(); |
|
| 255 | - $query->update(self::TAG_TABLE) |
|
| 256 | - ->set('name', $query->createParameter('name')) |
|
| 257 | - ->set('visibility', $query->createParameter('visibility')) |
|
| 258 | - ->set('editable', $query->createParameter('editable')) |
|
| 259 | - ->where($query->expr()->eq('id', $query->createParameter('tagid'))) |
|
| 260 | - ->setParameter('name', $tagName) |
|
| 261 | - ->setParameter('visibility', $userVisible) |
|
| 262 | - ->setParameter('editable', $userAssignable) |
|
| 263 | - ->setParameter('tagid', $tagId); |
|
| 264 | - |
|
| 265 | - try { |
|
| 266 | - if ($query->execute() === 0) { |
|
| 267 | - throw new TagNotFoundException( |
|
| 268 | - 'Tag does not exist', 0, null, [$tagId] |
|
| 269 | - ); |
|
| 270 | - } |
|
| 271 | - } catch (UniqueConstraintViolationException $e) { |
|
| 272 | - throw new TagAlreadyExistsException( |
|
| 273 | - 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists', |
|
| 274 | - 0, |
|
| 275 | - $e |
|
| 276 | - ); |
|
| 277 | - } |
|
| 278 | - |
|
| 279 | - $this->dispatcher->dispatch(ManagerEvent::EVENT_UPDATE, new ManagerEvent( |
|
| 280 | - ManagerEvent::EVENT_UPDATE, $afterUpdate, $beforeUpdate |
|
| 281 | - )); |
|
| 282 | - } |
|
| 283 | - |
|
| 284 | - /** |
|
| 285 | - * {@inheritdoc} |
|
| 286 | - */ |
|
| 287 | - public function deleteTags($tagIds) { |
|
| 288 | - if (!is_array($tagIds)) { |
|
| 289 | - $tagIds = [$tagIds]; |
|
| 290 | - } |
|
| 291 | - |
|
| 292 | - $tagNotFoundException = null; |
|
| 293 | - $tags = []; |
|
| 294 | - try { |
|
| 295 | - $tags = $this->getTagsByIds($tagIds); |
|
| 296 | - } catch (TagNotFoundException $e) { |
|
| 297 | - $tagNotFoundException = $e; |
|
| 298 | - |
|
| 299 | - // Get existing tag objects for the hooks later |
|
| 300 | - $existingTags = array_diff($tagIds, $tagNotFoundException->getMissingTags()); |
|
| 301 | - if (!empty($existingTags)) { |
|
| 302 | - try { |
|
| 303 | - $tags = $this->getTagsByIds($existingTags); |
|
| 304 | - } catch (TagNotFoundException $e) { |
|
| 305 | - // Ignore further errors... |
|
| 306 | - } |
|
| 307 | - } |
|
| 308 | - } |
|
| 309 | - |
|
| 310 | - // delete relationships first |
|
| 311 | - $query = $this->connection->getQueryBuilder(); |
|
| 312 | - $query->delete(SystemTagObjectMapper::RELATION_TABLE) |
|
| 313 | - ->where($query->expr()->in('systemtagid', $query->createParameter('tagids'))) |
|
| 314 | - ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) |
|
| 315 | - ->execute(); |
|
| 316 | - |
|
| 317 | - $query = $this->connection->getQueryBuilder(); |
|
| 318 | - $query->delete(self::TAG_TABLE) |
|
| 319 | - ->where($query->expr()->in('id', $query->createParameter('tagids'))) |
|
| 320 | - ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) |
|
| 321 | - ->execute(); |
|
| 322 | - |
|
| 323 | - foreach ($tags as $tag) { |
|
| 324 | - $this->dispatcher->dispatch(ManagerEvent::EVENT_DELETE, new ManagerEvent( |
|
| 325 | - ManagerEvent::EVENT_DELETE, $tag |
|
| 326 | - )); |
|
| 327 | - } |
|
| 328 | - |
|
| 329 | - if ($tagNotFoundException !== null) { |
|
| 330 | - throw new TagNotFoundException( |
|
| 331 | - 'Tag id(s) not found', 0, $tagNotFoundException, $tagNotFoundException->getMissingTags() |
|
| 332 | - ); |
|
| 333 | - } |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * {@inheritdoc} |
|
| 338 | - */ |
|
| 339 | - public function canUserAssignTag(ISystemTag $tag, IUser $user) { |
|
| 340 | - // early check to avoid unneeded group lookups |
|
| 341 | - if ($tag->isUserAssignable() && $tag->isUserVisible()) { |
|
| 342 | - return true; |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - if ($this->groupManager->isAdmin($user->getUID())) { |
|
| 346 | - return true; |
|
| 347 | - } |
|
| 348 | - |
|
| 349 | - if (!$tag->isUserVisible()) { |
|
| 350 | - return false; |
|
| 351 | - } |
|
| 352 | - |
|
| 353 | - $groupIds = $this->groupManager->getUserGroupIds($user); |
|
| 354 | - if (!empty($groupIds)) { |
|
| 355 | - $matchingGroups = array_intersect($groupIds, $this->getTagGroups($tag)); |
|
| 356 | - if (!empty($matchingGroups)) { |
|
| 357 | - return true; |
|
| 358 | - } |
|
| 359 | - } |
|
| 360 | - |
|
| 361 | - return false; |
|
| 362 | - } |
|
| 363 | - |
|
| 364 | - /** |
|
| 365 | - * {@inheritdoc} |
|
| 366 | - */ |
|
| 367 | - public function canUserSeeTag(ISystemTag $tag, IUser $user) { |
|
| 368 | - if ($tag->isUserVisible()) { |
|
| 369 | - return true; |
|
| 370 | - } |
|
| 371 | - |
|
| 372 | - if ($this->groupManager->isAdmin($user->getUID())) { |
|
| 373 | - return true; |
|
| 374 | - } |
|
| 375 | - |
|
| 376 | - return false; |
|
| 377 | - } |
|
| 378 | - |
|
| 379 | - private function createSystemTagFromRow($row) { |
|
| 380 | - return new SystemTag((int)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); |
|
| 381 | - } |
|
| 382 | - |
|
| 383 | - /** |
|
| 384 | - * {@inheritdoc} |
|
| 385 | - */ |
|
| 386 | - public function setTagGroups(ISystemTag $tag, $groupIds) { |
|
| 387 | - // delete relationships first |
|
| 388 | - $this->connection->beginTransaction(); |
|
| 389 | - try { |
|
| 390 | - $query = $this->connection->getQueryBuilder(); |
|
| 391 | - $query->delete(self::TAG_GROUP_TABLE) |
|
| 392 | - ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) |
|
| 393 | - ->execute(); |
|
| 394 | - |
|
| 395 | - // add each group id |
|
| 396 | - $query = $this->connection->getQueryBuilder(); |
|
| 397 | - $query->insert(self::TAG_GROUP_TABLE) |
|
| 398 | - ->values([ |
|
| 399 | - 'systemtagid' => $query->createNamedParameter($tag->getId()), |
|
| 400 | - 'gid' => $query->createParameter('gid'), |
|
| 401 | - ]); |
|
| 402 | - foreach ($groupIds as $groupId) { |
|
| 403 | - if ($groupId === '') { |
|
| 404 | - continue; |
|
| 405 | - } |
|
| 406 | - $query->setParameter('gid', $groupId); |
|
| 407 | - $query->execute(); |
|
| 408 | - } |
|
| 409 | - |
|
| 410 | - $this->connection->commit(); |
|
| 411 | - } catch (\Exception $e) { |
|
| 412 | - $this->connection->rollback(); |
|
| 413 | - throw $e; |
|
| 414 | - } |
|
| 415 | - } |
|
| 416 | - |
|
| 417 | - /** |
|
| 418 | - * {@inheritdoc} |
|
| 419 | - */ |
|
| 420 | - public function getTagGroups(ISystemTag $tag) { |
|
| 421 | - $groupIds = []; |
|
| 422 | - $query = $this->connection->getQueryBuilder(); |
|
| 423 | - $query->select('gid') |
|
| 424 | - ->from(self::TAG_GROUP_TABLE) |
|
| 425 | - ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) |
|
| 426 | - ->orderBy('gid'); |
|
| 427 | - |
|
| 428 | - $result = $query->execute(); |
|
| 429 | - while ($row = $result->fetch()) { |
|
| 430 | - $groupIds[] = $row['gid']; |
|
| 431 | - } |
|
| 432 | - |
|
| 433 | - $result->closeCursor(); |
|
| 434 | - |
|
| 435 | - return $groupIds; |
|
| 436 | - } |
|
| 44 | + const TAG_TABLE = 'systemtag'; |
|
| 45 | + const TAG_GROUP_TABLE = 'systemtag_group'; |
|
| 46 | + |
|
| 47 | + /** @var IDBConnection */ |
|
| 48 | + protected $connection; |
|
| 49 | + |
|
| 50 | + /** @var EventDispatcherInterface */ |
|
| 51 | + protected $dispatcher; |
|
| 52 | + |
|
| 53 | + /** @var IGroupManager */ |
|
| 54 | + protected $groupManager; |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * Prepared query for selecting tags directly |
|
| 58 | + * |
|
| 59 | + * @var \OCP\DB\QueryBuilder\IQueryBuilder |
|
| 60 | + */ |
|
| 61 | + private $selectTagQuery; |
|
| 62 | + |
|
| 63 | + /** |
|
| 64 | + * Constructor. |
|
| 65 | + * |
|
| 66 | + * @param IDBConnection $connection database connection |
|
| 67 | + * @param EventDispatcherInterface $dispatcher |
|
| 68 | + */ |
|
| 69 | + public function __construct( |
|
| 70 | + IDBConnection $connection, |
|
| 71 | + IGroupManager $groupManager, |
|
| 72 | + EventDispatcherInterface $dispatcher |
|
| 73 | + ) { |
|
| 74 | + $this->connection = $connection; |
|
| 75 | + $this->groupManager = $groupManager; |
|
| 76 | + $this->dispatcher = $dispatcher; |
|
| 77 | + |
|
| 78 | + $query = $this->connection->getQueryBuilder(); |
|
| 79 | + $this->selectTagQuery = $query->select('*') |
|
| 80 | + ->from(self::TAG_TABLE) |
|
| 81 | + ->where($query->expr()->eq('name', $query->createParameter('name'))) |
|
| 82 | + ->andWhere($query->expr()->eq('visibility', $query->createParameter('visibility'))) |
|
| 83 | + ->andWhere($query->expr()->eq('editable', $query->createParameter('editable'))); |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + /** |
|
| 87 | + * {@inheritdoc} |
|
| 88 | + */ |
|
| 89 | + public function getTagsByIds($tagIds) { |
|
| 90 | + if (!is_array($tagIds)) { |
|
| 91 | + $tagIds = [$tagIds]; |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + $tags = []; |
|
| 95 | + |
|
| 96 | + // note: not all databases will fail if it's a string or starts with a number |
|
| 97 | + foreach ($tagIds as $tagId) { |
|
| 98 | + if (!is_numeric($tagId)) { |
|
| 99 | + throw new \InvalidArgumentException('Tag id must be integer'); |
|
| 100 | + } |
|
| 101 | + } |
|
| 102 | + |
|
| 103 | + $query = $this->connection->getQueryBuilder(); |
|
| 104 | + $query->select('*') |
|
| 105 | + ->from(self::TAG_TABLE) |
|
| 106 | + ->where($query->expr()->in('id', $query->createParameter('tagids'))) |
|
| 107 | + ->addOrderBy('name', 'ASC') |
|
| 108 | + ->addOrderBy('visibility', 'ASC') |
|
| 109 | + ->addOrderBy('editable', 'ASC') |
|
| 110 | + ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY); |
|
| 111 | + |
|
| 112 | + $result = $query->execute(); |
|
| 113 | + while ($row = $result->fetch()) { |
|
| 114 | + $tags[$row['id']] = $this->createSystemTagFromRow($row); |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + $result->closeCursor(); |
|
| 118 | + |
|
| 119 | + if (count($tags) !== count($tagIds)) { |
|
| 120 | + throw new TagNotFoundException( |
|
| 121 | + 'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags)) |
|
| 122 | + ); |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + return $tags; |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * {@inheritdoc} |
|
| 130 | + */ |
|
| 131 | + public function getAllTags($visibilityFilter = null, $nameSearchPattern = null) { |
|
| 132 | + $tags = []; |
|
| 133 | + |
|
| 134 | + $query = $this->connection->getQueryBuilder(); |
|
| 135 | + $query->select('*') |
|
| 136 | + ->from(self::TAG_TABLE); |
|
| 137 | + |
|
| 138 | + if (!is_null($visibilityFilter)) { |
|
| 139 | + $query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter))); |
|
| 140 | + } |
|
| 141 | + |
|
| 142 | + if (!empty($nameSearchPattern)) { |
|
| 143 | + $query->andWhere( |
|
| 144 | + $query->expr()->like( |
|
| 145 | + 'name', |
|
| 146 | + $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($nameSearchPattern). '%') |
|
| 147 | + ) |
|
| 148 | + ); |
|
| 149 | + } |
|
| 150 | + |
|
| 151 | + $query |
|
| 152 | + ->addOrderBy('name', 'ASC') |
|
| 153 | + ->addOrderBy('visibility', 'ASC') |
|
| 154 | + ->addOrderBy('editable', 'ASC'); |
|
| 155 | + |
|
| 156 | + $result = $query->execute(); |
|
| 157 | + while ($row = $result->fetch()) { |
|
| 158 | + $tags[$row['id']] = $this->createSystemTagFromRow($row); |
|
| 159 | + } |
|
| 160 | + |
|
| 161 | + $result->closeCursor(); |
|
| 162 | + |
|
| 163 | + return $tags; |
|
| 164 | + } |
|
| 165 | + |
|
| 166 | + /** |
|
| 167 | + * {@inheritdoc} |
|
| 168 | + */ |
|
| 169 | + public function getTag($tagName, $userVisible, $userAssignable) { |
|
| 170 | + $userVisible = (int)$userVisible; |
|
| 171 | + $userAssignable = (int)$userAssignable; |
|
| 172 | + |
|
| 173 | + $result = $this->selectTagQuery |
|
| 174 | + ->setParameter('name', $tagName) |
|
| 175 | + ->setParameter('visibility', $userVisible) |
|
| 176 | + ->setParameter('editable', $userAssignable) |
|
| 177 | + ->execute(); |
|
| 178 | + |
|
| 179 | + $row = $result->fetch(); |
|
| 180 | + $result->closeCursor(); |
|
| 181 | + if (!$row) { |
|
| 182 | + throw new TagNotFoundException( |
|
| 183 | + 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') does not exist' |
|
| 184 | + ); |
|
| 185 | + } |
|
| 186 | + |
|
| 187 | + return $this->createSystemTagFromRow($row); |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + /** |
|
| 191 | + * {@inheritdoc} |
|
| 192 | + */ |
|
| 193 | + public function createTag($tagName, $userVisible, $userAssignable) { |
|
| 194 | + $userVisible = (int)$userVisible; |
|
| 195 | + $userAssignable = (int)$userAssignable; |
|
| 196 | + |
|
| 197 | + $query = $this->connection->getQueryBuilder(); |
|
| 198 | + $query->insert(self::TAG_TABLE) |
|
| 199 | + ->values([ |
|
| 200 | + 'name' => $query->createNamedParameter($tagName), |
|
| 201 | + 'visibility' => $query->createNamedParameter($userVisible), |
|
| 202 | + 'editable' => $query->createNamedParameter($userAssignable), |
|
| 203 | + ]); |
|
| 204 | + |
|
| 205 | + try { |
|
| 206 | + $query->execute(); |
|
| 207 | + } catch (UniqueConstraintViolationException $e) { |
|
| 208 | + throw new TagAlreadyExistsException( |
|
| 209 | + 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists', |
|
| 210 | + 0, |
|
| 211 | + $e |
|
| 212 | + ); |
|
| 213 | + } |
|
| 214 | + |
|
| 215 | + $tagId = $query->getLastInsertId(); |
|
| 216 | + |
|
| 217 | + $tag = new SystemTag( |
|
| 218 | + (int)$tagId, |
|
| 219 | + $tagName, |
|
| 220 | + (bool)$userVisible, |
|
| 221 | + (bool)$userAssignable |
|
| 222 | + ); |
|
| 223 | + |
|
| 224 | + $this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent( |
|
| 225 | + ManagerEvent::EVENT_CREATE, $tag |
|
| 226 | + )); |
|
| 227 | + |
|
| 228 | + return $tag; |
|
| 229 | + } |
|
| 230 | + |
|
| 231 | + /** |
|
| 232 | + * {@inheritdoc} |
|
| 233 | + */ |
|
| 234 | + public function updateTag($tagId, $tagName, $userVisible, $userAssignable) { |
|
| 235 | + $userVisible = (int)$userVisible; |
|
| 236 | + $userAssignable = (int)$userAssignable; |
|
| 237 | + |
|
| 238 | + try { |
|
| 239 | + $tags = $this->getTagsByIds($tagId); |
|
| 240 | + } catch (TagNotFoundException $e) { |
|
| 241 | + throw new TagNotFoundException( |
|
| 242 | + 'Tag does not exist', 0, null, [$tagId] |
|
| 243 | + ); |
|
| 244 | + } |
|
| 245 | + |
|
| 246 | + $beforeUpdate = array_shift($tags); |
|
| 247 | + $afterUpdate = new SystemTag( |
|
| 248 | + (int) $tagId, |
|
| 249 | + $tagName, |
|
| 250 | + (bool) $userVisible, |
|
| 251 | + (bool) $userAssignable |
|
| 252 | + ); |
|
| 253 | + |
|
| 254 | + $query = $this->connection->getQueryBuilder(); |
|
| 255 | + $query->update(self::TAG_TABLE) |
|
| 256 | + ->set('name', $query->createParameter('name')) |
|
| 257 | + ->set('visibility', $query->createParameter('visibility')) |
|
| 258 | + ->set('editable', $query->createParameter('editable')) |
|
| 259 | + ->where($query->expr()->eq('id', $query->createParameter('tagid'))) |
|
| 260 | + ->setParameter('name', $tagName) |
|
| 261 | + ->setParameter('visibility', $userVisible) |
|
| 262 | + ->setParameter('editable', $userAssignable) |
|
| 263 | + ->setParameter('tagid', $tagId); |
|
| 264 | + |
|
| 265 | + try { |
|
| 266 | + if ($query->execute() === 0) { |
|
| 267 | + throw new TagNotFoundException( |
|
| 268 | + 'Tag does not exist', 0, null, [$tagId] |
|
| 269 | + ); |
|
| 270 | + } |
|
| 271 | + } catch (UniqueConstraintViolationException $e) { |
|
| 272 | + throw new TagAlreadyExistsException( |
|
| 273 | + 'Tag ("' . $tagName . '", '. $userVisible . ', ' . $userAssignable . ') already exists', |
|
| 274 | + 0, |
|
| 275 | + $e |
|
| 276 | + ); |
|
| 277 | + } |
|
| 278 | + |
|
| 279 | + $this->dispatcher->dispatch(ManagerEvent::EVENT_UPDATE, new ManagerEvent( |
|
| 280 | + ManagerEvent::EVENT_UPDATE, $afterUpdate, $beforeUpdate |
|
| 281 | + )); |
|
| 282 | + } |
|
| 283 | + |
|
| 284 | + /** |
|
| 285 | + * {@inheritdoc} |
|
| 286 | + */ |
|
| 287 | + public function deleteTags($tagIds) { |
|
| 288 | + if (!is_array($tagIds)) { |
|
| 289 | + $tagIds = [$tagIds]; |
|
| 290 | + } |
|
| 291 | + |
|
| 292 | + $tagNotFoundException = null; |
|
| 293 | + $tags = []; |
|
| 294 | + try { |
|
| 295 | + $tags = $this->getTagsByIds($tagIds); |
|
| 296 | + } catch (TagNotFoundException $e) { |
|
| 297 | + $tagNotFoundException = $e; |
|
| 298 | + |
|
| 299 | + // Get existing tag objects for the hooks later |
|
| 300 | + $existingTags = array_diff($tagIds, $tagNotFoundException->getMissingTags()); |
|
| 301 | + if (!empty($existingTags)) { |
|
| 302 | + try { |
|
| 303 | + $tags = $this->getTagsByIds($existingTags); |
|
| 304 | + } catch (TagNotFoundException $e) { |
|
| 305 | + // Ignore further errors... |
|
| 306 | + } |
|
| 307 | + } |
|
| 308 | + } |
|
| 309 | + |
|
| 310 | + // delete relationships first |
|
| 311 | + $query = $this->connection->getQueryBuilder(); |
|
| 312 | + $query->delete(SystemTagObjectMapper::RELATION_TABLE) |
|
| 313 | + ->where($query->expr()->in('systemtagid', $query->createParameter('tagids'))) |
|
| 314 | + ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) |
|
| 315 | + ->execute(); |
|
| 316 | + |
|
| 317 | + $query = $this->connection->getQueryBuilder(); |
|
| 318 | + $query->delete(self::TAG_TABLE) |
|
| 319 | + ->where($query->expr()->in('id', $query->createParameter('tagids'))) |
|
| 320 | + ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) |
|
| 321 | + ->execute(); |
|
| 322 | + |
|
| 323 | + foreach ($tags as $tag) { |
|
| 324 | + $this->dispatcher->dispatch(ManagerEvent::EVENT_DELETE, new ManagerEvent( |
|
| 325 | + ManagerEvent::EVENT_DELETE, $tag |
|
| 326 | + )); |
|
| 327 | + } |
|
| 328 | + |
|
| 329 | + if ($tagNotFoundException !== null) { |
|
| 330 | + throw new TagNotFoundException( |
|
| 331 | + 'Tag id(s) not found', 0, $tagNotFoundException, $tagNotFoundException->getMissingTags() |
|
| 332 | + ); |
|
| 333 | + } |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * {@inheritdoc} |
|
| 338 | + */ |
|
| 339 | + public function canUserAssignTag(ISystemTag $tag, IUser $user) { |
|
| 340 | + // early check to avoid unneeded group lookups |
|
| 341 | + if ($tag->isUserAssignable() && $tag->isUserVisible()) { |
|
| 342 | + return true; |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + if ($this->groupManager->isAdmin($user->getUID())) { |
|
| 346 | + return true; |
|
| 347 | + } |
|
| 348 | + |
|
| 349 | + if (!$tag->isUserVisible()) { |
|
| 350 | + return false; |
|
| 351 | + } |
|
| 352 | + |
|
| 353 | + $groupIds = $this->groupManager->getUserGroupIds($user); |
|
| 354 | + if (!empty($groupIds)) { |
|
| 355 | + $matchingGroups = array_intersect($groupIds, $this->getTagGroups($tag)); |
|
| 356 | + if (!empty($matchingGroups)) { |
|
| 357 | + return true; |
|
| 358 | + } |
|
| 359 | + } |
|
| 360 | + |
|
| 361 | + return false; |
|
| 362 | + } |
|
| 363 | + |
|
| 364 | + /** |
|
| 365 | + * {@inheritdoc} |
|
| 366 | + */ |
|
| 367 | + public function canUserSeeTag(ISystemTag $tag, IUser $user) { |
|
| 368 | + if ($tag->isUserVisible()) { |
|
| 369 | + return true; |
|
| 370 | + } |
|
| 371 | + |
|
| 372 | + if ($this->groupManager->isAdmin($user->getUID())) { |
|
| 373 | + return true; |
|
| 374 | + } |
|
| 375 | + |
|
| 376 | + return false; |
|
| 377 | + } |
|
| 378 | + |
|
| 379 | + private function createSystemTagFromRow($row) { |
|
| 380 | + return new SystemTag((int)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); |
|
| 381 | + } |
|
| 382 | + |
|
| 383 | + /** |
|
| 384 | + * {@inheritdoc} |
|
| 385 | + */ |
|
| 386 | + public function setTagGroups(ISystemTag $tag, $groupIds) { |
|
| 387 | + // delete relationships first |
|
| 388 | + $this->connection->beginTransaction(); |
|
| 389 | + try { |
|
| 390 | + $query = $this->connection->getQueryBuilder(); |
|
| 391 | + $query->delete(self::TAG_GROUP_TABLE) |
|
| 392 | + ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) |
|
| 393 | + ->execute(); |
|
| 394 | + |
|
| 395 | + // add each group id |
|
| 396 | + $query = $this->connection->getQueryBuilder(); |
|
| 397 | + $query->insert(self::TAG_GROUP_TABLE) |
|
| 398 | + ->values([ |
|
| 399 | + 'systemtagid' => $query->createNamedParameter($tag->getId()), |
|
| 400 | + 'gid' => $query->createParameter('gid'), |
|
| 401 | + ]); |
|
| 402 | + foreach ($groupIds as $groupId) { |
|
| 403 | + if ($groupId === '') { |
|
| 404 | + continue; |
|
| 405 | + } |
|
| 406 | + $query->setParameter('gid', $groupId); |
|
| 407 | + $query->execute(); |
|
| 408 | + } |
|
| 409 | + |
|
| 410 | + $this->connection->commit(); |
|
| 411 | + } catch (\Exception $e) { |
|
| 412 | + $this->connection->rollback(); |
|
| 413 | + throw $e; |
|
| 414 | + } |
|
| 415 | + } |
|
| 416 | + |
|
| 417 | + /** |
|
| 418 | + * {@inheritdoc} |
|
| 419 | + */ |
|
| 420 | + public function getTagGroups(ISystemTag $tag) { |
|
| 421 | + $groupIds = []; |
|
| 422 | + $query = $this->connection->getQueryBuilder(); |
|
| 423 | + $query->select('gid') |
|
| 424 | + ->from(self::TAG_GROUP_TABLE) |
|
| 425 | + ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tag->getId()))) |
|
| 426 | + ->orderBy('gid'); |
|
| 427 | + |
|
| 428 | + $result = $query->execute(); |
|
| 429 | + while ($row = $result->fetch()) { |
|
| 430 | + $groupIds[] = $row['gid']; |
|
| 431 | + } |
|
| 432 | + |
|
| 433 | + $result->closeCursor(); |
|
| 434 | + |
|
| 435 | + return $groupIds; |
|
| 436 | + } |
|
| 437 | 437 | } |
@@ -11,14 +11,14 @@ discard block |
||
| 11 | 11 | <div id="app-navigation"> |
| 12 | 12 | <ul class="with-icon"> |
| 13 | 13 | <?php foreach($_['forms'] as $form) { |
| 14 | - if (isset($form['anchor'])) { |
|
| 15 | - $anchor = '#' . $form['anchor']; |
|
| 16 | - $class = 'nav-icon-' . $form['anchor']; |
|
| 17 | - $sectionName = $form['section-name']; |
|
| 18 | - print_unescaped(sprintf("<li><a href='%s' class='%s'>%s</a></li>", \OCP\Util::sanitizeHTML($anchor), |
|
| 19 | - \OCP\Util::sanitizeHTML($class), \OCP\Util::sanitizeHTML($sectionName))); |
|
| 20 | - } |
|
| 21 | - }?> |
|
| 14 | + if (isset($form['anchor'])) { |
|
| 15 | + $anchor = '#' . $form['anchor']; |
|
| 16 | + $class = 'nav-icon-' . $form['anchor']; |
|
| 17 | + $sectionName = $form['section-name']; |
|
| 18 | + print_unescaped(sprintf("<li><a href='%s' class='%s'>%s</a></li>", \OCP\Util::sanitizeHTML($anchor), |
|
| 19 | + \OCP\Util::sanitizeHTML($class), \OCP\Util::sanitizeHTML($sectionName))); |
|
| 20 | + } |
|
| 21 | + }?> |
|
| 22 | 22 | </ul> |
| 23 | 23 | </div> |
| 24 | 24 | |
@@ -30,10 +30,10 @@ discard block |
||
| 30 | 30 | <p id="quotatext"> |
| 31 | 31 | <?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?> |
| 32 | 32 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong>', |
| 33 | - [$_['usage'], $_['total_space']]));?> |
|
| 33 | + [$_['usage'], $_['total_space']]));?> |
|
| 34 | 34 | <?php else: ?> |
| 35 | 35 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)', |
| 36 | - [$_['usage'], $_['total_space'], $_['usage_relative']]));?> |
|
| 36 | + [$_['usage'], $_['total_space'], $_['usage_relative']]));?> |
|
| 37 | 37 | <?php endif ?> |
| 38 | 38 | </p> |
| 39 | 39 | </div> |
@@ -179,7 +179,7 @@ discard block |
||
| 179 | 179 | |
| 180 | 180 | <?php |
| 181 | 181 | if($_['passwordChangeSupported']) { |
| 182 | - script('jquery-showpassword'); |
|
| 182 | + script('jquery-showpassword'); |
|
| 183 | 183 | ?> |
| 184 | 184 | <form id="passwordform" class="section"> |
| 185 | 185 | <h2 class="inlineblock"><?php p($l->t('Password'));?></h2> |
@@ -248,15 +248,15 @@ discard block |
||
| 248 | 248 | |
| 249 | 249 | <p> |
| 250 | 250 | <?php print_unescaped(str_replace( |
| 251 | - [ |
|
| 252 | - '{contributeopen}', |
|
| 253 | - '{linkclose}', |
|
| 254 | - ], |
|
| 255 | - [ |
|
| 256 | - '<a href="https://nextcloud.com/contribute" target="_blank" rel="noreferrer">', |
|
| 257 | - '</a>', |
|
| 258 | - ], |
|
| 259 | - $l->t('If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!'))); ?> |
|
| 251 | + [ |
|
| 252 | + '{contributeopen}', |
|
| 253 | + '{linkclose}', |
|
| 254 | + ], |
|
| 255 | + [ |
|
| 256 | + '<a href="https://nextcloud.com/contribute" target="_blank" rel="noreferrer">', |
|
| 257 | + '</a>', |
|
| 258 | + ], |
|
| 259 | + $l->t('If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!'))); ?> |
|
| 260 | 260 | </p> |
| 261 | 261 | |
| 262 | 262 | <?php if(OC_APP::isEnabled('firstrunwizard')) {?> |
@@ -317,7 +317,7 @@ discard block |
||
| 317 | 317 | </div> |
| 318 | 318 | |
| 319 | 319 | <?php foreach($_['forms'] as $form) { |
| 320 | - if (isset($form['form'])) {?> |
|
| 320 | + if (isset($form['form'])) {?> |
|
| 321 | 321 | <div id="<?php isset($form['anchor']) ? p($form['anchor']) : p('');?>"><?php print_unescaped($form['form']);?></div> |
| 322 | 322 | <?php } |
| 323 | 323 | };?> |
@@ -10,10 +10,10 @@ discard block |
||
| 10 | 10 | |
| 11 | 11 | <div id="app-navigation"> |
| 12 | 12 | <ul class="with-icon"> |
| 13 | - <?php foreach($_['forms'] as $form) { |
|
| 13 | + <?php foreach ($_['forms'] as $form) { |
|
| 14 | 14 | if (isset($form['anchor'])) { |
| 15 | - $anchor = '#' . $form['anchor']; |
|
| 16 | - $class = 'nav-icon-' . $form['anchor']; |
|
| 15 | + $anchor = '#'.$form['anchor']; |
|
| 16 | + $class = 'nav-icon-'.$form['anchor']; |
|
| 17 | 17 | $sectionName = $form['section-name']; |
| 18 | 18 | print_unescaped(sprintf("<li><a href='%s' class='%s'>%s</a></li>", \OCP\Util::sanitizeHTML($anchor), |
| 19 | 19 | \OCP\Util::sanitizeHTML($class), \OCP\Util::sanitizeHTML($sectionName))); |
@@ -25,15 +25,15 @@ discard block |
||
| 25 | 25 | <div id="app-content"> |
| 26 | 26 | |
| 27 | 27 | <div id="quota" class="section"> |
| 28 | - <div style="width:<?php p($_['usage_relative']);?>%" |
|
| 29 | - <?php if($_['usage_relative'] > 80): ?> class="quota-warning" <?php endif; ?>> |
|
| 28 | + <div style="width:<?php p($_['usage_relative']); ?>%" |
|
| 29 | + <?php if ($_['usage_relative'] > 80): ?> class="quota-warning" <?php endif; ?>> |
|
| 30 | 30 | <p id="quotatext"> |
| 31 | 31 | <?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?> |
| 32 | 32 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong>', |
| 33 | - [$_['usage'], $_['total_space']]));?> |
|
| 33 | + [$_['usage'], $_['total_space']])); ?> |
|
| 34 | 34 | <?php else: ?> |
| 35 | 35 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)', |
| 36 | - [$_['usage'], $_['total_space'], $_['usage_relative']]));?> |
|
| 36 | + [$_['usage'], $_['total_space'], $_['usage_relative']])); ?> |
|
| 37 | 37 | <?php endif ?> |
| 38 | 38 | </p> |
| 39 | 39 | </div> |
@@ -79,11 +79,11 @@ discard block |
||
| 79 | 79 | <span class="icon-password"/> |
| 80 | 80 | </h2> |
| 81 | 81 | <input type="text" id="displayname" name="displayname" |
| 82 | - <?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> |
|
| 82 | + <?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> |
|
| 83 | 83 | value="<?php p($_['displayName']) ?>" |
| 84 | 84 | autocomplete="on" autocapitalize="off" autocorrect="off" /> |
| 85 | - <?php if(!$_['displayNameChangeSupported']) { ?> |
|
| 86 | - <span><?php if(isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span> |
|
| 85 | + <?php if (!$_['displayNameChangeSupported']) { ?> |
|
| 86 | + <span><?php if (isset($_['displayName']) && !empty($_['displayName'])) { p($_['displayName']); } else { p($l->t('No display name set')); } ?></span> |
|
| 87 | 87 | <?php } ?> |
| 88 | 88 | <span class="icon-checkmark hidden"/> |
| 89 | 89 | <input type="hidden" id="displaynamescope" value="<?php p($_['displayNameScope']) ?>"> |
@@ -96,13 +96,13 @@ discard block |
||
| 96 | 96 | <span class="icon-password"/> |
| 97 | 97 | </h2> |
| 98 | 98 | <input type="email" name="email" id="email" value="<?php p($_['email']); ?>" |
| 99 | - <?php if(!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> |
|
| 99 | + <?php if (!$_['displayNameChangeSupported']) { print_unescaped('class="hidden"'); } ?> |
|
| 100 | 100 | placeholder="<?php p($l->t('Your email address')); ?>" |
| 101 | 101 | autocomplete="on" autocapitalize="off" autocorrect="off" /> |
| 102 | - <?php if(!$_['displayNameChangeSupported']) { ?> |
|
| 103 | - <span><?php if(isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> |
|
| 102 | + <?php if (!$_['displayNameChangeSupported']) { ?> |
|
| 103 | + <span><?php if (isset($_['email']) && !empty($_['email'])) { p($_['email']); } else { p($l->t('No email address set')); }?></span> |
|
| 104 | 104 | <?php } ?> |
| 105 | - <?php if($_['displayNameChangeSupported']) { ?> |
|
| 105 | + <?php if ($_['displayNameChangeSupported']) { ?> |
|
| 106 | 106 | <br /> |
| 107 | 107 | <em><?php p($l->t('For password reset and notifications')); ?></em> |
| 108 | 108 | <?php } ?> |
@@ -178,19 +178,19 @@ discard block |
||
| 178 | 178 | </div> |
| 179 | 179 | |
| 180 | 180 | <?php |
| 181 | -if($_['passwordChangeSupported']) { |
|
| 181 | +if ($_['passwordChangeSupported']) { |
|
| 182 | 182 | script('jquery-showpassword'); |
| 183 | 183 | ?> |
| 184 | 184 | <form id="passwordform" class="section"> |
| 185 | - <h2 class="inlineblock"><?php p($l->t('Password'));?></h2> |
|
| 185 | + <h2 class="inlineblock"><?php p($l->t('Password')); ?></h2> |
|
| 186 | 186 | <div id="password-error-msg" class="msg success inlineblock" style="display: none;">Saved</div> |
| 187 | 187 | <br> |
| 188 | 188 | <label for="pass1" class="hidden-visually"><?php p($l->t('Current password')); ?>: </label> |
| 189 | 189 | <input type="password" id="pass1" name="oldpassword" |
| 190 | - placeholder="<?php p($l->t('Current password'));?>" |
|
| 190 | + placeholder="<?php p($l->t('Current password')); ?>" |
|
| 191 | 191 | autocomplete="off" autocapitalize="off" autocorrect="off" /> |
| 192 | 192 | <div class="personal-show-container"> |
| 193 | - <label for="pass2" class="hidden-visually"><?php p($l->t('New password'));?>: </label> |
|
| 193 | + <label for="pass2" class="hidden-visually"><?php p($l->t('New password')); ?>: </label> |
|
| 194 | 194 | <input type="password" id="pass2" name="newpassword" |
| 195 | 195 | placeholder="<?php p($l->t('New password')); ?>" |
| 196 | 196 | data-typetoggle="#personal-show" |
@@ -206,44 +206,44 @@ discard block |
||
| 206 | 206 | |
| 207 | 207 | <form id="language" class="section"> |
| 208 | 208 | <h2> |
| 209 | - <label for="languageinput"><?php p($l->t('Language'));?></label> |
|
| 209 | + <label for="languageinput"><?php p($l->t('Language')); ?></label> |
|
| 210 | 210 | </h2> |
| 211 | - <select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language'));?>"> |
|
| 212 | - <option value="<?php p($_['activelanguage']['code']);?>"> |
|
| 213 | - <?php p($_['activelanguage']['name']);?> |
|
| 211 | + <select id="languageinput" name="lang" data-placeholder="<?php p($l->t('Language')); ?>"> |
|
| 212 | + <option value="<?php p($_['activelanguage']['code']); ?>"> |
|
| 213 | + <?php p($_['activelanguage']['name']); ?> |
|
| 214 | 214 | </option> |
| 215 | - <?php foreach($_['commonlanguages'] as $language):?> |
|
| 216 | - <option value="<?php p($language['code']);?>"> |
|
| 217 | - <?php p($language['name']);?> |
|
| 215 | + <?php foreach ($_['commonlanguages'] as $language):?> |
|
| 216 | + <option value="<?php p($language['code']); ?>"> |
|
| 217 | + <?php p($language['name']); ?> |
|
| 218 | 218 | </option> |
| 219 | - <?php endforeach;?> |
|
| 219 | + <?php endforeach; ?> |
|
| 220 | 220 | <optgroup label="––––––––––"></optgroup> |
| 221 | - <?php foreach($_['languages'] as $language):?> |
|
| 222 | - <option value="<?php p($language['code']);?>"> |
|
| 223 | - <?php p($language['name']);?> |
|
| 221 | + <?php foreach ($_['languages'] as $language):?> |
|
| 222 | + <option value="<?php p($language['code']); ?>"> |
|
| 223 | + <?php p($language['name']); ?> |
|
| 224 | 224 | </option> |
| 225 | - <?php endforeach;?> |
|
| 225 | + <?php endforeach; ?> |
|
| 226 | 226 | </select> |
| 227 | 227 | <a href="https://www.transifex.com/nextcloud/nextcloud/" |
| 228 | 228 | target="_blank" rel="noreferrer"> |
| 229 | - <em><?php p($l->t('Help translate'));?></em> |
|
| 229 | + <em><?php p($l->t('Help translate')); ?></em> |
|
| 230 | 230 | </a> |
| 231 | 231 | </form> |
| 232 | 232 | |
| 233 | 233 | |
| 234 | 234 | <div id="clientsbox" class="section clientsbox"> |
| 235 | - <h2><?php p($l->t('Get the apps to sync your files'));?></h2> |
|
| 235 | + <h2><?php p($l->t('Get the apps to sync your files')); ?></h2> |
|
| 236 | 236 | <a href="<?php p($_['clients']['desktop']); ?>" rel="noreferrer" target="_blank"> |
| 237 | 237 | <img src="<?php print_unescaped(image_path('core', 'desktopapp.svg')); ?>" |
| 238 | - alt="<?php p($l->t('Desktop client'));?>" /> |
|
| 238 | + alt="<?php p($l->t('Desktop client')); ?>" /> |
|
| 239 | 239 | </a> |
| 240 | 240 | <a href="<?php p($_['clients']['android']); ?>" rel="noreferrer" target="_blank"> |
| 241 | 241 | <img src="<?php print_unescaped(image_path('core', 'googleplay.png')); ?>" |
| 242 | - alt="<?php p($l->t('Android app'));?>" /> |
|
| 242 | + alt="<?php p($l->t('Android app')); ?>" /> |
|
| 243 | 243 | </a> |
| 244 | 244 | <a href="<?php p($_['clients']['ios']); ?>" rel="noreferrer" target="_blank"> |
| 245 | 245 | <img src="<?php print_unescaped(image_path('core', 'appstore.svg')); ?>" |
| 246 | - alt="<?php p($l->t('iOS app'));?>" /> |
|
| 246 | + alt="<?php p($l->t('iOS app')); ?>" /> |
|
| 247 | 247 | </a> |
| 248 | 248 | |
| 249 | 249 | <p> |
@@ -259,19 +259,19 @@ discard block |
||
| 259 | 259 | $l->t('If you want to support the project {contributeopen}join development{linkclose} or {contributeopen}spread the word{linkclose}!'))); ?> |
| 260 | 260 | </p> |
| 261 | 261 | |
| 262 | - <?php if(OC_APP::isEnabled('firstrunwizard')) {?> |
|
| 263 | - <p><a class="button" href="#" id="showWizard"><?php p($l->t('Show First Run Wizard again'));?></a></p> |
|
| 262 | + <?php if (OC_APP::isEnabled('firstrunwizard')) {?> |
|
| 263 | + <p><a class="button" href="#" id="showWizard"><?php p($l->t('Show First Run Wizard again')); ?></a></p> |
|
| 264 | 264 | <?php }?> |
| 265 | 265 | </div> |
| 266 | 266 | |
| 267 | 267 | <div id="sessions" class="section"> |
| 268 | - <h2><?php p($l->t('Sessions'));?></h2> |
|
| 269 | - <span class="hidden-when-empty"><?php p($l->t('Web, desktop and mobile clients currently logged in to your account.'));?></span> |
|
| 268 | + <h2><?php p($l->t('Sessions')); ?></h2> |
|
| 269 | + <span class="hidden-when-empty"><?php p($l->t('Web, desktop and mobile clients currently logged in to your account.')); ?></span> |
|
| 270 | 270 | <table class="icon-loading"> |
| 271 | 271 | <thead class="token-list-header"> |
| 272 | 272 | <tr> |
| 273 | - <th><?php p($l->t('Device'));?></th> |
|
| 274 | - <th><?php p($l->t('Last activity'));?></th> |
|
| 273 | + <th><?php p($l->t('Device')); ?></th> |
|
| 274 | + <th><?php p($l->t('Last activity')); ?></th> |
|
| 275 | 275 | <th></th> |
| 276 | 276 | </tr> |
| 277 | 277 | </thead> |
@@ -281,13 +281,13 @@ discard block |
||
| 281 | 281 | </div> |
| 282 | 282 | |
| 283 | 283 | <div id="apppasswords" class="section"> |
| 284 | - <h2><?php p($l->t('App passwords'));?></h2> |
|
| 285 | - <p><?php p($l->t('Passcodes that give an app or device permissions to access your account.'));?></p> |
|
| 284 | + <h2><?php p($l->t('App passwords')); ?></h2> |
|
| 285 | + <p><?php p($l->t('Passcodes that give an app or device permissions to access your account.')); ?></p> |
|
| 286 | 286 | <table class="icon-loading"> |
| 287 | 287 | <thead class="hidden-when-empty"> |
| 288 | 288 | <tr> |
| 289 | - <th><?php p($l->t('Name'));?></th> |
|
| 290 | - <th><?php p($l->t('Last activity'));?></th> |
|
| 289 | + <th><?php p($l->t('Name')); ?></th> |
|
| 290 | + <th><?php p($l->t('Last activity')); ?></th> |
|
| 291 | 291 | <th></th> |
| 292 | 292 | </tr> |
| 293 | 293 | </thead> |
@@ -316,14 +316,14 @@ discard block |
||
| 316 | 316 | </div> |
| 317 | 317 | </div> |
| 318 | 318 | |
| 319 | -<?php foreach($_['forms'] as $form) { |
|
| 319 | +<?php foreach ($_['forms'] as $form) { |
|
| 320 | 320 | if (isset($form['form'])) {?> |
| 321 | - <div id="<?php isset($form['anchor']) ? p($form['anchor']) : p('');?>"><?php print_unescaped($form['form']);?></div> |
|
| 321 | + <div id="<?php isset($form['anchor']) ? p($form['anchor']) : p(''); ?>"><?php print_unescaped($form['form']); ?></div> |
|
| 322 | 322 | <?php } |
| 323 | 323 | };?> |
| 324 | 324 | |
| 325 | 325 | <div class="section"> |
| 326 | - <h2><?php p($l->t('Version'));?></h2> |
|
| 326 | + <h2><?php p($l->t('Version')); ?></h2> |
|
| 327 | 327 | <p><a href="<?php print_unescaped($theme->getBaseUrl()); ?>" target="_blank"><?php p($theme->getTitle()); ?></a> <?php p(OC_Util::getHumanVersion()) ?></p> |
| 328 | 328 | <p><?php include('settings.development.notice.php'); ?></p> |
| 329 | 329 | </div> |
@@ -31,9 +31,12 @@ discard block |
||
| 31 | 31 | <?php if ($_['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED): ?> |
| 32 | 32 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong>', |
| 33 | 33 | [$_['usage'], $_['total_space']]));?> |
| 34 | - <?php else: ?> |
|
| 34 | + <?php else { |
|
| 35 | + : ?> |
|
| 35 | 36 | <?php print_unescaped($l->t('You are using <strong>%s</strong> of <strong>%s</strong> (<strong>%s %%</strong>)', |
| 36 | - [$_['usage'], $_['total_space'], $_['usage_relative']]));?> |
|
| 37 | + [$_['usage'], $_['total_space'], $_['usage_relative']])); |
|
| 38 | +} |
|
| 39 | +?> |
|
| 37 | 40 | <?php endif ?> |
| 38 | 41 | </p> |
| 39 | 42 | </div> |
@@ -55,8 +58,11 @@ discard block |
||
| 55 | 58 | <div class="hidden button icon-delete svg" id="removeavatar" title="<?php p($l->t('Remove image')); ?>"></div> |
| 56 | 59 | <input type="file" name="files[]" id="uploadavatar" class="hiddenuploadfield"> |
| 57 | 60 | <p><em><?php p($l->t('png or jpg, max. 20 MB')); ?></em></p> |
| 58 | - <?php else: ?> |
|
| 59 | - <?php p($l->t('Picture provided by original account')); ?> |
|
| 61 | + <?php else { |
|
| 62 | + : ?> |
|
| 63 | + <?php p($l->t('Picture provided by original account')); |
|
| 64 | +} |
|
| 65 | +?> |
|
| 60 | 66 | <?php endif; ?> |
| 61 | 67 | </div> |
| 62 | 68 | |
@@ -34,102 +34,102 @@ |
||
| 34 | 34 | |
| 35 | 35 | class EncryptAll extends Command { |
| 36 | 36 | |
| 37 | - /** @var IManager */ |
|
| 38 | - protected $encryptionManager; |
|
| 39 | - |
|
| 40 | - /** @var IAppManager */ |
|
| 41 | - protected $appManager; |
|
| 42 | - |
|
| 43 | - /** @var IConfig */ |
|
| 44 | - protected $config; |
|
| 45 | - |
|
| 46 | - /** @var QuestionHelper */ |
|
| 47 | - protected $questionHelper; |
|
| 48 | - |
|
| 49 | - /** @var bool */ |
|
| 50 | - protected $wasTrashbinEnabled; |
|
| 51 | - |
|
| 52 | - /** @var bool */ |
|
| 53 | - protected $wasMaintenanceModeEnabled; |
|
| 54 | - |
|
| 55 | - /** |
|
| 56 | - * @param IManager $encryptionManager |
|
| 57 | - * @param IAppManager $appManager |
|
| 58 | - * @param IConfig $config |
|
| 59 | - * @param QuestionHelper $questionHelper |
|
| 60 | - */ |
|
| 61 | - public function __construct( |
|
| 62 | - IManager $encryptionManager, |
|
| 63 | - IAppManager $appManager, |
|
| 64 | - IConfig $config, |
|
| 65 | - QuestionHelper $questionHelper |
|
| 66 | - ) { |
|
| 67 | - parent::__construct(); |
|
| 68 | - $this->appManager = $appManager; |
|
| 69 | - $this->encryptionManager = $encryptionManager; |
|
| 70 | - $this->config = $config; |
|
| 71 | - $this->questionHelper = $questionHelper; |
|
| 72 | - } |
|
| 73 | - |
|
| 74 | - /** |
|
| 75 | - * Set maintenance mode and disable the trashbin app |
|
| 76 | - */ |
|
| 77 | - protected function forceMaintenanceAndTrashbin() { |
|
| 78 | - $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); |
|
| 79 | - $this->wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); |
|
| 80 | - $this->config->setSystemValue('maintenance', true); |
|
| 81 | - $this->appManager->disableApp('files_trashbin'); |
|
| 82 | - } |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Reset the maintenance mode and re-enable the trashbin app |
|
| 86 | - */ |
|
| 87 | - protected function resetMaintenanceAndTrashbin() { |
|
| 88 | - $this->config->setSystemValue('maintenance', $this->wasMaintenanceModeEnabled); |
|
| 89 | - if ($this->wasTrashbinEnabled) { |
|
| 90 | - $this->appManager->enableApp('files_trashbin'); |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - protected function configure() { |
|
| 95 | - parent::configure(); |
|
| 96 | - |
|
| 97 | - $this->setName('encryption:encrypt-all'); |
|
| 98 | - $this->setDescription('Encrypt all files for all users'); |
|
| 99 | - $this->setHelp( |
|
| 100 | - 'This will encrypt all files for all users. ' |
|
| 101 | - . 'Please make sure that no user access his files during this process!' |
|
| 102 | - ); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - protected function execute(InputInterface $input, OutputInterface $output) { |
|
| 106 | - |
|
| 107 | - if ($this->encryptionManager->isEnabled() === false) { |
|
| 108 | - throw new \Exception('Server side encryption is not enabled'); |
|
| 109 | - } |
|
| 110 | - |
|
| 111 | - $output->writeln("\n"); |
|
| 112 | - $output->writeln('You are about to encrypt all files stored in your Nextcloud installation.'); |
|
| 113 | - $output->writeln('Depending on the number of available files, and their size, this may take quite some time.'); |
|
| 114 | - $output->writeln('Please ensure that no user accesses their files during this time!'); |
|
| 115 | - $output->writeln('Note: The encryption module you use determines which files get encrypted.'); |
|
| 116 | - $output->writeln(''); |
|
| 117 | - $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); |
|
| 118 | - if ($this->questionHelper->ask($input, $output, $question)) { |
|
| 119 | - $this->forceMaintenanceAndTrashbin(); |
|
| 120 | - |
|
| 121 | - try { |
|
| 122 | - $defaultModule = $this->encryptionManager->getEncryptionModule(); |
|
| 123 | - $defaultModule->encryptAll($input, $output); |
|
| 124 | - } catch (\Exception $ex) { |
|
| 125 | - $this->resetMaintenanceAndTrashbin(); |
|
| 126 | - throw $ex; |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - $this->resetMaintenanceAndTrashbin(); |
|
| 130 | - } else { |
|
| 131 | - $output->writeln('aborted'); |
|
| 132 | - } |
|
| 133 | - } |
|
| 37 | + /** @var IManager */ |
|
| 38 | + protected $encryptionManager; |
|
| 39 | + |
|
| 40 | + /** @var IAppManager */ |
|
| 41 | + protected $appManager; |
|
| 42 | + |
|
| 43 | + /** @var IConfig */ |
|
| 44 | + protected $config; |
|
| 45 | + |
|
| 46 | + /** @var QuestionHelper */ |
|
| 47 | + protected $questionHelper; |
|
| 48 | + |
|
| 49 | + /** @var bool */ |
|
| 50 | + protected $wasTrashbinEnabled; |
|
| 51 | + |
|
| 52 | + /** @var bool */ |
|
| 53 | + protected $wasMaintenanceModeEnabled; |
|
| 54 | + |
|
| 55 | + /** |
|
| 56 | + * @param IManager $encryptionManager |
|
| 57 | + * @param IAppManager $appManager |
|
| 58 | + * @param IConfig $config |
|
| 59 | + * @param QuestionHelper $questionHelper |
|
| 60 | + */ |
|
| 61 | + public function __construct( |
|
| 62 | + IManager $encryptionManager, |
|
| 63 | + IAppManager $appManager, |
|
| 64 | + IConfig $config, |
|
| 65 | + QuestionHelper $questionHelper |
|
| 66 | + ) { |
|
| 67 | + parent::__construct(); |
|
| 68 | + $this->appManager = $appManager; |
|
| 69 | + $this->encryptionManager = $encryptionManager; |
|
| 70 | + $this->config = $config; |
|
| 71 | + $this->questionHelper = $questionHelper; |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + /** |
|
| 75 | + * Set maintenance mode and disable the trashbin app |
|
| 76 | + */ |
|
| 77 | + protected function forceMaintenanceAndTrashbin() { |
|
| 78 | + $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); |
|
| 79 | + $this->wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false); |
|
| 80 | + $this->config->setSystemValue('maintenance', true); |
|
| 81 | + $this->appManager->disableApp('files_trashbin'); |
|
| 82 | + } |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Reset the maintenance mode and re-enable the trashbin app |
|
| 86 | + */ |
|
| 87 | + protected function resetMaintenanceAndTrashbin() { |
|
| 88 | + $this->config->setSystemValue('maintenance', $this->wasMaintenanceModeEnabled); |
|
| 89 | + if ($this->wasTrashbinEnabled) { |
|
| 90 | + $this->appManager->enableApp('files_trashbin'); |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + protected function configure() { |
|
| 95 | + parent::configure(); |
|
| 96 | + |
|
| 97 | + $this->setName('encryption:encrypt-all'); |
|
| 98 | + $this->setDescription('Encrypt all files for all users'); |
|
| 99 | + $this->setHelp( |
|
| 100 | + 'This will encrypt all files for all users. ' |
|
| 101 | + . 'Please make sure that no user access his files during this process!' |
|
| 102 | + ); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + protected function execute(InputInterface $input, OutputInterface $output) { |
|
| 106 | + |
|
| 107 | + if ($this->encryptionManager->isEnabled() === false) { |
|
| 108 | + throw new \Exception('Server side encryption is not enabled'); |
|
| 109 | + } |
|
| 110 | + |
|
| 111 | + $output->writeln("\n"); |
|
| 112 | + $output->writeln('You are about to encrypt all files stored in your Nextcloud installation.'); |
|
| 113 | + $output->writeln('Depending on the number of available files, and their size, this may take quite some time.'); |
|
| 114 | + $output->writeln('Please ensure that no user accesses their files during this time!'); |
|
| 115 | + $output->writeln('Note: The encryption module you use determines which files get encrypted.'); |
|
| 116 | + $output->writeln(''); |
|
| 117 | + $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); |
|
| 118 | + if ($this->questionHelper->ask($input, $output, $question)) { |
|
| 119 | + $this->forceMaintenanceAndTrashbin(); |
|
| 120 | + |
|
| 121 | + try { |
|
| 122 | + $defaultModule = $this->encryptionManager->getEncryptionModule(); |
|
| 123 | + $defaultModule->encryptAll($input, $output); |
|
| 124 | + } catch (\Exception $ex) { |
|
| 125 | + $this->resetMaintenanceAndTrashbin(); |
|
| 126 | + throw $ex; |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + $this->resetMaintenanceAndTrashbin(); |
|
| 130 | + } else { |
|
| 131 | + $output->writeln('aborted'); |
|
| 132 | + } |
|
| 133 | + } |
|
| 134 | 134 | |
| 135 | 135 | } |
@@ -46,396 +46,396 @@ |
||
| 46 | 46 | * |
| 47 | 47 | */ |
| 48 | 48 | class OC_Files { |
| 49 | - const FILE = 1; |
|
| 50 | - const ZIP_FILES = 2; |
|
| 51 | - const ZIP_DIR = 3; |
|
| 52 | - |
|
| 53 | - const UPLOAD_MIN_LIMIT_BYTES = 1048576; // 1 MiB |
|
| 54 | - |
|
| 55 | - |
|
| 56 | - private static $multipartBoundary = ''; |
|
| 57 | - |
|
| 58 | - /** |
|
| 59 | - * @return string |
|
| 60 | - */ |
|
| 61 | - private static function getBoundary() { |
|
| 62 | - if (empty(self::$multipartBoundary)) { |
|
| 63 | - self::$multipartBoundary = md5(mt_rand()); |
|
| 64 | - } |
|
| 65 | - return self::$multipartBoundary; |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - /** |
|
| 69 | - * @param string $filename |
|
| 70 | - * @param string $name |
|
| 71 | - * @param array $rangeArray ('from'=>int,'to'=>int), ... |
|
| 72 | - */ |
|
| 73 | - private static function sendHeaders($filename, $name, array $rangeArray) { |
|
| 74 | - OC_Response::setContentDispositionHeader($name, 'attachment'); |
|
| 75 | - header('Content-Transfer-Encoding: binary', true); |
|
| 76 | - OC_Response::disableCaching(); |
|
| 77 | - $fileSize = \OC\Files\Filesystem::filesize($filename); |
|
| 78 | - $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); |
|
| 79 | - if ($fileSize > -1) { |
|
| 80 | - if (!empty($rangeArray)) { |
|
| 81 | - header('HTTP/1.1 206 Partial Content', true); |
|
| 82 | - header('Accept-Ranges: bytes', true); |
|
| 83 | - if (count($rangeArray) > 1) { |
|
| 84 | - $type = 'multipart/byteranges; boundary='.self::getBoundary(); |
|
| 85 | - // no Content-Length header here |
|
| 86 | - } |
|
| 87 | - else { |
|
| 88 | - header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true); |
|
| 89 | - OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1); |
|
| 90 | - } |
|
| 91 | - } |
|
| 92 | - else { |
|
| 93 | - OC_Response::setContentLengthHeader($fileSize); |
|
| 94 | - } |
|
| 95 | - } |
|
| 96 | - header('Content-Type: '.$type, true); |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - /** |
|
| 100 | - * return the content of a file or return a zip file containing multiple files |
|
| 101 | - * |
|
| 102 | - * @param string $dir |
|
| 103 | - * @param string $files ; separated list of files to download |
|
| 104 | - * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header |
|
| 105 | - */ |
|
| 106 | - public static function get($dir, $files, $params = null) { |
|
| 107 | - |
|
| 108 | - $view = \OC\Files\Filesystem::getView(); |
|
| 109 | - $getType = self::FILE; |
|
| 110 | - $filename = $dir; |
|
| 111 | - try { |
|
| 112 | - |
|
| 113 | - if (is_array($files) && count($files) === 1) { |
|
| 114 | - $files = $files[0]; |
|
| 115 | - } |
|
| 116 | - |
|
| 117 | - if (!is_array($files)) { |
|
| 118 | - $filename = $dir . '/' . $files; |
|
| 119 | - if (!$view->is_dir($filename)) { |
|
| 120 | - self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params); |
|
| 121 | - return; |
|
| 122 | - } |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - $name = 'download'; |
|
| 126 | - if (is_array($files)) { |
|
| 127 | - $getType = self::ZIP_FILES; |
|
| 128 | - $basename = basename($dir); |
|
| 129 | - if ($basename) { |
|
| 130 | - $name = $basename; |
|
| 131 | - } |
|
| 132 | - |
|
| 133 | - $filename = $dir . '/' . $name; |
|
| 134 | - } else { |
|
| 135 | - $filename = $dir . '/' . $files; |
|
| 136 | - $getType = self::ZIP_DIR; |
|
| 137 | - // downloading root ? |
|
| 138 | - if ($files !== '') { |
|
| 139 | - $name = $files; |
|
| 140 | - } |
|
| 141 | - } |
|
| 142 | - |
|
| 143 | - $streamer = new Streamer(); |
|
| 144 | - OC_Util::obEnd(); |
|
| 145 | - |
|
| 146 | - self::lockFiles($view, $dir, $files); |
|
| 147 | - |
|
| 148 | - $streamer->sendHeaders($name); |
|
| 149 | - $executionTime = intval(OC::$server->getIniWrapper()->getNumeric('max_execution_time')); |
|
| 150 | - if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { |
|
| 151 | - @set_time_limit(0); |
|
| 152 | - } |
|
| 153 | - ignore_user_abort(true); |
|
| 154 | - if ($getType === self::ZIP_FILES) { |
|
| 155 | - foreach ($files as $file) { |
|
| 156 | - $file = $dir . '/' . $file; |
|
| 157 | - if (\OC\Files\Filesystem::is_file($file)) { |
|
| 158 | - $fileSize = \OC\Files\Filesystem::filesize($file); |
|
| 159 | - $fileTime = \OC\Files\Filesystem::filemtime($file); |
|
| 160 | - $fh = \OC\Files\Filesystem::fopen($file, 'r'); |
|
| 161 | - $streamer->addFileFromStream($fh, basename($file), $fileSize, $fileTime); |
|
| 162 | - fclose($fh); |
|
| 163 | - } elseif (\OC\Files\Filesystem::is_dir($file)) { |
|
| 164 | - $streamer->addDirRecursive($file); |
|
| 165 | - } |
|
| 166 | - } |
|
| 167 | - } elseif ($getType === self::ZIP_DIR) { |
|
| 168 | - $file = $dir . '/' . $files; |
|
| 169 | - $streamer->addDirRecursive($file); |
|
| 170 | - } |
|
| 171 | - $streamer->finalize(); |
|
| 172 | - set_time_limit($executionTime); |
|
| 173 | - self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 174 | - } catch (\OCP\Lock\LockedException $ex) { |
|
| 175 | - self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 176 | - OC::$server->getLogger()->logException($ex); |
|
| 177 | - $l = \OC::$server->getL10N('core'); |
|
| 178 | - $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; |
|
| 179 | - \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint); |
|
| 180 | - } catch (\OCP\Files\ForbiddenException $ex) { |
|
| 181 | - self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 182 | - OC::$server->getLogger()->logException($ex); |
|
| 183 | - $l = \OC::$server->getL10N('core'); |
|
| 184 | - \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage()); |
|
| 185 | - } catch (\Exception $ex) { |
|
| 186 | - self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 187 | - OC::$server->getLogger()->logException($ex); |
|
| 188 | - $l = \OC::$server->getL10N('core'); |
|
| 189 | - $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; |
|
| 190 | - \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint); |
|
| 191 | - } |
|
| 192 | - } |
|
| 193 | - |
|
| 194 | - /** |
|
| 195 | - * @param string $rangeHeaderPos |
|
| 196 | - * @param int $fileSize |
|
| 197 | - * @return array $rangeArray ('from'=>int,'to'=>int), ... |
|
| 198 | - */ |
|
| 199 | - private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) { |
|
| 200 | - $rArray=explode(',', $rangeHeaderPos); |
|
| 201 | - $minOffset = 0; |
|
| 202 | - $ind = 0; |
|
| 203 | - |
|
| 204 | - $rangeArray = array(); |
|
| 205 | - |
|
| 206 | - foreach ($rArray as $value) { |
|
| 207 | - $ranges = explode('-', $value); |
|
| 208 | - if (is_numeric($ranges[0])) { |
|
| 209 | - if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999 |
|
| 210 | - $ranges[0] = $minOffset; |
|
| 211 | - } |
|
| 212 | - if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999 |
|
| 213 | - $ind--; |
|
| 214 | - $ranges[0] = $rangeArray[$ind]['from']; |
|
| 215 | - } |
|
| 216 | - } |
|
| 217 | - |
|
| 218 | - if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) { |
|
| 219 | - // case: x-x |
|
| 220 | - if ($ranges[1] >= $fileSize) { |
|
| 221 | - $ranges[1] = $fileSize-1; |
|
| 222 | - } |
|
| 223 | - $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize ); |
|
| 224 | - $minOffset = $ranges[1] + 1; |
|
| 225 | - if ($minOffset >= $fileSize) { |
|
| 226 | - break; |
|
| 227 | - } |
|
| 228 | - } |
|
| 229 | - elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) { |
|
| 230 | - // case: x- |
|
| 231 | - $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize ); |
|
| 232 | - break; |
|
| 233 | - } |
|
| 234 | - elseif (is_numeric($ranges[1])) { |
|
| 235 | - // case: -x |
|
| 236 | - if ($ranges[1] > $fileSize) { |
|
| 237 | - $ranges[1] = $fileSize; |
|
| 238 | - } |
|
| 239 | - $rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize ); |
|
| 240 | - break; |
|
| 241 | - } |
|
| 242 | - } |
|
| 243 | - return $rangeArray; |
|
| 244 | - } |
|
| 245 | - |
|
| 246 | - /** |
|
| 247 | - * @param View $view |
|
| 248 | - * @param string $name |
|
| 249 | - * @param string $dir |
|
| 250 | - * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header |
|
| 251 | - */ |
|
| 252 | - private static function getSingleFile($view, $dir, $name, $params) { |
|
| 253 | - $filename = $dir . '/' . $name; |
|
| 254 | - OC_Util::obEnd(); |
|
| 255 | - $view->lockFile($filename, ILockingProvider::LOCK_SHARED); |
|
| 49 | + const FILE = 1; |
|
| 50 | + const ZIP_FILES = 2; |
|
| 51 | + const ZIP_DIR = 3; |
|
| 52 | + |
|
| 53 | + const UPLOAD_MIN_LIMIT_BYTES = 1048576; // 1 MiB |
|
| 54 | + |
|
| 55 | + |
|
| 56 | + private static $multipartBoundary = ''; |
|
| 57 | + |
|
| 58 | + /** |
|
| 59 | + * @return string |
|
| 60 | + */ |
|
| 61 | + private static function getBoundary() { |
|
| 62 | + if (empty(self::$multipartBoundary)) { |
|
| 63 | + self::$multipartBoundary = md5(mt_rand()); |
|
| 64 | + } |
|
| 65 | + return self::$multipartBoundary; |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + /** |
|
| 69 | + * @param string $filename |
|
| 70 | + * @param string $name |
|
| 71 | + * @param array $rangeArray ('from'=>int,'to'=>int), ... |
|
| 72 | + */ |
|
| 73 | + private static function sendHeaders($filename, $name, array $rangeArray) { |
|
| 74 | + OC_Response::setContentDispositionHeader($name, 'attachment'); |
|
| 75 | + header('Content-Transfer-Encoding: binary', true); |
|
| 76 | + OC_Response::disableCaching(); |
|
| 77 | + $fileSize = \OC\Files\Filesystem::filesize($filename); |
|
| 78 | + $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); |
|
| 79 | + if ($fileSize > -1) { |
|
| 80 | + if (!empty($rangeArray)) { |
|
| 81 | + header('HTTP/1.1 206 Partial Content', true); |
|
| 82 | + header('Accept-Ranges: bytes', true); |
|
| 83 | + if (count($rangeArray) > 1) { |
|
| 84 | + $type = 'multipart/byteranges; boundary='.self::getBoundary(); |
|
| 85 | + // no Content-Length header here |
|
| 86 | + } |
|
| 87 | + else { |
|
| 88 | + header(sprintf('Content-Range: bytes %d-%d/%d', $rangeArray[0]['from'], $rangeArray[0]['to'], $fileSize), true); |
|
| 89 | + OC_Response::setContentLengthHeader($rangeArray[0]['to'] - $rangeArray[0]['from'] + 1); |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | + else { |
|
| 93 | + OC_Response::setContentLengthHeader($fileSize); |
|
| 94 | + } |
|
| 95 | + } |
|
| 96 | + header('Content-Type: '.$type, true); |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + /** |
|
| 100 | + * return the content of a file or return a zip file containing multiple files |
|
| 101 | + * |
|
| 102 | + * @param string $dir |
|
| 103 | + * @param string $files ; separated list of files to download |
|
| 104 | + * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header |
|
| 105 | + */ |
|
| 106 | + public static function get($dir, $files, $params = null) { |
|
| 107 | + |
|
| 108 | + $view = \OC\Files\Filesystem::getView(); |
|
| 109 | + $getType = self::FILE; |
|
| 110 | + $filename = $dir; |
|
| 111 | + try { |
|
| 112 | + |
|
| 113 | + if (is_array($files) && count($files) === 1) { |
|
| 114 | + $files = $files[0]; |
|
| 115 | + } |
|
| 116 | + |
|
| 117 | + if (!is_array($files)) { |
|
| 118 | + $filename = $dir . '/' . $files; |
|
| 119 | + if (!$view->is_dir($filename)) { |
|
| 120 | + self::getSingleFile($view, $dir, $files, is_null($params) ? array() : $params); |
|
| 121 | + return; |
|
| 122 | + } |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + $name = 'download'; |
|
| 126 | + if (is_array($files)) { |
|
| 127 | + $getType = self::ZIP_FILES; |
|
| 128 | + $basename = basename($dir); |
|
| 129 | + if ($basename) { |
|
| 130 | + $name = $basename; |
|
| 131 | + } |
|
| 132 | + |
|
| 133 | + $filename = $dir . '/' . $name; |
|
| 134 | + } else { |
|
| 135 | + $filename = $dir . '/' . $files; |
|
| 136 | + $getType = self::ZIP_DIR; |
|
| 137 | + // downloading root ? |
|
| 138 | + if ($files !== '') { |
|
| 139 | + $name = $files; |
|
| 140 | + } |
|
| 141 | + } |
|
| 142 | + |
|
| 143 | + $streamer = new Streamer(); |
|
| 144 | + OC_Util::obEnd(); |
|
| 145 | + |
|
| 146 | + self::lockFiles($view, $dir, $files); |
|
| 147 | + |
|
| 148 | + $streamer->sendHeaders($name); |
|
| 149 | + $executionTime = intval(OC::$server->getIniWrapper()->getNumeric('max_execution_time')); |
|
| 150 | + if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { |
|
| 151 | + @set_time_limit(0); |
|
| 152 | + } |
|
| 153 | + ignore_user_abort(true); |
|
| 154 | + if ($getType === self::ZIP_FILES) { |
|
| 155 | + foreach ($files as $file) { |
|
| 156 | + $file = $dir . '/' . $file; |
|
| 157 | + if (\OC\Files\Filesystem::is_file($file)) { |
|
| 158 | + $fileSize = \OC\Files\Filesystem::filesize($file); |
|
| 159 | + $fileTime = \OC\Files\Filesystem::filemtime($file); |
|
| 160 | + $fh = \OC\Files\Filesystem::fopen($file, 'r'); |
|
| 161 | + $streamer->addFileFromStream($fh, basename($file), $fileSize, $fileTime); |
|
| 162 | + fclose($fh); |
|
| 163 | + } elseif (\OC\Files\Filesystem::is_dir($file)) { |
|
| 164 | + $streamer->addDirRecursive($file); |
|
| 165 | + } |
|
| 166 | + } |
|
| 167 | + } elseif ($getType === self::ZIP_DIR) { |
|
| 168 | + $file = $dir . '/' . $files; |
|
| 169 | + $streamer->addDirRecursive($file); |
|
| 170 | + } |
|
| 171 | + $streamer->finalize(); |
|
| 172 | + set_time_limit($executionTime); |
|
| 173 | + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 174 | + } catch (\OCP\Lock\LockedException $ex) { |
|
| 175 | + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 176 | + OC::$server->getLogger()->logException($ex); |
|
| 177 | + $l = \OC::$server->getL10N('core'); |
|
| 178 | + $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; |
|
| 179 | + \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint); |
|
| 180 | + } catch (\OCP\Files\ForbiddenException $ex) { |
|
| 181 | + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 182 | + OC::$server->getLogger()->logException($ex); |
|
| 183 | + $l = \OC::$server->getL10N('core'); |
|
| 184 | + \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage()); |
|
| 185 | + } catch (\Exception $ex) { |
|
| 186 | + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); |
|
| 187 | + OC::$server->getLogger()->logException($ex); |
|
| 188 | + $l = \OC::$server->getL10N('core'); |
|
| 189 | + $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; |
|
| 190 | + \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint); |
|
| 191 | + } |
|
| 192 | + } |
|
| 193 | + |
|
| 194 | + /** |
|
| 195 | + * @param string $rangeHeaderPos |
|
| 196 | + * @param int $fileSize |
|
| 197 | + * @return array $rangeArray ('from'=>int,'to'=>int), ... |
|
| 198 | + */ |
|
| 199 | + private static function parseHttpRangeHeader($rangeHeaderPos, $fileSize) { |
|
| 200 | + $rArray=explode(',', $rangeHeaderPos); |
|
| 201 | + $minOffset = 0; |
|
| 202 | + $ind = 0; |
|
| 203 | + |
|
| 204 | + $rangeArray = array(); |
|
| 205 | + |
|
| 206 | + foreach ($rArray as $value) { |
|
| 207 | + $ranges = explode('-', $value); |
|
| 208 | + if (is_numeric($ranges[0])) { |
|
| 209 | + if ($ranges[0] < $minOffset) { // case: bytes=500-700,601-999 |
|
| 210 | + $ranges[0] = $minOffset; |
|
| 211 | + } |
|
| 212 | + if ($ind > 0 && $rangeArray[$ind-1]['to']+1 == $ranges[0]) { // case: bytes=500-600,601-999 |
|
| 213 | + $ind--; |
|
| 214 | + $ranges[0] = $rangeArray[$ind]['from']; |
|
| 215 | + } |
|
| 216 | + } |
|
| 217 | + |
|
| 218 | + if (is_numeric($ranges[0]) && is_numeric($ranges[1]) && $ranges[0] < $fileSize && $ranges[0] <= $ranges[1]) { |
|
| 219 | + // case: x-x |
|
| 220 | + if ($ranges[1] >= $fileSize) { |
|
| 221 | + $ranges[1] = $fileSize-1; |
|
| 222 | + } |
|
| 223 | + $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $ranges[1], 'size' => $fileSize ); |
|
| 224 | + $minOffset = $ranges[1] + 1; |
|
| 225 | + if ($minOffset >= $fileSize) { |
|
| 226 | + break; |
|
| 227 | + } |
|
| 228 | + } |
|
| 229 | + elseif (is_numeric($ranges[0]) && $ranges[0] < $fileSize) { |
|
| 230 | + // case: x- |
|
| 231 | + $rangeArray[$ind++] = array( 'from' => $ranges[0], 'to' => $fileSize-1, 'size' => $fileSize ); |
|
| 232 | + break; |
|
| 233 | + } |
|
| 234 | + elseif (is_numeric($ranges[1])) { |
|
| 235 | + // case: -x |
|
| 236 | + if ($ranges[1] > $fileSize) { |
|
| 237 | + $ranges[1] = $fileSize; |
|
| 238 | + } |
|
| 239 | + $rangeArray[$ind++] = array( 'from' => $fileSize-$ranges[1], 'to' => $fileSize-1, 'size' => $fileSize ); |
|
| 240 | + break; |
|
| 241 | + } |
|
| 242 | + } |
|
| 243 | + return $rangeArray; |
|
| 244 | + } |
|
| 245 | + |
|
| 246 | + /** |
|
| 247 | + * @param View $view |
|
| 248 | + * @param string $name |
|
| 249 | + * @param string $dir |
|
| 250 | + * @param array $params ; 'head' boolean to only send header of the request ; 'range' http range header |
|
| 251 | + */ |
|
| 252 | + private static function getSingleFile($view, $dir, $name, $params) { |
|
| 253 | + $filename = $dir . '/' . $name; |
|
| 254 | + OC_Util::obEnd(); |
|
| 255 | + $view->lockFile($filename, ILockingProvider::LOCK_SHARED); |
|
| 256 | 256 | |
| 257 | - $rangeArray = array(); |
|
| 257 | + $rangeArray = array(); |
|
| 258 | 258 | |
| 259 | - if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') { |
|
| 260 | - $rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), |
|
| 261 | - \OC\Files\Filesystem::filesize($filename)); |
|
| 262 | - } |
|
| 259 | + if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') { |
|
| 260 | + $rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), |
|
| 261 | + \OC\Files\Filesystem::filesize($filename)); |
|
| 262 | + } |
|
| 263 | 263 | |
| 264 | - if (\OC\Files\Filesystem::isReadable($filename)) { |
|
| 265 | - self::sendHeaders($filename, $name, $rangeArray); |
|
| 266 | - } elseif (!\OC\Files\Filesystem::file_exists($filename)) { |
|
| 267 | - header("HTTP/1.1 404 Not Found"); |
|
| 268 | - $tmpl = new OC_Template('', '404', 'guest'); |
|
| 269 | - $tmpl->printPage(); |
|
| 270 | - exit(); |
|
| 271 | - } else { |
|
| 272 | - header("HTTP/1.1 403 Forbidden"); |
|
| 273 | - die('403 Forbidden'); |
|
| 274 | - } |
|
| 275 | - if (isset($params['head']) && $params['head']) { |
|
| 276 | - return; |
|
| 277 | - } |
|
| 278 | - if (!empty($rangeArray)) { |
|
| 279 | - try { |
|
| 280 | - if (count($rangeArray) == 1) { |
|
| 281 | - $view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']); |
|
| 282 | - } |
|
| 283 | - else { |
|
| 284 | - // check if file is seekable (if not throw UnseekableException) |
|
| 285 | - // we have to check it before body contents |
|
| 286 | - $view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']); |
|
| 287 | - |
|
| 288 | - $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); |
|
| 289 | - |
|
| 290 | - foreach ($rangeArray as $range) { |
|
| 291 | - echo "\r\n--".self::getBoundary()."\r\n". |
|
| 292 | - "Content-type: ".$type."\r\n". |
|
| 293 | - "Content-range: bytes ".$range['from']."-".$range['to']."/".$range['size']."\r\n\r\n"; |
|
| 294 | - $view->readfilePart($filename, $range['from'], $range['to']); |
|
| 295 | - } |
|
| 296 | - echo "\r\n--".self::getBoundary()."--\r\n"; |
|
| 297 | - } |
|
| 298 | - } catch (\OCP\Files\UnseekableException $ex) { |
|
| 299 | - // file is unseekable |
|
| 300 | - header_remove('Accept-Ranges'); |
|
| 301 | - header_remove('Content-Range'); |
|
| 302 | - header("HTTP/1.1 200 OK"); |
|
| 303 | - self::sendHeaders($filename, $name, array()); |
|
| 304 | - $view->readfile($filename); |
|
| 305 | - } |
|
| 306 | - } |
|
| 307 | - else { |
|
| 308 | - $view->readfile($filename); |
|
| 309 | - } |
|
| 310 | - } |
|
| 311 | - |
|
| 312 | - /** |
|
| 313 | - * @param View $view |
|
| 314 | - * @param string $dir |
|
| 315 | - * @param string[]|string $files |
|
| 316 | - */ |
|
| 317 | - public static function lockFiles($view, $dir, $files) { |
|
| 318 | - if (!is_array($files)) { |
|
| 319 | - $file = $dir . '/' . $files; |
|
| 320 | - $files = [$file]; |
|
| 321 | - } |
|
| 322 | - foreach ($files as $file) { |
|
| 323 | - $file = $dir . '/' . $file; |
|
| 324 | - $view->lockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 325 | - if ($view->is_dir($file)) { |
|
| 326 | - $contents = $view->getDirectoryContent($file); |
|
| 327 | - $contents = array_map(function($fileInfo) use ($file) { |
|
| 328 | - /** @var \OCP\Files\FileInfo $fileInfo */ |
|
| 329 | - return $file . '/' . $fileInfo->getName(); |
|
| 330 | - }, $contents); |
|
| 331 | - self::lockFiles($view, $dir, $contents); |
|
| 332 | - } |
|
| 333 | - } |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * set the maximum upload size limit for apache hosts using .htaccess |
|
| 338 | - * |
|
| 339 | - * @param int $size file size in bytes |
|
| 340 | - * @param array $files override '.htaccess' and '.user.ini' locations |
|
| 341 | - * @return bool false on failure, size on success |
|
| 342 | - */ |
|
| 343 | - public static function setUploadLimit($size, $files = []) { |
|
| 344 | - //don't allow user to break his config |
|
| 345 | - $size = intval($size); |
|
| 346 | - if ($size < self::UPLOAD_MIN_LIMIT_BYTES) { |
|
| 347 | - return false; |
|
| 348 | - } |
|
| 349 | - $size = OC_Helper::phpFileSize($size); |
|
| 350 | - |
|
| 351 | - $phpValueKeys = array( |
|
| 352 | - 'upload_max_filesize', |
|
| 353 | - 'post_max_size' |
|
| 354 | - ); |
|
| 355 | - |
|
| 356 | - // default locations if not overridden by $files |
|
| 357 | - $files = array_merge([ |
|
| 358 | - '.htaccess' => OC::$SERVERROOT . '/.htaccess', |
|
| 359 | - '.user.ini' => OC::$SERVERROOT . '/.user.ini' |
|
| 360 | - ], $files); |
|
| 361 | - |
|
| 362 | - $updateFiles = [ |
|
| 363 | - $files['.htaccess'] => [ |
|
| 364 | - 'pattern' => '/php_value %1$s (\S)*/', |
|
| 365 | - 'setting' => 'php_value %1$s %2$s' |
|
| 366 | - ], |
|
| 367 | - $files['.user.ini'] => [ |
|
| 368 | - 'pattern' => '/%1$s=(\S)*/', |
|
| 369 | - 'setting' => '%1$s=%2$s' |
|
| 370 | - ] |
|
| 371 | - ]; |
|
| 372 | - |
|
| 373 | - $success = true; |
|
| 374 | - |
|
| 375 | - foreach ($updateFiles as $filename => $patternMap) { |
|
| 376 | - // suppress warnings from fopen() |
|
| 377 | - $handle = @fopen($filename, 'r+'); |
|
| 378 | - if (!$handle) { |
|
| 379 | - \OCP\Util::writeLog('files', |
|
| 380 | - 'Can\'t write upload limit to ' . $filename . '. Please check the file permissions', |
|
| 381 | - \OCP\Util::WARN); |
|
| 382 | - $success = false; |
|
| 383 | - continue; // try to update as many files as possible |
|
| 384 | - } |
|
| 385 | - |
|
| 386 | - $content = ''; |
|
| 387 | - while (!feof($handle)) { |
|
| 388 | - $content .= fread($handle, 1000); |
|
| 389 | - } |
|
| 390 | - |
|
| 391 | - foreach ($phpValueKeys as $key) { |
|
| 392 | - $pattern = vsprintf($patternMap['pattern'], [$key]); |
|
| 393 | - $setting = vsprintf($patternMap['setting'], [$key, $size]); |
|
| 394 | - $hasReplaced = 0; |
|
| 395 | - $newContent = preg_replace($pattern, $setting, $content, 2, $hasReplaced); |
|
| 396 | - if ($newContent !== null) { |
|
| 397 | - $content = $newContent; |
|
| 398 | - } |
|
| 399 | - if ($hasReplaced === 0) { |
|
| 400 | - $content .= "\n" . $setting; |
|
| 401 | - } |
|
| 402 | - } |
|
| 403 | - |
|
| 404 | - // write file back |
|
| 405 | - ftruncate($handle, 0); |
|
| 406 | - rewind($handle); |
|
| 407 | - fwrite($handle, $content); |
|
| 408 | - |
|
| 409 | - fclose($handle); |
|
| 410 | - } |
|
| 411 | - |
|
| 412 | - if ($success) { |
|
| 413 | - return OC_Helper::computerFileSize($size); |
|
| 414 | - } |
|
| 415 | - return false; |
|
| 416 | - } |
|
| 417 | - |
|
| 418 | - /** |
|
| 419 | - * @param string $dir |
|
| 420 | - * @param $files |
|
| 421 | - * @param integer $getType |
|
| 422 | - * @param View $view |
|
| 423 | - * @param string $filename |
|
| 424 | - */ |
|
| 425 | - private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) { |
|
| 426 | - if ($getType === self::FILE) { |
|
| 427 | - $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); |
|
| 428 | - } |
|
| 429 | - if ($getType === self::ZIP_FILES) { |
|
| 430 | - foreach ($files as $file) { |
|
| 431 | - $file = $dir . '/' . $file; |
|
| 432 | - $view->unlockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 433 | - } |
|
| 434 | - } |
|
| 435 | - if ($getType === self::ZIP_DIR) { |
|
| 436 | - $file = $dir . '/' . $files; |
|
| 437 | - $view->unlockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 438 | - } |
|
| 439 | - } |
|
| 264 | + if (\OC\Files\Filesystem::isReadable($filename)) { |
|
| 265 | + self::sendHeaders($filename, $name, $rangeArray); |
|
| 266 | + } elseif (!\OC\Files\Filesystem::file_exists($filename)) { |
|
| 267 | + header("HTTP/1.1 404 Not Found"); |
|
| 268 | + $tmpl = new OC_Template('', '404', 'guest'); |
|
| 269 | + $tmpl->printPage(); |
|
| 270 | + exit(); |
|
| 271 | + } else { |
|
| 272 | + header("HTTP/1.1 403 Forbidden"); |
|
| 273 | + die('403 Forbidden'); |
|
| 274 | + } |
|
| 275 | + if (isset($params['head']) && $params['head']) { |
|
| 276 | + return; |
|
| 277 | + } |
|
| 278 | + if (!empty($rangeArray)) { |
|
| 279 | + try { |
|
| 280 | + if (count($rangeArray) == 1) { |
|
| 281 | + $view->readfilePart($filename, $rangeArray[0]['from'], $rangeArray[0]['to']); |
|
| 282 | + } |
|
| 283 | + else { |
|
| 284 | + // check if file is seekable (if not throw UnseekableException) |
|
| 285 | + // we have to check it before body contents |
|
| 286 | + $view->readfilePart($filename, $rangeArray[0]['size'], $rangeArray[0]['size']); |
|
| 287 | + |
|
| 288 | + $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); |
|
| 289 | + |
|
| 290 | + foreach ($rangeArray as $range) { |
|
| 291 | + echo "\r\n--".self::getBoundary()."\r\n". |
|
| 292 | + "Content-type: ".$type."\r\n". |
|
| 293 | + "Content-range: bytes ".$range['from']."-".$range['to']."/".$range['size']."\r\n\r\n"; |
|
| 294 | + $view->readfilePart($filename, $range['from'], $range['to']); |
|
| 295 | + } |
|
| 296 | + echo "\r\n--".self::getBoundary()."--\r\n"; |
|
| 297 | + } |
|
| 298 | + } catch (\OCP\Files\UnseekableException $ex) { |
|
| 299 | + // file is unseekable |
|
| 300 | + header_remove('Accept-Ranges'); |
|
| 301 | + header_remove('Content-Range'); |
|
| 302 | + header("HTTP/1.1 200 OK"); |
|
| 303 | + self::sendHeaders($filename, $name, array()); |
|
| 304 | + $view->readfile($filename); |
|
| 305 | + } |
|
| 306 | + } |
|
| 307 | + else { |
|
| 308 | + $view->readfile($filename); |
|
| 309 | + } |
|
| 310 | + } |
|
| 311 | + |
|
| 312 | + /** |
|
| 313 | + * @param View $view |
|
| 314 | + * @param string $dir |
|
| 315 | + * @param string[]|string $files |
|
| 316 | + */ |
|
| 317 | + public static function lockFiles($view, $dir, $files) { |
|
| 318 | + if (!is_array($files)) { |
|
| 319 | + $file = $dir . '/' . $files; |
|
| 320 | + $files = [$file]; |
|
| 321 | + } |
|
| 322 | + foreach ($files as $file) { |
|
| 323 | + $file = $dir . '/' . $file; |
|
| 324 | + $view->lockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 325 | + if ($view->is_dir($file)) { |
|
| 326 | + $contents = $view->getDirectoryContent($file); |
|
| 327 | + $contents = array_map(function($fileInfo) use ($file) { |
|
| 328 | + /** @var \OCP\Files\FileInfo $fileInfo */ |
|
| 329 | + return $file . '/' . $fileInfo->getName(); |
|
| 330 | + }, $contents); |
|
| 331 | + self::lockFiles($view, $dir, $contents); |
|
| 332 | + } |
|
| 333 | + } |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * set the maximum upload size limit for apache hosts using .htaccess |
|
| 338 | + * |
|
| 339 | + * @param int $size file size in bytes |
|
| 340 | + * @param array $files override '.htaccess' and '.user.ini' locations |
|
| 341 | + * @return bool false on failure, size on success |
|
| 342 | + */ |
|
| 343 | + public static function setUploadLimit($size, $files = []) { |
|
| 344 | + //don't allow user to break his config |
|
| 345 | + $size = intval($size); |
|
| 346 | + if ($size < self::UPLOAD_MIN_LIMIT_BYTES) { |
|
| 347 | + return false; |
|
| 348 | + } |
|
| 349 | + $size = OC_Helper::phpFileSize($size); |
|
| 350 | + |
|
| 351 | + $phpValueKeys = array( |
|
| 352 | + 'upload_max_filesize', |
|
| 353 | + 'post_max_size' |
|
| 354 | + ); |
|
| 355 | + |
|
| 356 | + // default locations if not overridden by $files |
|
| 357 | + $files = array_merge([ |
|
| 358 | + '.htaccess' => OC::$SERVERROOT . '/.htaccess', |
|
| 359 | + '.user.ini' => OC::$SERVERROOT . '/.user.ini' |
|
| 360 | + ], $files); |
|
| 361 | + |
|
| 362 | + $updateFiles = [ |
|
| 363 | + $files['.htaccess'] => [ |
|
| 364 | + 'pattern' => '/php_value %1$s (\S)*/', |
|
| 365 | + 'setting' => 'php_value %1$s %2$s' |
|
| 366 | + ], |
|
| 367 | + $files['.user.ini'] => [ |
|
| 368 | + 'pattern' => '/%1$s=(\S)*/', |
|
| 369 | + 'setting' => '%1$s=%2$s' |
|
| 370 | + ] |
|
| 371 | + ]; |
|
| 372 | + |
|
| 373 | + $success = true; |
|
| 374 | + |
|
| 375 | + foreach ($updateFiles as $filename => $patternMap) { |
|
| 376 | + // suppress warnings from fopen() |
|
| 377 | + $handle = @fopen($filename, 'r+'); |
|
| 378 | + if (!$handle) { |
|
| 379 | + \OCP\Util::writeLog('files', |
|
| 380 | + 'Can\'t write upload limit to ' . $filename . '. Please check the file permissions', |
|
| 381 | + \OCP\Util::WARN); |
|
| 382 | + $success = false; |
|
| 383 | + continue; // try to update as many files as possible |
|
| 384 | + } |
|
| 385 | + |
|
| 386 | + $content = ''; |
|
| 387 | + while (!feof($handle)) { |
|
| 388 | + $content .= fread($handle, 1000); |
|
| 389 | + } |
|
| 390 | + |
|
| 391 | + foreach ($phpValueKeys as $key) { |
|
| 392 | + $pattern = vsprintf($patternMap['pattern'], [$key]); |
|
| 393 | + $setting = vsprintf($patternMap['setting'], [$key, $size]); |
|
| 394 | + $hasReplaced = 0; |
|
| 395 | + $newContent = preg_replace($pattern, $setting, $content, 2, $hasReplaced); |
|
| 396 | + if ($newContent !== null) { |
|
| 397 | + $content = $newContent; |
|
| 398 | + } |
|
| 399 | + if ($hasReplaced === 0) { |
|
| 400 | + $content .= "\n" . $setting; |
|
| 401 | + } |
|
| 402 | + } |
|
| 403 | + |
|
| 404 | + // write file back |
|
| 405 | + ftruncate($handle, 0); |
|
| 406 | + rewind($handle); |
|
| 407 | + fwrite($handle, $content); |
|
| 408 | + |
|
| 409 | + fclose($handle); |
|
| 410 | + } |
|
| 411 | + |
|
| 412 | + if ($success) { |
|
| 413 | + return OC_Helper::computerFileSize($size); |
|
| 414 | + } |
|
| 415 | + return false; |
|
| 416 | + } |
|
| 417 | + |
|
| 418 | + /** |
|
| 419 | + * @param string $dir |
|
| 420 | + * @param $files |
|
| 421 | + * @param integer $getType |
|
| 422 | + * @param View $view |
|
| 423 | + * @param string $filename |
|
| 424 | + */ |
|
| 425 | + private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) { |
|
| 426 | + if ($getType === self::FILE) { |
|
| 427 | + $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); |
|
| 428 | + } |
|
| 429 | + if ($getType === self::ZIP_FILES) { |
|
| 430 | + foreach ($files as $file) { |
|
| 431 | + $file = $dir . '/' . $file; |
|
| 432 | + $view->unlockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 433 | + } |
|
| 434 | + } |
|
| 435 | + if ($getType === self::ZIP_DIR) { |
|
| 436 | + $file = $dir . '/' . $files; |
|
| 437 | + $view->unlockFile($file, ILockingProvider::LOCK_SHARED); |
|
| 438 | + } |
|
| 439 | + } |
|
| 440 | 440 | |
| 441 | 441 | } |
@@ -27,98 +27,98 @@ discard block |
||
| 27 | 27 | namespace OC\Template; |
| 28 | 28 | |
| 29 | 29 | abstract class ResourceLocator { |
| 30 | - protected $theme; |
|
| 30 | + protected $theme; |
|
| 31 | 31 | |
| 32 | - protected $mapping; |
|
| 33 | - protected $serverroot; |
|
| 34 | - protected $thirdpartyroot; |
|
| 35 | - protected $webroot; |
|
| 32 | + protected $mapping; |
|
| 33 | + protected $serverroot; |
|
| 34 | + protected $thirdpartyroot; |
|
| 35 | + protected $webroot; |
|
| 36 | 36 | |
| 37 | - protected $resources = array(); |
|
| 37 | + protected $resources = array(); |
|
| 38 | 38 | |
| 39 | - /** @var \OCP\ILogger */ |
|
| 40 | - protected $logger; |
|
| 39 | + /** @var \OCP\ILogger */ |
|
| 40 | + protected $logger; |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * @param \OCP\ILogger $logger |
|
| 44 | - * @param string $theme |
|
| 45 | - * @param array $core_map |
|
| 46 | - * @param array $party_map |
|
| 47 | - */ |
|
| 48 | - public function __construct(\OCP\ILogger $logger, $theme, $core_map, $party_map) { |
|
| 49 | - $this->logger = $logger; |
|
| 50 | - $this->theme = $theme; |
|
| 51 | - $this->mapping = $core_map + $party_map; |
|
| 52 | - $this->serverroot = key($core_map); |
|
| 53 | - $this->thirdpartyroot = key($party_map); |
|
| 54 | - $this->webroot = $this->mapping[$this->serverroot]; |
|
| 55 | - } |
|
| 42 | + /** |
|
| 43 | + * @param \OCP\ILogger $logger |
|
| 44 | + * @param string $theme |
|
| 45 | + * @param array $core_map |
|
| 46 | + * @param array $party_map |
|
| 47 | + */ |
|
| 48 | + public function __construct(\OCP\ILogger $logger, $theme, $core_map, $party_map) { |
|
| 49 | + $this->logger = $logger; |
|
| 50 | + $this->theme = $theme; |
|
| 51 | + $this->mapping = $core_map + $party_map; |
|
| 52 | + $this->serverroot = key($core_map); |
|
| 53 | + $this->thirdpartyroot = key($party_map); |
|
| 54 | + $this->webroot = $this->mapping[$this->serverroot]; |
|
| 55 | + } |
|
| 56 | 56 | |
| 57 | - /** |
|
| 58 | - * @param string $resource |
|
| 59 | - */ |
|
| 60 | - abstract public function doFind($resource); |
|
| 57 | + /** |
|
| 58 | + * @param string $resource |
|
| 59 | + */ |
|
| 60 | + abstract public function doFind($resource); |
|
| 61 | 61 | |
| 62 | - /** |
|
| 63 | - * @param string $resource |
|
| 64 | - */ |
|
| 65 | - abstract public function doFindTheme($resource); |
|
| 62 | + /** |
|
| 63 | + * @param string $resource |
|
| 64 | + */ |
|
| 65 | + abstract public function doFindTheme($resource); |
|
| 66 | 66 | |
| 67 | - /** |
|
| 68 | - * Finds the resources and adds them to the list |
|
| 69 | - * |
|
| 70 | - * @param array $resources |
|
| 71 | - */ |
|
| 72 | - public function find($resources) { |
|
| 73 | - foreach ($resources as $resource) { |
|
| 74 | - try { |
|
| 75 | - $this->doFind($resource); |
|
| 76 | - } catch (ResourceNotFoundException $e) { |
|
| 77 | - $resourceApp = substr($resource, 0, strpos($resource, '/')); |
|
| 78 | - $this->logger->debug('Could not find resource file "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 79 | - } |
|
| 80 | - } |
|
| 81 | - if (!empty($this->theme)) { |
|
| 82 | - foreach ($resources as $resource) { |
|
| 83 | - try { |
|
| 84 | - $this->doFindTheme($resource); |
|
| 85 | - } catch (ResourceNotFoundException $e) { |
|
| 86 | - $resourceApp = substr($resource, 0, strpos($resource, '/')); |
|
| 87 | - $this->logger->debug('Could not find resource file in theme "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 88 | - } |
|
| 89 | - } |
|
| 90 | - } |
|
| 91 | - } |
|
| 67 | + /** |
|
| 68 | + * Finds the resources and adds them to the list |
|
| 69 | + * |
|
| 70 | + * @param array $resources |
|
| 71 | + */ |
|
| 72 | + public function find($resources) { |
|
| 73 | + foreach ($resources as $resource) { |
|
| 74 | + try { |
|
| 75 | + $this->doFind($resource); |
|
| 76 | + } catch (ResourceNotFoundException $e) { |
|
| 77 | + $resourceApp = substr($resource, 0, strpos($resource, '/')); |
|
| 78 | + $this->logger->debug('Could not find resource file "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 79 | + } |
|
| 80 | + } |
|
| 81 | + if (!empty($this->theme)) { |
|
| 82 | + foreach ($resources as $resource) { |
|
| 83 | + try { |
|
| 84 | + $this->doFindTheme($resource); |
|
| 85 | + } catch (ResourceNotFoundException $e) { |
|
| 86 | + $resourceApp = substr($resource, 0, strpos($resource, '/')); |
|
| 87 | + $this->logger->debug('Could not find resource file in theme "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 88 | + } |
|
| 89 | + } |
|
| 90 | + } |
|
| 91 | + } |
|
| 92 | 92 | |
| 93 | - /** |
|
| 94 | - * append the $file resource if exist at $root |
|
| 95 | - * |
|
| 96 | - * @param string $root path to check |
|
| 97 | - * @param string $file the filename |
|
| 98 | - * @param string|null $webRoot base for path, default map $root to $webRoot |
|
| 99 | - * @return bool True if the resource was found, false otherwise |
|
| 100 | - */ |
|
| 101 | - protected function appendIfExist($root, $file, $webRoot = null) { |
|
| 102 | - if (is_file($root.'/'.$file)) { |
|
| 103 | - $this->append($root, $file, $webRoot, false); |
|
| 104 | - return true; |
|
| 105 | - } |
|
| 106 | - return false; |
|
| 107 | - } |
|
| 93 | + /** |
|
| 94 | + * append the $file resource if exist at $root |
|
| 95 | + * |
|
| 96 | + * @param string $root path to check |
|
| 97 | + * @param string $file the filename |
|
| 98 | + * @param string|null $webRoot base for path, default map $root to $webRoot |
|
| 99 | + * @return bool True if the resource was found, false otherwise |
|
| 100 | + */ |
|
| 101 | + protected function appendIfExist($root, $file, $webRoot = null) { |
|
| 102 | + if (is_file($root.'/'.$file)) { |
|
| 103 | + $this->append($root, $file, $webRoot, false); |
|
| 104 | + return true; |
|
| 105 | + } |
|
| 106 | + return false; |
|
| 107 | + } |
|
| 108 | 108 | |
| 109 | - /** |
|
| 110 | - * append the $file resource at $root |
|
| 111 | - * |
|
| 112 | - * @param string $root path to check |
|
| 113 | - * @param string $file the filename |
|
| 114 | - * @param string|null $webRoot base for path, default map $root to $webRoot |
|
| 115 | - * @param bool $throw Throw an exception, when the route does not exist |
|
| 116 | - * @throws ResourceNotFoundException Only thrown when $throw is true and the resource is missing |
|
| 117 | - */ |
|
| 118 | - protected function append($root, $file, $webRoot = null, $throw = true) { |
|
| 119 | - if (!$webRoot) { |
|
| 120 | - $tmpRoot = $root; |
|
| 121 | - /* |
|
| 109 | + /** |
|
| 110 | + * append the $file resource at $root |
|
| 111 | + * |
|
| 112 | + * @param string $root path to check |
|
| 113 | + * @param string $file the filename |
|
| 114 | + * @param string|null $webRoot base for path, default map $root to $webRoot |
|
| 115 | + * @param bool $throw Throw an exception, when the route does not exist |
|
| 116 | + * @throws ResourceNotFoundException Only thrown when $throw is true and the resource is missing |
|
| 117 | + */ |
|
| 118 | + protected function append($root, $file, $webRoot = null, $throw = true) { |
|
| 119 | + if (!$webRoot) { |
|
| 120 | + $tmpRoot = $root; |
|
| 121 | + /* |
|
| 122 | 122 | * traverse the potential web roots upwards in the path |
| 123 | 123 | * |
| 124 | 124 | * example: |
@@ -129,39 +129,39 @@ discard block |
||
| 129 | 129 | * then /srv/www/apps, /srv/www/apps, /srv/www, ... until we find a |
| 130 | 130 | * valid web root |
| 131 | 131 | */ |
| 132 | - do { |
|
| 133 | - if (isset($this->mapping[$tmpRoot])) { |
|
| 134 | - $webRoot = $this->mapping[$tmpRoot]; |
|
| 135 | - break; |
|
| 136 | - } |
|
| 132 | + do { |
|
| 133 | + if (isset($this->mapping[$tmpRoot])) { |
|
| 134 | + $webRoot = $this->mapping[$tmpRoot]; |
|
| 135 | + break; |
|
| 136 | + } |
|
| 137 | 137 | |
| 138 | - if ($tmpRoot === '/') { |
|
| 139 | - $webRoot = ''; |
|
| 140 | - $this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [ |
|
| 141 | - 'app' => 'lib', |
|
| 142 | - 'root' => $root, |
|
| 143 | - 'file' => $file, |
|
| 144 | - 'webRoot' => $webRoot, |
|
| 145 | - 'throw' => $throw ? 'true' : 'false' |
|
| 146 | - ]); |
|
| 147 | - break; |
|
| 148 | - } |
|
| 149 | - $tmpRoot = dirname($tmpRoot); |
|
| 150 | - } while(true); |
|
| 138 | + if ($tmpRoot === '/') { |
|
| 139 | + $webRoot = ''; |
|
| 140 | + $this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [ |
|
| 141 | + 'app' => 'lib', |
|
| 142 | + 'root' => $root, |
|
| 143 | + 'file' => $file, |
|
| 144 | + 'webRoot' => $webRoot, |
|
| 145 | + 'throw' => $throw ? 'true' : 'false' |
|
| 146 | + ]); |
|
| 147 | + break; |
|
| 148 | + } |
|
| 149 | + $tmpRoot = dirname($tmpRoot); |
|
| 150 | + } while(true); |
|
| 151 | 151 | |
| 152 | - } |
|
| 153 | - $this->resources[] = array($root, $webRoot, $file); |
|
| 152 | + } |
|
| 153 | + $this->resources[] = array($root, $webRoot, $file); |
|
| 154 | 154 | |
| 155 | - if ($throw && !is_file($root . '/' . $file)) { |
|
| 156 | - throw new ResourceNotFoundException($file, $webRoot); |
|
| 157 | - } |
|
| 158 | - } |
|
| 155 | + if ($throw && !is_file($root . '/' . $file)) { |
|
| 156 | + throw new ResourceNotFoundException($file, $webRoot); |
|
| 157 | + } |
|
| 158 | + } |
|
| 159 | 159 | |
| 160 | - /** |
|
| 161 | - * Returns the list of all resources that should be loaded |
|
| 162 | - * @return array |
|
| 163 | - */ |
|
| 164 | - public function getResources() { |
|
| 165 | - return $this->resources; |
|
| 166 | - } |
|
| 160 | + /** |
|
| 161 | + * Returns the list of all resources that should be loaded |
|
| 162 | + * @return array |
|
| 163 | + */ |
|
| 164 | + public function getResources() { |
|
| 165 | + return $this->resources; |
|
| 166 | + } |
|
| 167 | 167 | } |
@@ -75,7 +75,7 @@ discard block |
||
| 75 | 75 | $this->doFind($resource); |
| 76 | 76 | } catch (ResourceNotFoundException $e) { |
| 77 | 77 | $resourceApp = substr($resource, 0, strpos($resource, '/')); |
| 78 | - $this->logger->debug('Could not find resource file "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 78 | + $this->logger->debug('Could not find resource file "'.$e->getResourcePath().'"', ['app' => $resourceApp]); |
|
| 79 | 79 | } |
| 80 | 80 | } |
| 81 | 81 | if (!empty($this->theme)) { |
@@ -84,7 +84,7 @@ discard block |
||
| 84 | 84 | $this->doFindTheme($resource); |
| 85 | 85 | } catch (ResourceNotFoundException $e) { |
| 86 | 86 | $resourceApp = substr($resource, 0, strpos($resource, '/')); |
| 87 | - $this->logger->debug('Could not find resource file in theme "' . $e->getResourcePath() . '"', ['app' => $resourceApp]); |
|
| 87 | + $this->logger->debug('Could not find resource file in theme "'.$e->getResourcePath().'"', ['app' => $resourceApp]); |
|
| 88 | 88 | } |
| 89 | 89 | } |
| 90 | 90 | } |
@@ -147,12 +147,12 @@ discard block |
||
| 147 | 147 | break; |
| 148 | 148 | } |
| 149 | 149 | $tmpRoot = dirname($tmpRoot); |
| 150 | - } while(true); |
|
| 150 | + } while (true); |
|
| 151 | 151 | |
| 152 | 152 | } |
| 153 | 153 | $this->resources[] = array($root, $webRoot, $file); |
| 154 | 154 | |
| 155 | - if ($throw && !is_file($root . '/' . $file)) { |
|
| 155 | + if ($throw && !is_file($root.'/'.$file)) { |
|
| 156 | 156 | throw new ResourceNotFoundException($file, $webRoot); |
| 157 | 157 | } |
| 158 | 158 | } |
@@ -35,273 +35,273 @@ |
||
| 35 | 35 | |
| 36 | 36 | class DefaultTokenProvider implements IProvider { |
| 37 | 37 | |
| 38 | - /** @var DefaultTokenMapper */ |
|
| 39 | - private $mapper; |
|
| 38 | + /** @var DefaultTokenMapper */ |
|
| 39 | + private $mapper; |
|
| 40 | 40 | |
| 41 | - /** @var ICrypto */ |
|
| 42 | - private $crypto; |
|
| 41 | + /** @var ICrypto */ |
|
| 42 | + private $crypto; |
|
| 43 | 43 | |
| 44 | - /** @var IConfig */ |
|
| 45 | - private $config; |
|
| 44 | + /** @var IConfig */ |
|
| 45 | + private $config; |
|
| 46 | 46 | |
| 47 | - /** @var ILogger $logger */ |
|
| 48 | - private $logger; |
|
| 47 | + /** @var ILogger $logger */ |
|
| 48 | + private $logger; |
|
| 49 | 49 | |
| 50 | - /** @var ITimeFactory $time */ |
|
| 51 | - private $time; |
|
| 50 | + /** @var ITimeFactory $time */ |
|
| 51 | + private $time; |
|
| 52 | 52 | |
| 53 | - /** |
|
| 54 | - * @param DefaultTokenMapper $mapper |
|
| 55 | - * @param ICrypto $crypto |
|
| 56 | - * @param IConfig $config |
|
| 57 | - * @param ILogger $logger |
|
| 58 | - * @param ITimeFactory $time |
|
| 59 | - */ |
|
| 60 | - public function __construct(DefaultTokenMapper $mapper, |
|
| 61 | - ICrypto $crypto, |
|
| 62 | - IConfig $config, |
|
| 63 | - ILogger $logger, |
|
| 64 | - ITimeFactory $time) { |
|
| 65 | - $this->mapper = $mapper; |
|
| 66 | - $this->crypto = $crypto; |
|
| 67 | - $this->config = $config; |
|
| 68 | - $this->logger = $logger; |
|
| 69 | - $this->time = $time; |
|
| 70 | - } |
|
| 53 | + /** |
|
| 54 | + * @param DefaultTokenMapper $mapper |
|
| 55 | + * @param ICrypto $crypto |
|
| 56 | + * @param IConfig $config |
|
| 57 | + * @param ILogger $logger |
|
| 58 | + * @param ITimeFactory $time |
|
| 59 | + */ |
|
| 60 | + public function __construct(DefaultTokenMapper $mapper, |
|
| 61 | + ICrypto $crypto, |
|
| 62 | + IConfig $config, |
|
| 63 | + ILogger $logger, |
|
| 64 | + ITimeFactory $time) { |
|
| 65 | + $this->mapper = $mapper; |
|
| 66 | + $this->crypto = $crypto; |
|
| 67 | + $this->config = $config; |
|
| 68 | + $this->logger = $logger; |
|
| 69 | + $this->time = $time; |
|
| 70 | + } |
|
| 71 | 71 | |
| 72 | - /** |
|
| 73 | - * Create and persist a new token |
|
| 74 | - * |
|
| 75 | - * @param string $token |
|
| 76 | - * @param string $uid |
|
| 77 | - * @param string $loginName |
|
| 78 | - * @param string|null $password |
|
| 79 | - * @param string $name |
|
| 80 | - * @param int $type token type |
|
| 81 | - * @param int $remember whether the session token should be used for remember-me |
|
| 82 | - * @return IToken |
|
| 83 | - */ |
|
| 84 | - public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER) { |
|
| 85 | - $dbToken = new DefaultToken(); |
|
| 86 | - $dbToken->setUid($uid); |
|
| 87 | - $dbToken->setLoginName($loginName); |
|
| 88 | - if (!is_null($password)) { |
|
| 89 | - $dbToken->setPassword($this->encryptPassword($password, $token)); |
|
| 90 | - } |
|
| 91 | - $dbToken->setName($name); |
|
| 92 | - $dbToken->setToken($this->hashToken($token)); |
|
| 93 | - $dbToken->setType($type); |
|
| 94 | - $dbToken->setRemember($remember); |
|
| 95 | - $dbToken->setLastActivity($this->time->getTime()); |
|
| 72 | + /** |
|
| 73 | + * Create and persist a new token |
|
| 74 | + * |
|
| 75 | + * @param string $token |
|
| 76 | + * @param string $uid |
|
| 77 | + * @param string $loginName |
|
| 78 | + * @param string|null $password |
|
| 79 | + * @param string $name |
|
| 80 | + * @param int $type token type |
|
| 81 | + * @param int $remember whether the session token should be used for remember-me |
|
| 82 | + * @return IToken |
|
| 83 | + */ |
|
| 84 | + public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER) { |
|
| 85 | + $dbToken = new DefaultToken(); |
|
| 86 | + $dbToken->setUid($uid); |
|
| 87 | + $dbToken->setLoginName($loginName); |
|
| 88 | + if (!is_null($password)) { |
|
| 89 | + $dbToken->setPassword($this->encryptPassword($password, $token)); |
|
| 90 | + } |
|
| 91 | + $dbToken->setName($name); |
|
| 92 | + $dbToken->setToken($this->hashToken($token)); |
|
| 93 | + $dbToken->setType($type); |
|
| 94 | + $dbToken->setRemember($remember); |
|
| 95 | + $dbToken->setLastActivity($this->time->getTime()); |
|
| 96 | 96 | |
| 97 | - $this->mapper->insert($dbToken); |
|
| 97 | + $this->mapper->insert($dbToken); |
|
| 98 | 98 | |
| 99 | - return $dbToken; |
|
| 100 | - } |
|
| 99 | + return $dbToken; |
|
| 100 | + } |
|
| 101 | 101 | |
| 102 | - /** |
|
| 103 | - * Save the updated token |
|
| 104 | - * |
|
| 105 | - * @param IToken $token |
|
| 106 | - * @throws InvalidTokenException |
|
| 107 | - */ |
|
| 108 | - public function updateToken(IToken $token) { |
|
| 109 | - if (!($token instanceof DefaultToken)) { |
|
| 110 | - throw new InvalidTokenException(); |
|
| 111 | - } |
|
| 112 | - $this->mapper->update($token); |
|
| 113 | - } |
|
| 102 | + /** |
|
| 103 | + * Save the updated token |
|
| 104 | + * |
|
| 105 | + * @param IToken $token |
|
| 106 | + * @throws InvalidTokenException |
|
| 107 | + */ |
|
| 108 | + public function updateToken(IToken $token) { |
|
| 109 | + if (!($token instanceof DefaultToken)) { |
|
| 110 | + throw new InvalidTokenException(); |
|
| 111 | + } |
|
| 112 | + $this->mapper->update($token); |
|
| 113 | + } |
|
| 114 | 114 | |
| 115 | - /** |
|
| 116 | - * Update token activity timestamp |
|
| 117 | - * |
|
| 118 | - * @throws InvalidTokenException |
|
| 119 | - * @param IToken $token |
|
| 120 | - */ |
|
| 121 | - public function updateTokenActivity(IToken $token) { |
|
| 122 | - if (!($token instanceof DefaultToken)) { |
|
| 123 | - throw new InvalidTokenException(); |
|
| 124 | - } |
|
| 125 | - /** @var DefaultToken $token */ |
|
| 126 | - $now = $this->time->getTime(); |
|
| 127 | - if ($token->getLastActivity() < ($now - 60)) { |
|
| 128 | - // Update token only once per minute |
|
| 129 | - $token->setLastActivity($now); |
|
| 130 | - $this->mapper->update($token); |
|
| 131 | - } |
|
| 132 | - } |
|
| 115 | + /** |
|
| 116 | + * Update token activity timestamp |
|
| 117 | + * |
|
| 118 | + * @throws InvalidTokenException |
|
| 119 | + * @param IToken $token |
|
| 120 | + */ |
|
| 121 | + public function updateTokenActivity(IToken $token) { |
|
| 122 | + if (!($token instanceof DefaultToken)) { |
|
| 123 | + throw new InvalidTokenException(); |
|
| 124 | + } |
|
| 125 | + /** @var DefaultToken $token */ |
|
| 126 | + $now = $this->time->getTime(); |
|
| 127 | + if ($token->getLastActivity() < ($now - 60)) { |
|
| 128 | + // Update token only once per minute |
|
| 129 | + $token->setLastActivity($now); |
|
| 130 | + $this->mapper->update($token); |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | 133 | |
| 134 | - /** |
|
| 135 | - * Get all token of a user |
|
| 136 | - * |
|
| 137 | - * The provider may limit the number of result rows in case of an abuse |
|
| 138 | - * where a high number of (session) tokens is generated |
|
| 139 | - * |
|
| 140 | - * @param IUser $user |
|
| 141 | - * @return IToken[] |
|
| 142 | - */ |
|
| 143 | - public function getTokenByUser(IUser $user) { |
|
| 144 | - return $this->mapper->getTokenByUser($user); |
|
| 145 | - } |
|
| 134 | + /** |
|
| 135 | + * Get all token of a user |
|
| 136 | + * |
|
| 137 | + * The provider may limit the number of result rows in case of an abuse |
|
| 138 | + * where a high number of (session) tokens is generated |
|
| 139 | + * |
|
| 140 | + * @param IUser $user |
|
| 141 | + * @return IToken[] |
|
| 142 | + */ |
|
| 143 | + public function getTokenByUser(IUser $user) { |
|
| 144 | + return $this->mapper->getTokenByUser($user); |
|
| 145 | + } |
|
| 146 | 146 | |
| 147 | - /** |
|
| 148 | - * Get a token by token |
|
| 149 | - * |
|
| 150 | - * @param string $tokenId |
|
| 151 | - * @throws InvalidTokenException |
|
| 152 | - * @return DefaultToken |
|
| 153 | - */ |
|
| 154 | - public function getToken($tokenId) { |
|
| 155 | - try { |
|
| 156 | - return $this->mapper->getToken($this->hashToken($tokenId)); |
|
| 157 | - } catch (DoesNotExistException $ex) { |
|
| 158 | - throw new InvalidTokenException(); |
|
| 159 | - } |
|
| 160 | - } |
|
| 147 | + /** |
|
| 148 | + * Get a token by token |
|
| 149 | + * |
|
| 150 | + * @param string $tokenId |
|
| 151 | + * @throws InvalidTokenException |
|
| 152 | + * @return DefaultToken |
|
| 153 | + */ |
|
| 154 | + public function getToken($tokenId) { |
|
| 155 | + try { |
|
| 156 | + return $this->mapper->getToken($this->hashToken($tokenId)); |
|
| 157 | + } catch (DoesNotExistException $ex) { |
|
| 158 | + throw new InvalidTokenException(); |
|
| 159 | + } |
|
| 160 | + } |
|
| 161 | 161 | |
| 162 | - /** |
|
| 163 | - * Get a token by token id |
|
| 164 | - * |
|
| 165 | - * @param string $tokenId |
|
| 166 | - * @throws InvalidTokenException |
|
| 167 | - * @return DefaultToken |
|
| 168 | - */ |
|
| 169 | - public function getTokenById($tokenId) { |
|
| 170 | - try { |
|
| 171 | - return $this->mapper->getTokenById($tokenId); |
|
| 172 | - } catch (DoesNotExistException $ex) { |
|
| 173 | - throw new InvalidTokenException(); |
|
| 174 | - } |
|
| 175 | - } |
|
| 162 | + /** |
|
| 163 | + * Get a token by token id |
|
| 164 | + * |
|
| 165 | + * @param string $tokenId |
|
| 166 | + * @throws InvalidTokenException |
|
| 167 | + * @return DefaultToken |
|
| 168 | + */ |
|
| 169 | + public function getTokenById($tokenId) { |
|
| 170 | + try { |
|
| 171 | + return $this->mapper->getTokenById($tokenId); |
|
| 172 | + } catch (DoesNotExistException $ex) { |
|
| 173 | + throw new InvalidTokenException(); |
|
| 174 | + } |
|
| 175 | + } |
|
| 176 | 176 | |
| 177 | - /** |
|
| 178 | - * @param string $oldSessionId |
|
| 179 | - * @param string $sessionId |
|
| 180 | - * @throws InvalidTokenException |
|
| 181 | - */ |
|
| 182 | - public function renewSessionToken($oldSessionId, $sessionId) { |
|
| 183 | - $token = $this->getToken($oldSessionId); |
|
| 177 | + /** |
|
| 178 | + * @param string $oldSessionId |
|
| 179 | + * @param string $sessionId |
|
| 180 | + * @throws InvalidTokenException |
|
| 181 | + */ |
|
| 182 | + public function renewSessionToken($oldSessionId, $sessionId) { |
|
| 183 | + $token = $this->getToken($oldSessionId); |
|
| 184 | 184 | |
| 185 | - $newToken = new DefaultToken(); |
|
| 186 | - $newToken->setUid($token->getUID()); |
|
| 187 | - $newToken->setLoginName($token->getLoginName()); |
|
| 188 | - if (!is_null($token->getPassword())) { |
|
| 189 | - $password = $this->decryptPassword($token->getPassword(), $oldSessionId); |
|
| 190 | - $newToken->setPassword($this->encryptPassword($password, $sessionId)); |
|
| 191 | - } |
|
| 192 | - $newToken->setName($token->getName()); |
|
| 193 | - $newToken->setToken($this->hashToken($sessionId)); |
|
| 194 | - $newToken->setType(IToken::TEMPORARY_TOKEN); |
|
| 195 | - $newToken->setRemember($token->getRemember()); |
|
| 196 | - $newToken->setLastActivity($this->time->getTime()); |
|
| 197 | - $this->mapper->insert($newToken); |
|
| 198 | - } |
|
| 185 | + $newToken = new DefaultToken(); |
|
| 186 | + $newToken->setUid($token->getUID()); |
|
| 187 | + $newToken->setLoginName($token->getLoginName()); |
|
| 188 | + if (!is_null($token->getPassword())) { |
|
| 189 | + $password = $this->decryptPassword($token->getPassword(), $oldSessionId); |
|
| 190 | + $newToken->setPassword($this->encryptPassword($password, $sessionId)); |
|
| 191 | + } |
|
| 192 | + $newToken->setName($token->getName()); |
|
| 193 | + $newToken->setToken($this->hashToken($sessionId)); |
|
| 194 | + $newToken->setType(IToken::TEMPORARY_TOKEN); |
|
| 195 | + $newToken->setRemember($token->getRemember()); |
|
| 196 | + $newToken->setLastActivity($this->time->getTime()); |
|
| 197 | + $this->mapper->insert($newToken); |
|
| 198 | + } |
|
| 199 | 199 | |
| 200 | - /** |
|
| 201 | - * @param IToken $savedToken |
|
| 202 | - * @param string $tokenId session token |
|
| 203 | - * @throws InvalidTokenException |
|
| 204 | - * @throws PasswordlessTokenException |
|
| 205 | - * @return string |
|
| 206 | - */ |
|
| 207 | - public function getPassword(IToken $savedToken, $tokenId) { |
|
| 208 | - $password = $savedToken->getPassword(); |
|
| 209 | - if (is_null($password)) { |
|
| 210 | - throw new PasswordlessTokenException(); |
|
| 211 | - } |
|
| 212 | - return $this->decryptPassword($password, $tokenId); |
|
| 213 | - } |
|
| 200 | + /** |
|
| 201 | + * @param IToken $savedToken |
|
| 202 | + * @param string $tokenId session token |
|
| 203 | + * @throws InvalidTokenException |
|
| 204 | + * @throws PasswordlessTokenException |
|
| 205 | + * @return string |
|
| 206 | + */ |
|
| 207 | + public function getPassword(IToken $savedToken, $tokenId) { |
|
| 208 | + $password = $savedToken->getPassword(); |
|
| 209 | + if (is_null($password)) { |
|
| 210 | + throw new PasswordlessTokenException(); |
|
| 211 | + } |
|
| 212 | + return $this->decryptPassword($password, $tokenId); |
|
| 213 | + } |
|
| 214 | 214 | |
| 215 | - /** |
|
| 216 | - * Encrypt and set the password of the given token |
|
| 217 | - * |
|
| 218 | - * @param IToken $token |
|
| 219 | - * @param string $tokenId |
|
| 220 | - * @param string $password |
|
| 221 | - * @throws InvalidTokenException |
|
| 222 | - */ |
|
| 223 | - public function setPassword(IToken $token, $tokenId, $password) { |
|
| 224 | - if (!($token instanceof DefaultToken)) { |
|
| 225 | - throw new InvalidTokenException(); |
|
| 226 | - } |
|
| 227 | - /** @var DefaultToken $token */ |
|
| 228 | - $token->setPassword($this->encryptPassword($password, $tokenId)); |
|
| 229 | - $this->mapper->update($token); |
|
| 230 | - } |
|
| 215 | + /** |
|
| 216 | + * Encrypt and set the password of the given token |
|
| 217 | + * |
|
| 218 | + * @param IToken $token |
|
| 219 | + * @param string $tokenId |
|
| 220 | + * @param string $password |
|
| 221 | + * @throws InvalidTokenException |
|
| 222 | + */ |
|
| 223 | + public function setPassword(IToken $token, $tokenId, $password) { |
|
| 224 | + if (!($token instanceof DefaultToken)) { |
|
| 225 | + throw new InvalidTokenException(); |
|
| 226 | + } |
|
| 227 | + /** @var DefaultToken $token */ |
|
| 228 | + $token->setPassword($this->encryptPassword($password, $tokenId)); |
|
| 229 | + $this->mapper->update($token); |
|
| 230 | + } |
|
| 231 | 231 | |
| 232 | - /** |
|
| 233 | - * Invalidate (delete) the given session token |
|
| 234 | - * |
|
| 235 | - * @param string $token |
|
| 236 | - */ |
|
| 237 | - public function invalidateToken($token) { |
|
| 238 | - $this->mapper->invalidate($this->hashToken($token)); |
|
| 239 | - } |
|
| 232 | + /** |
|
| 233 | + * Invalidate (delete) the given session token |
|
| 234 | + * |
|
| 235 | + * @param string $token |
|
| 236 | + */ |
|
| 237 | + public function invalidateToken($token) { |
|
| 238 | + $this->mapper->invalidate($this->hashToken($token)); |
|
| 239 | + } |
|
| 240 | 240 | |
| 241 | - /** |
|
| 242 | - * Invalidate (delete) the given token |
|
| 243 | - * |
|
| 244 | - * @param IUser $user |
|
| 245 | - * @param int $id |
|
| 246 | - */ |
|
| 247 | - public function invalidateTokenById(IUser $user, $id) { |
|
| 248 | - $this->mapper->deleteById($user, $id); |
|
| 249 | - } |
|
| 241 | + /** |
|
| 242 | + * Invalidate (delete) the given token |
|
| 243 | + * |
|
| 244 | + * @param IUser $user |
|
| 245 | + * @param int $id |
|
| 246 | + */ |
|
| 247 | + public function invalidateTokenById(IUser $user, $id) { |
|
| 248 | + $this->mapper->deleteById($user, $id); |
|
| 249 | + } |
|
| 250 | 250 | |
| 251 | - /** |
|
| 252 | - * Invalidate (delete) old session tokens |
|
| 253 | - */ |
|
| 254 | - public function invalidateOldTokens() { |
|
| 255 | - $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); |
|
| 256 | - $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']); |
|
| 257 | - $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER); |
|
| 258 | - $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); |
|
| 259 | - $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']); |
|
| 260 | - $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER); |
|
| 261 | - } |
|
| 251 | + /** |
|
| 252 | + * Invalidate (delete) old session tokens |
|
| 253 | + */ |
|
| 254 | + public function invalidateOldTokens() { |
|
| 255 | + $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); |
|
| 256 | + $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']); |
|
| 257 | + $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER); |
|
| 258 | + $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); |
|
| 259 | + $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']); |
|
| 260 | + $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER); |
|
| 261 | + } |
|
| 262 | 262 | |
| 263 | - /** |
|
| 264 | - * @param string $token |
|
| 265 | - * @return string |
|
| 266 | - */ |
|
| 267 | - private function hashToken($token) { |
|
| 268 | - $secret = $this->config->getSystemValue('secret'); |
|
| 269 | - return hash('sha512', $token . $secret); |
|
| 270 | - } |
|
| 263 | + /** |
|
| 264 | + * @param string $token |
|
| 265 | + * @return string |
|
| 266 | + */ |
|
| 267 | + private function hashToken($token) { |
|
| 268 | + $secret = $this->config->getSystemValue('secret'); |
|
| 269 | + return hash('sha512', $token . $secret); |
|
| 270 | + } |
|
| 271 | 271 | |
| 272 | - /** |
|
| 273 | - * Encrypt the given password |
|
| 274 | - * |
|
| 275 | - * The token is used as key |
|
| 276 | - * |
|
| 277 | - * @param string $password |
|
| 278 | - * @param string $token |
|
| 279 | - * @return string encrypted password |
|
| 280 | - */ |
|
| 281 | - private function encryptPassword($password, $token) { |
|
| 282 | - $secret = $this->config->getSystemValue('secret'); |
|
| 283 | - return $this->crypto->encrypt($password, $token . $secret); |
|
| 284 | - } |
|
| 272 | + /** |
|
| 273 | + * Encrypt the given password |
|
| 274 | + * |
|
| 275 | + * The token is used as key |
|
| 276 | + * |
|
| 277 | + * @param string $password |
|
| 278 | + * @param string $token |
|
| 279 | + * @return string encrypted password |
|
| 280 | + */ |
|
| 281 | + private function encryptPassword($password, $token) { |
|
| 282 | + $secret = $this->config->getSystemValue('secret'); |
|
| 283 | + return $this->crypto->encrypt($password, $token . $secret); |
|
| 284 | + } |
|
| 285 | 285 | |
| 286 | - /** |
|
| 287 | - * Decrypt the given password |
|
| 288 | - * |
|
| 289 | - * The token is used as key |
|
| 290 | - * |
|
| 291 | - * @param string $password |
|
| 292 | - * @param string $token |
|
| 293 | - * @throws InvalidTokenException |
|
| 294 | - * @return string the decrypted key |
|
| 295 | - */ |
|
| 296 | - private function decryptPassword($password, $token) { |
|
| 297 | - $secret = $this->config->getSystemValue('secret'); |
|
| 298 | - try { |
|
| 299 | - return $this->crypto->decrypt($password, $token . $secret); |
|
| 300 | - } catch (Exception $ex) { |
|
| 301 | - // Delete the invalid token |
|
| 302 | - $this->invalidateToken($token); |
|
| 303 | - throw new InvalidTokenException(); |
|
| 304 | - } |
|
| 305 | - } |
|
| 286 | + /** |
|
| 287 | + * Decrypt the given password |
|
| 288 | + * |
|
| 289 | + * The token is used as key |
|
| 290 | + * |
|
| 291 | + * @param string $password |
|
| 292 | + * @param string $token |
|
| 293 | + * @throws InvalidTokenException |
|
| 294 | + * @return string the decrypted key |
|
| 295 | + */ |
|
| 296 | + private function decryptPassword($password, $token) { |
|
| 297 | + $secret = $this->config->getSystemValue('secret'); |
|
| 298 | + try { |
|
| 299 | + return $this->crypto->decrypt($password, $token . $secret); |
|
| 300 | + } catch (Exception $ex) { |
|
| 301 | + // Delete the invalid token |
|
| 302 | + $this->invalidateToken($token); |
|
| 303 | + throw new InvalidTokenException(); |
|
| 304 | + } |
|
| 305 | + } |
|
| 306 | 306 | |
| 307 | 307 | } |
@@ -253,10 +253,10 @@ discard block |
||
| 253 | 253 | */ |
| 254 | 254 | public function invalidateOldTokens() { |
| 255 | 255 | $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); |
| 256 | - $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']); |
|
| 256 | + $this->logger->debug('Invalidating session tokens older than '.date('c', $olderThan), ['app' => 'cron']); |
|
| 257 | 257 | $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER); |
| 258 | 258 | $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); |
| 259 | - $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']); |
|
| 259 | + $this->logger->debug('Invalidating remembered session tokens older than '.date('c', $rememberThreshold), ['app' => 'cron']); |
|
| 260 | 260 | $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER); |
| 261 | 261 | } |
| 262 | 262 | |
@@ -266,7 +266,7 @@ discard block |
||
| 266 | 266 | */ |
| 267 | 267 | private function hashToken($token) { |
| 268 | 268 | $secret = $this->config->getSystemValue('secret'); |
| 269 | - return hash('sha512', $token . $secret); |
|
| 269 | + return hash('sha512', $token.$secret); |
|
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | /** |
@@ -280,7 +280,7 @@ discard block |
||
| 280 | 280 | */ |
| 281 | 281 | private function encryptPassword($password, $token) { |
| 282 | 282 | $secret = $this->config->getSystemValue('secret'); |
| 283 | - return $this->crypto->encrypt($password, $token . $secret); |
|
| 283 | + return $this->crypto->encrypt($password, $token.$secret); |
|
| 284 | 284 | } |
| 285 | 285 | |
| 286 | 286 | /** |
@@ -296,7 +296,7 @@ discard block |
||
| 296 | 296 | private function decryptPassword($password, $token) { |
| 297 | 297 | $secret = $this->config->getSystemValue('secret'); |
| 298 | 298 | try { |
| 299 | - return $this->crypto->decrypt($password, $token . $secret); |
|
| 299 | + return $this->crypto->decrypt($password, $token.$secret); |
|
| 300 | 300 | } catch (Exception $ex) { |
| 301 | 301 | // Delete the invalid token |
| 302 | 302 | $this->invalidateToken($token); |
@@ -37,7 +37,6 @@ |
||
| 37 | 37 | use Symfony\Component\Console\Input\InputInterface; |
| 38 | 38 | use Symfony\Component\Console\Input\InputOption; |
| 39 | 39 | use Symfony\Component\Console\Output\OutputInterface; |
| 40 | -use Symfony\Component\Console\Output\ConsoleOutputInterface; |
|
| 41 | 40 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
| 42 | 41 | |
| 43 | 42 | class Application { |
@@ -41,149 +41,149 @@ |
||
| 41 | 41 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
| 42 | 42 | |
| 43 | 43 | class Application { |
| 44 | - /** @var IConfig */ |
|
| 45 | - private $config; |
|
| 46 | - /** @var EventDispatcherInterface */ |
|
| 47 | - private $dispatcher; |
|
| 48 | - /** @var IRequest */ |
|
| 49 | - private $request; |
|
| 50 | - /** @var ILogger */ |
|
| 51 | - private $logger; |
|
| 44 | + /** @var IConfig */ |
|
| 45 | + private $config; |
|
| 46 | + /** @var EventDispatcherInterface */ |
|
| 47 | + private $dispatcher; |
|
| 48 | + /** @var IRequest */ |
|
| 49 | + private $request; |
|
| 50 | + /** @var ILogger */ |
|
| 51 | + private $logger; |
|
| 52 | 52 | |
| 53 | - /** |
|
| 54 | - * @param IConfig $config |
|
| 55 | - * @param EventDispatcherInterface $dispatcher |
|
| 56 | - * @param IRequest $request |
|
| 57 | - * @param ILogger $logger |
|
| 58 | - */ |
|
| 59 | - public function __construct(IConfig $config, EventDispatcherInterface $dispatcher, IRequest $request, ILogger $logger) { |
|
| 60 | - $defaults = \OC::$server->getThemingDefaults(); |
|
| 61 | - $this->config = $config; |
|
| 62 | - $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString()); |
|
| 63 | - $this->dispatcher = $dispatcher; |
|
| 64 | - $this->request = $request; |
|
| 65 | - $this->logger = $logger; |
|
| 66 | - } |
|
| 53 | + /** |
|
| 54 | + * @param IConfig $config |
|
| 55 | + * @param EventDispatcherInterface $dispatcher |
|
| 56 | + * @param IRequest $request |
|
| 57 | + * @param ILogger $logger |
|
| 58 | + */ |
|
| 59 | + public function __construct(IConfig $config, EventDispatcherInterface $dispatcher, IRequest $request, ILogger $logger) { |
|
| 60 | + $defaults = \OC::$server->getThemingDefaults(); |
|
| 61 | + $this->config = $config; |
|
| 62 | + $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString()); |
|
| 63 | + $this->dispatcher = $dispatcher; |
|
| 64 | + $this->request = $request; |
|
| 65 | + $this->logger = $logger; |
|
| 66 | + } |
|
| 67 | 67 | |
| 68 | - /** |
|
| 69 | - * @param InputInterface $input |
|
| 70 | - * @param OutputInterface $output |
|
| 71 | - * @throws \Exception |
|
| 72 | - */ |
|
| 73 | - public function loadCommands(InputInterface $input, OutputInterface $output) { |
|
| 74 | - // $application is required to be defined in the register_command scripts |
|
| 75 | - $application = $this->application; |
|
| 76 | - $inputDefinition = $application->getDefinition(); |
|
| 77 | - $inputDefinition->addOption( |
|
| 78 | - new InputOption( |
|
| 79 | - 'no-warnings', |
|
| 80 | - null, |
|
| 81 | - InputOption::VALUE_NONE, |
|
| 82 | - 'Skip global warnings, show command output only', |
|
| 83 | - null |
|
| 84 | - ) |
|
| 85 | - ); |
|
| 86 | - try { |
|
| 87 | - $input->bind($inputDefinition); |
|
| 88 | - } catch (\RuntimeException $e) { |
|
| 89 | - //expected if there are extra options |
|
| 90 | - } |
|
| 91 | - if ($input->getOption('no-warnings')) { |
|
| 92 | - $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); |
|
| 93 | - } |
|
| 94 | - try { |
|
| 95 | - require_once __DIR__ . '/../../../core/register_command.php'; |
|
| 96 | - if ($this->config->getSystemValue('installed', false)) { |
|
| 97 | - if (\OCP\Util::needUpgrade()) { |
|
| 98 | - throw new NeedsUpdateException(); |
|
| 99 | - } elseif ($this->config->getSystemValue('maintenance', false)) { |
|
| 100 | - if ($input->getArgument('command') !== '_completion') { |
|
| 101 | - $errOutput = $output->getErrorOutput(); |
|
| 102 | - $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no app have been loaded</comment>' . PHP_EOL); |
|
| 103 | - } |
|
| 104 | - } else { |
|
| 105 | - OC_App::loadApps(); |
|
| 106 | - foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) { |
|
| 107 | - $appPath = \OC_App::getAppPath($app); |
|
| 108 | - if ($appPath === false) { |
|
| 109 | - continue; |
|
| 110 | - } |
|
| 111 | - // load commands using info.xml |
|
| 112 | - $info = \OC_App::getAppInfo($app); |
|
| 113 | - if (isset($info['commands'])) { |
|
| 114 | - $this->loadCommandsFromInfoXml($info['commands']); |
|
| 115 | - } |
|
| 116 | - // load from register_command.php |
|
| 117 | - \OC_App::registerAutoloading($app, $appPath); |
|
| 118 | - $file = $appPath . '/appinfo/register_command.php'; |
|
| 119 | - if (file_exists($file)) { |
|
| 120 | - try { |
|
| 121 | - require $file; |
|
| 122 | - } catch (\Exception $e) { |
|
| 123 | - $this->logger->logException($e); |
|
| 124 | - } |
|
| 125 | - } |
|
| 126 | - } |
|
| 127 | - } |
|
| 128 | - } else if ($input->getArgument('command') !== '_completion') { |
|
| 129 | - $output->writeln("Nextcloud is not installed - only a limited number of commands are available"); |
|
| 130 | - } |
|
| 131 | - } catch(NeedsUpdateException $e) { |
|
| 132 | - if ($input->getArgument('command') !== '_completion') { |
|
| 133 | - $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available"); |
|
| 134 | - $output->writeln("You may use your browser or the occ upgrade command to do the upgrade"); |
|
| 135 | - } |
|
| 136 | - } |
|
| 68 | + /** |
|
| 69 | + * @param InputInterface $input |
|
| 70 | + * @param OutputInterface $output |
|
| 71 | + * @throws \Exception |
|
| 72 | + */ |
|
| 73 | + public function loadCommands(InputInterface $input, OutputInterface $output) { |
|
| 74 | + // $application is required to be defined in the register_command scripts |
|
| 75 | + $application = $this->application; |
|
| 76 | + $inputDefinition = $application->getDefinition(); |
|
| 77 | + $inputDefinition->addOption( |
|
| 78 | + new InputOption( |
|
| 79 | + 'no-warnings', |
|
| 80 | + null, |
|
| 81 | + InputOption::VALUE_NONE, |
|
| 82 | + 'Skip global warnings, show command output only', |
|
| 83 | + null |
|
| 84 | + ) |
|
| 85 | + ); |
|
| 86 | + try { |
|
| 87 | + $input->bind($inputDefinition); |
|
| 88 | + } catch (\RuntimeException $e) { |
|
| 89 | + //expected if there are extra options |
|
| 90 | + } |
|
| 91 | + if ($input->getOption('no-warnings')) { |
|
| 92 | + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); |
|
| 93 | + } |
|
| 94 | + try { |
|
| 95 | + require_once __DIR__ . '/../../../core/register_command.php'; |
|
| 96 | + if ($this->config->getSystemValue('installed', false)) { |
|
| 97 | + if (\OCP\Util::needUpgrade()) { |
|
| 98 | + throw new NeedsUpdateException(); |
|
| 99 | + } elseif ($this->config->getSystemValue('maintenance', false)) { |
|
| 100 | + if ($input->getArgument('command') !== '_completion') { |
|
| 101 | + $errOutput = $output->getErrorOutput(); |
|
| 102 | + $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no app have been loaded</comment>' . PHP_EOL); |
|
| 103 | + } |
|
| 104 | + } else { |
|
| 105 | + OC_App::loadApps(); |
|
| 106 | + foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) { |
|
| 107 | + $appPath = \OC_App::getAppPath($app); |
|
| 108 | + if ($appPath === false) { |
|
| 109 | + continue; |
|
| 110 | + } |
|
| 111 | + // load commands using info.xml |
|
| 112 | + $info = \OC_App::getAppInfo($app); |
|
| 113 | + if (isset($info['commands'])) { |
|
| 114 | + $this->loadCommandsFromInfoXml($info['commands']); |
|
| 115 | + } |
|
| 116 | + // load from register_command.php |
|
| 117 | + \OC_App::registerAutoloading($app, $appPath); |
|
| 118 | + $file = $appPath . '/appinfo/register_command.php'; |
|
| 119 | + if (file_exists($file)) { |
|
| 120 | + try { |
|
| 121 | + require $file; |
|
| 122 | + } catch (\Exception $e) { |
|
| 123 | + $this->logger->logException($e); |
|
| 124 | + } |
|
| 125 | + } |
|
| 126 | + } |
|
| 127 | + } |
|
| 128 | + } else if ($input->getArgument('command') !== '_completion') { |
|
| 129 | + $output->writeln("Nextcloud is not installed - only a limited number of commands are available"); |
|
| 130 | + } |
|
| 131 | + } catch(NeedsUpdateException $e) { |
|
| 132 | + if ($input->getArgument('command') !== '_completion') { |
|
| 133 | + $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available"); |
|
| 134 | + $output->writeln("You may use your browser or the occ upgrade command to do the upgrade"); |
|
| 135 | + } |
|
| 136 | + } |
|
| 137 | 137 | |
| 138 | - if ($input->getFirstArgument() !== 'check') { |
|
| 139 | - $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig()); |
|
| 140 | - if (!empty($errors)) { |
|
| 141 | - foreach ($errors as $error) { |
|
| 142 | - $output->writeln((string)$error['error']); |
|
| 143 | - $output->writeln((string)$error['hint']); |
|
| 144 | - $output->writeln(''); |
|
| 145 | - } |
|
| 146 | - throw new \Exception("Environment not properly prepared."); |
|
| 147 | - } |
|
| 148 | - } |
|
| 149 | - } |
|
| 138 | + if ($input->getFirstArgument() !== 'check') { |
|
| 139 | + $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig()); |
|
| 140 | + if (!empty($errors)) { |
|
| 141 | + foreach ($errors as $error) { |
|
| 142 | + $output->writeln((string)$error['error']); |
|
| 143 | + $output->writeln((string)$error['hint']); |
|
| 144 | + $output->writeln(''); |
|
| 145 | + } |
|
| 146 | + throw new \Exception("Environment not properly prepared."); |
|
| 147 | + } |
|
| 148 | + } |
|
| 149 | + } |
|
| 150 | 150 | |
| 151 | - /** |
|
| 152 | - * Sets whether to automatically exit after a command execution or not. |
|
| 153 | - * |
|
| 154 | - * @param bool $boolean Whether to automatically exit after a command execution or not |
|
| 155 | - */ |
|
| 156 | - public function setAutoExit($boolean) { |
|
| 157 | - $this->application->setAutoExit($boolean); |
|
| 158 | - } |
|
| 151 | + /** |
|
| 152 | + * Sets whether to automatically exit after a command execution or not. |
|
| 153 | + * |
|
| 154 | + * @param bool $boolean Whether to automatically exit after a command execution or not |
|
| 155 | + */ |
|
| 156 | + public function setAutoExit($boolean) { |
|
| 157 | + $this->application->setAutoExit($boolean); |
|
| 158 | + } |
|
| 159 | 159 | |
| 160 | - /** |
|
| 161 | - * @param InputInterface $input |
|
| 162 | - * @param OutputInterface $output |
|
| 163 | - * @return int |
|
| 164 | - * @throws \Exception |
|
| 165 | - */ |
|
| 166 | - public function run(InputInterface $input = null, OutputInterface $output = null) { |
|
| 167 | - $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent( |
|
| 168 | - ConsoleEvent::EVENT_RUN, |
|
| 169 | - $this->request->server['argv'] |
|
| 170 | - )); |
|
| 171 | - return $this->application->run($input, $output); |
|
| 172 | - } |
|
| 160 | + /** |
|
| 161 | + * @param InputInterface $input |
|
| 162 | + * @param OutputInterface $output |
|
| 163 | + * @return int |
|
| 164 | + * @throws \Exception |
|
| 165 | + */ |
|
| 166 | + public function run(InputInterface $input = null, OutputInterface $output = null) { |
|
| 167 | + $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent( |
|
| 168 | + ConsoleEvent::EVENT_RUN, |
|
| 169 | + $this->request->server['argv'] |
|
| 170 | + )); |
|
| 171 | + return $this->application->run($input, $output); |
|
| 172 | + } |
|
| 173 | 173 | |
| 174 | - private function loadCommandsFromInfoXml($commands) { |
|
| 175 | - foreach ($commands as $command) { |
|
| 176 | - try { |
|
| 177 | - $c = \OC::$server->query($command); |
|
| 178 | - } catch (QueryException $e) { |
|
| 179 | - if (class_exists($command)) { |
|
| 180 | - $c = new $command(); |
|
| 181 | - } else { |
|
| 182 | - throw new \Exception("Console command '$command' is unknown and could not be loaded"); |
|
| 183 | - } |
|
| 184 | - } |
|
| 174 | + private function loadCommandsFromInfoXml($commands) { |
|
| 175 | + foreach ($commands as $command) { |
|
| 176 | + try { |
|
| 177 | + $c = \OC::$server->query($command); |
|
| 178 | + } catch (QueryException $e) { |
|
| 179 | + if (class_exists($command)) { |
|
| 180 | + $c = new $command(); |
|
| 181 | + } else { |
|
| 182 | + throw new \Exception("Console command '$command' is unknown and could not be loaded"); |
|
| 183 | + } |
|
| 184 | + } |
|
| 185 | 185 | |
| 186 | - $this->application->add($c); |
|
| 187 | - } |
|
| 188 | - } |
|
| 186 | + $this->application->add($c); |
|
| 187 | + } |
|
| 188 | + } |
|
| 189 | 189 | } |
@@ -92,14 +92,14 @@ discard block |
||
| 92 | 92 | $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); |
| 93 | 93 | } |
| 94 | 94 | try { |
| 95 | - require_once __DIR__ . '/../../../core/register_command.php'; |
|
| 95 | + require_once __DIR__.'/../../../core/register_command.php'; |
|
| 96 | 96 | if ($this->config->getSystemValue('installed', false)) { |
| 97 | 97 | if (\OCP\Util::needUpgrade()) { |
| 98 | 98 | throw new NeedsUpdateException(); |
| 99 | 99 | } elseif ($this->config->getSystemValue('maintenance', false)) { |
| 100 | 100 | if ($input->getArgument('command') !== '_completion') { |
| 101 | 101 | $errOutput = $output->getErrorOutput(); |
| 102 | - $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no app have been loaded</comment>' . PHP_EOL); |
|
| 102 | + $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no app have been loaded</comment>'.PHP_EOL); |
|
| 103 | 103 | } |
| 104 | 104 | } else { |
| 105 | 105 | OC_App::loadApps(); |
@@ -115,7 +115,7 @@ discard block |
||
| 115 | 115 | } |
| 116 | 116 | // load from register_command.php |
| 117 | 117 | \OC_App::registerAutoloading($app, $appPath); |
| 118 | - $file = $appPath . '/appinfo/register_command.php'; |
|
| 118 | + $file = $appPath.'/appinfo/register_command.php'; |
|
| 119 | 119 | if (file_exists($file)) { |
| 120 | 120 | try { |
| 121 | 121 | require $file; |
@@ -128,7 +128,7 @@ discard block |
||
| 128 | 128 | } else if ($input->getArgument('command') !== '_completion') { |
| 129 | 129 | $output->writeln("Nextcloud is not installed - only a limited number of commands are available"); |
| 130 | 130 | } |
| 131 | - } catch(NeedsUpdateException $e) { |
|
| 131 | + } catch (NeedsUpdateException $e) { |
|
| 132 | 132 | if ($input->getArgument('command') !== '_completion') { |
| 133 | 133 | $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available"); |
| 134 | 134 | $output->writeln("You may use your browser or the occ upgrade command to do the upgrade"); |
@@ -139,8 +139,8 @@ discard block |
||
| 139 | 139 | $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig()); |
| 140 | 140 | if (!empty($errors)) { |
| 141 | 141 | foreach ($errors as $error) { |
| 142 | - $output->writeln((string)$error['error']); |
|
| 143 | - $output->writeln((string)$error['hint']); |
|
| 142 | + $output->writeln((string) $error['error']); |
|
| 143 | + $output->writeln((string) $error['hint']); |
|
| 144 | 144 | $output->writeln(''); |
| 145 | 145 | } |
| 146 | 146 | throw new \Exception("Environment not properly prepared."); |
@@ -39,98 +39,98 @@ |
||
| 39 | 39 | |
| 40 | 40 | class ResetPassword extends Command { |
| 41 | 41 | |
| 42 | - /** @var IUserManager */ |
|
| 43 | - protected $userManager; |
|
| 44 | - |
|
| 45 | - public function __construct(IUserManager $userManager) { |
|
| 46 | - $this->userManager = $userManager; |
|
| 47 | - parent::__construct(); |
|
| 48 | - } |
|
| 49 | - |
|
| 50 | - protected function configure() { |
|
| 51 | - $this |
|
| 52 | - ->setName('user:resetpassword') |
|
| 53 | - ->setDescription('Resets the password of the named user') |
|
| 54 | - ->addArgument( |
|
| 55 | - 'user', |
|
| 56 | - InputArgument::REQUIRED, |
|
| 57 | - 'Username to reset password' |
|
| 58 | - ) |
|
| 59 | - ->addOption( |
|
| 60 | - 'password-from-env', |
|
| 61 | - null, |
|
| 62 | - InputOption::VALUE_NONE, |
|
| 63 | - 'read password from environment variable OC_PASS' |
|
| 64 | - ) |
|
| 65 | - ; |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - protected function execute(InputInterface $input, OutputInterface $output) { |
|
| 69 | - $username = $input->getArgument('user'); |
|
| 70 | - |
|
| 71 | - /** @var $user \OCP\IUser */ |
|
| 72 | - $user = $this->userManager->get($username); |
|
| 73 | - if (is_null($user)) { |
|
| 74 | - $output->writeln('<error>User does not exist</error>'); |
|
| 75 | - return 1; |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - if ($input->getOption('password-from-env')) { |
|
| 79 | - $password = getenv('OC_PASS'); |
|
| 80 | - if (!$password) { |
|
| 81 | - $output->writeln('<error>--password-from-env given, but OC_PASS is empty!</error>'); |
|
| 82 | - return 1; |
|
| 83 | - } |
|
| 84 | - } elseif ($input->isInteractive()) { |
|
| 85 | - /** @var QuestionHelper $helper */ |
|
| 86 | - $helper = $this->getHelper('question'); |
|
| 87 | - |
|
| 88 | - if (\OCP\App::isEnabled('encryption')) { |
|
| 89 | - $output->writeln( |
|
| 90 | - '<error>Warning: Resetting the password when using encryption will result in data loss!</error>' |
|
| 91 | - ); |
|
| 92 | - |
|
| 93 | - $question = new ConfirmationQuestion('Do you want to continue?'); |
|
| 94 | - if (!$helper->ask($input, $output, $question)) { |
|
| 95 | - return 1; |
|
| 96 | - } |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - $question = new Question('Enter a new password: '); |
|
| 100 | - $question->setHidden(true); |
|
| 101 | - $password = $helper->ask($input, $output, $question); |
|
| 102 | - |
|
| 103 | - if ($password === null) { |
|
| 104 | - $output->writeln("<error>Password cannot be empty!</error>"); |
|
| 105 | - return 1; |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - $question = new Question('Confirm the new password: '); |
|
| 109 | - $question->setHidden(true); |
|
| 110 | - $confirm = $helper->ask($input, $output, $question); |
|
| 111 | - |
|
| 112 | - if ($password !== $confirm) { |
|
| 113 | - $output->writeln("<error>Passwords did not match!</error>"); |
|
| 114 | - return 1; |
|
| 115 | - } |
|
| 116 | - } else { |
|
| 117 | - $output->writeln("<error>Interactive input or --password-from-env is needed for entering a new password!</error>"); |
|
| 118 | - return 1; |
|
| 119 | - } |
|
| 120 | - |
|
| 121 | - |
|
| 122 | - try { |
|
| 123 | - $success = $user->setPassword($password); |
|
| 124 | - } catch (\Exception $e) { |
|
| 125 | - $output->writeln('<error>' . $e->getMessage() . '</error>'); |
|
| 126 | - return 1; |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - if ($success) { |
|
| 130 | - $output->writeln("<info>Successfully reset password for " . $username . "</info>"); |
|
| 131 | - } else { |
|
| 132 | - $output->writeln("<error>Error while resetting password!</error>"); |
|
| 133 | - return 1; |
|
| 134 | - } |
|
| 135 | - } |
|
| 42 | + /** @var IUserManager */ |
|
| 43 | + protected $userManager; |
|
| 44 | + |
|
| 45 | + public function __construct(IUserManager $userManager) { |
|
| 46 | + $this->userManager = $userManager; |
|
| 47 | + parent::__construct(); |
|
| 48 | + } |
|
| 49 | + |
|
| 50 | + protected function configure() { |
|
| 51 | + $this |
|
| 52 | + ->setName('user:resetpassword') |
|
| 53 | + ->setDescription('Resets the password of the named user') |
|
| 54 | + ->addArgument( |
|
| 55 | + 'user', |
|
| 56 | + InputArgument::REQUIRED, |
|
| 57 | + 'Username to reset password' |
|
| 58 | + ) |
|
| 59 | + ->addOption( |
|
| 60 | + 'password-from-env', |
|
| 61 | + null, |
|
| 62 | + InputOption::VALUE_NONE, |
|
| 63 | + 'read password from environment variable OC_PASS' |
|
| 64 | + ) |
|
| 65 | + ; |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + protected function execute(InputInterface $input, OutputInterface $output) { |
|
| 69 | + $username = $input->getArgument('user'); |
|
| 70 | + |
|
| 71 | + /** @var $user \OCP\IUser */ |
|
| 72 | + $user = $this->userManager->get($username); |
|
| 73 | + if (is_null($user)) { |
|
| 74 | + $output->writeln('<error>User does not exist</error>'); |
|
| 75 | + return 1; |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + if ($input->getOption('password-from-env')) { |
|
| 79 | + $password = getenv('OC_PASS'); |
|
| 80 | + if (!$password) { |
|
| 81 | + $output->writeln('<error>--password-from-env given, but OC_PASS is empty!</error>'); |
|
| 82 | + return 1; |
|
| 83 | + } |
|
| 84 | + } elseif ($input->isInteractive()) { |
|
| 85 | + /** @var QuestionHelper $helper */ |
|
| 86 | + $helper = $this->getHelper('question'); |
|
| 87 | + |
|
| 88 | + if (\OCP\App::isEnabled('encryption')) { |
|
| 89 | + $output->writeln( |
|
| 90 | + '<error>Warning: Resetting the password when using encryption will result in data loss!</error>' |
|
| 91 | + ); |
|
| 92 | + |
|
| 93 | + $question = new ConfirmationQuestion('Do you want to continue?'); |
|
| 94 | + if (!$helper->ask($input, $output, $question)) { |
|
| 95 | + return 1; |
|
| 96 | + } |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + $question = new Question('Enter a new password: '); |
|
| 100 | + $question->setHidden(true); |
|
| 101 | + $password = $helper->ask($input, $output, $question); |
|
| 102 | + |
|
| 103 | + if ($password === null) { |
|
| 104 | + $output->writeln("<error>Password cannot be empty!</error>"); |
|
| 105 | + return 1; |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + $question = new Question('Confirm the new password: '); |
|
| 109 | + $question->setHidden(true); |
|
| 110 | + $confirm = $helper->ask($input, $output, $question); |
|
| 111 | + |
|
| 112 | + if ($password !== $confirm) { |
|
| 113 | + $output->writeln("<error>Passwords did not match!</error>"); |
|
| 114 | + return 1; |
|
| 115 | + } |
|
| 116 | + } else { |
|
| 117 | + $output->writeln("<error>Interactive input or --password-from-env is needed for entering a new password!</error>"); |
|
| 118 | + return 1; |
|
| 119 | + } |
|
| 120 | + |
|
| 121 | + |
|
| 122 | + try { |
|
| 123 | + $success = $user->setPassword($password); |
|
| 124 | + } catch (\Exception $e) { |
|
| 125 | + $output->writeln('<error>' . $e->getMessage() . '</error>'); |
|
| 126 | + return 1; |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + if ($success) { |
|
| 130 | + $output->writeln("<info>Successfully reset password for " . $username . "</info>"); |
|
| 131 | + } else { |
|
| 132 | + $output->writeln("<error>Error while resetting password!</error>"); |
|
| 133 | + return 1; |
|
| 134 | + } |
|
| 135 | + } |
|
| 136 | 136 | } |