// Init owncloud
-
+
OCP\User::checkAdminUser();
$breadcrumb[] = array( "dir" => $pathtohere, "name" => $i );
}
}
-
+
$breadcrumbNav = new OCP\Template( "files", "part.breadcrumb", "" );
$breadcrumbNav->assign( "breadcrumb", $breadcrumb );
-
+
$data['breadcrumb'] = $breadcrumbNav->fetchPage();
}
case STREAM_NOTIFY_FILE_SIZE_IS:
$filesize = $bytes_max;
break;
-
+
case STREAM_NOTIFY_PROGRESS:
if ($bytes_transferred > 0) {
if (!isset($filesize)) {
// Load the files
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
-$mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : '';
+$mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : '';
// make filelist
$files = array();
if($force or !OC_FileCache::inCache('')) {
if(!$checkOnly) {
OCP\DB::beginTransaction();
-
+
if(OC_Cache::isFast()) {
- //make sure the old fileid's don't mess things up
- OC_Cache::clear('fileid/');
+ OC_Cache::clear('fileid/'); //make sure the old fileid's don't mess things up
}
-
- OC_FileCache::scan($dir, $eventSource);
+
+ OC_FileCache::scan($dir,$eventSource);
OC_FileCache::clean();
OCP\DB::commit();
$eventSource->send('success', true);
// see lib/base.php for an example
//session_start();
$_SESSION['timezone'] = $_GET['time'];
-
\ No newline at end of file
*/
// Init owncloud
-
+
// Check if we are a user
OCP\User::checkLoggedIn();
stop: function(e, data) {
if(data.dataType != 'iframe ') {
$('#upload input.stop').hide();
- }
+ }
$('#uploadprogressbar').progressbar('value',100);
$('#uploadprogressbar').fadeOut();
}
scanFiles();
}
}, "json");
-
+
var lastWidth = 0;
var breadcrumbs = [];
var breadcrumbsWidth = $('#navigation').get(0).offsetWidth;
$(window).resize(function() {
resizeBreadcrumbs(false);
});
-
+
resizeBreadcrumbs(true);
});
// Init owncloud
-
+
// Check if we are a user
OCP\User::checkLoggedIn();
<input type="submit" name="submitFilesAdminSettings" id="submitFilesAdminSettings" value="Save"/>
</fieldset>
</form>
-
-
-
onuncheck:blackListChange,
createText:'...',
});
-
+
function blackListChange(){
var blackList=$('#encryption_blacklist').val().join(',');
OC.AppConfig.setValue('files_encryption','type_blacklist',blackList);
fclose($handleread);
}
}
-
+
/**
* encrypt data in 8192b sized blocks
*/
}
return $result;
}
-
+
/**
* decrypt data in 8192b sized blocks
*/
}
return is_resource($this->source);
}
-
+
public function stream_seek($offset, $whence=SEEK_SET){
$this->flush();
fseek($this->source,$offset,$whence);
}
-
+
public function stream_tell(){
return ftell($this->source);
}
-
+
public function stream_read($count){
//$count will always be 8192 https://bugs.php.net/bug.php?id=21641
//This makes this function a lot simpler but will breake everything the moment it's fixed
}
return $result;
}
-
+
public function stream_write($data){
$length=strlen($data);
$currentPos=ftell($this->source);
public function stream_stat(){
return fstat($this->source);
}
-
+
public function stream_lock($mode){
flock($this->source,$mode);
}
-
+
public function stream_flush(){
return fflush($this->source);
}
class OC_FileProxy_Encryption extends OC_FileProxy{
private static $blackList=null; //mimetypes blacklisted from encryption
private static $enableEncryption=null;
-
+
/**
* check if a file should be encrypted during write
* @param string $path
$metadata=OC_FileCache_Cached::get($path,'');
return isset($metadata['encrypted']) and (bool)$metadata['encrypted'];
}
-
+
public function preFile_put_contents($path,&$data){
if(self::shouldEncrypt($path)){
if (!is_resource($data)) {//stream put contents should have been converter to fopen
}
}
}
-
+
public function postFile_get_contents($path,$data){
if(self::isEncrypted($path)){
$cached=OC_FileCache_Cached::get($path,'');
}
return $data;
}
-
+
public function postFopen($path,&$result){
if(!$result){
return $result;
$decrypted=OC_Crypt::decrypt($encrypted,$key);
$decrypted=rtrim($decrypted, "\0");
$this->assertEqual($decrypted,$chunk);
-
+
$encrypted=OC_Crypt::blockEncrypt($source,$key);
$decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
$this->assertNotEqual($encrypted,$source);
function testBinary(){
$key=uniqid();
-
+
$file=__DIR__.'/binary';
$source=file_get_contents($file); //binary file
$encrypted=OC_Crypt::encrypt($source,$key);
class Test_CryptProxy extends UnitTestCase {
private $oldConfig;
private $oldKey;
-
+
public function setUp(){
$user=OC_User::getUser();
$this->oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true');
OCP\Config::setAppValue('files_encryption','enable_encryption','true');
$this->oldKey=isset($_SESSION['enckey'])?$_SESSION['enckey']:null;
-
-
+
+
//set testing key
$_SESSION['enckey']=md5(time());
-
+
//clear all proxies and hooks so we can do clean testing
OC_FileProxy::clearProxies();
OC_Hook::clear('OC_Filesystem');
$original=file_get_contents($file);
OC_Filesystem::file_put_contents('/file',$original);
-
+
OC_FileProxy::$enabled=false;
$stored=OC_Filesystem::file_get_contents('/file');
OC_FileProxy::$enabled=true;
-
+
$fromFile=OC_Filesystem::file_get_contents('/file');
$this->assertNotEqual($original,$stored);
$this->assertEqual(strlen($original),strlen($fromFile));
class Test_CryptStream extends UnitTestCase {
private $tmpFiles=array();
-
+
function testStream(){
$stream=$this->getStream('test1','w',strlen('foobar'));
fwrite($stream,'foobar');
$data = fread($fh, filesize($to));
fclose($fh);
if (!strpos($data, 'BEGIN CERTIFICATE')) {
- $pem = chunk_split(base64_encode($data), 64, "\n");\r
+ $pem = chunk_split(base64_encode($data), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
$fh = fopen($to, 'w');
fwrite($fh, $pem);
$(document).ready(function() {
$('.chzn-select').chosen();
-
+
$('#selectBackend').live('change', function() {
var tr = $(this).parent().parent();
$('#externalStorage tbody').append($(tr).clone());
}
}
return defaultMountPoint+append;
- }
+ }
$('#externalStorage td').live('change', function() {
OC.MountConfig.saveStorage($(this).parent());
private $objects = array();
private static $tempFiles = array();
-
+
// TODO options: storage class, encryption server side, encrypt before upload?
public function __construct($params) {
}
public function free_space($path) {
- // Infinite?
+ // Infinite?
return false;
}
private $root;
private static $tempFiles=array();
-
+
public function __construct($params){
$this->host=$params['host'];
$this->user=$params['user'];
}
}
}
- return false;
+ return false;
}
private function getFeed($feedUri, $httpMethod, $postData = null) {
return 'html';
}
}
-
+
public function mkdir($path) {
$collection = dirname($path);
} else if ($entry = $this->getResource($path)) {
// NOTE: Native resources don't have a file size
$stat['size'] = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue;
-// if (isset($atime = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue))
+// if (isset($atime = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue))
// $stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue);
$stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue);
$stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue);
}
return false;
}
-
+
public function file_exists($path) {
if ($path == '' || $path == '/') {
return true;
}
return false;
}
-
+
public function unlink($path) {
// Get resource self link to trash resource
if ($entry = $this->getResource($path)) {
// TODO Wait for resource entry
}
}
-
+
public function getMimeType($path, $entry = null) {
// Entry can be passed, because extension is required for opendir and the entry can't be cached without the extension
if ($entry == null) {
}
return false;
}
-
+
public function free_space($path) {
if ($dom = $this->getFeed('https://docs.google.com/feeds/metadata/default', 'GET')) {
// NOTE: Native Google Docs resources don't count towards quota
}
return false;
}
-
+
public function touch($path, $mtime = null) {
-
+
}
}
\ No newline at end of file
}
$this->auth = new CF_Authentication($this->user, $this->token, null, $this->host);
$this->auth->authenticate();
-
+
$this->conn = new CF_Connection($this->auth);
if(!$this->containerExists($this->root)){
$parentContainer=$this->getContainer(dirname($path));
$this->removeSubContainer($parentContainer,basename($path));
}
-
+
$this->conn->delete_container($this->getContainerName($path));
unset($this->containers[$path]);
return true;
case 'rb':
$fp = fopen('php://temp', 'r+');
$obj->stream($fp);
-
+
rewind($fp);
return $fp;
case 'w':
if(is_null($mtime)){
$mtime=time();
}
-
+
//emulate setting mtime with metadata
$obj->metadata['Mtime']=$mtime;
$obj->sync_metadata();
private $client;
private static $tempFiles=array();
-
+
public function __construct($params){
$host = $params['host'];
//remove leading http[s], will be generated in createBaseUri()
if(substr($this->root,-1,1)!='/'){
$this->root.='/';
}
-
+
$settings = array(
'baseUri' => $this->createBaseUri(),
'userName' => $this->user,
);
$this->client = new OC_Connector_Sabre_Client($settings);
-
+
if($caview = \OCP\Files::getStorage('files_external')) {
$certPath=\OCP\Config::getSystemValue('datadirectory').$caview->getAbsolutePath("").'rootcerts.crt';
if (file_exists($certPath)) {
}
}
}
-
</tbody>
</table>
<br />
-
+
<?php if (!$_['isAdminPage']): ?>
<table id="sslCertificate" data-admin='<?php echo json_encode($_['isAdminPage']); ?>'>
<thead>
</thead>
<tbody width="100%">
<?php foreach ($_['certs'] as $rootCert): ?>
- <tr id="<?php echo $rootCert ?>">
+ <tr id="<?php echo $rootCert ?>">
<td class="rootCert"><?php echo $rootCert ?></td>
<td <?php echo ($rootCert != '') ? 'class="remove"' : 'style="visibility:hidden;"'; ?>><img alt="<?php echo $l->t('Delete'); ?>" title="<?php echo $l->t('Delete'); ?>" class="svg action" src="<?php echo image_path('core', 'actions/delete.svg'); ?>" /></td>
</tr>
<?php endforeach; ?>
</tbody>
- </table>
+ </table>
<input type="file" id="rootcert_import" name="rootcert_import" style="width:230px;">
- <input type="submit" name="cert_import" value="<?php echo $l->t('Import Root Certificate'); ?>" />
+ <input type="submit" name="cert_import" value="<?php echo $l->t('Import Root Certificate'); ?>" />
<?php endif; ?>
-
+
<?php if ($_['isAdminPage']): ?>
<br />
<input type="checkbox" name="allowUserMounting" id="allowUserMounting" value="1" <?php if ($_['allowUserMounting'] == 'yes') echo ' checked="checked"'; ?> />
* later.
* See the COPYING-README file.
*/
-
+
$config=include('apps/files_external/tests/config.php');
if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']){
abstract class Test_Filestorage_FTP extends Test_FileStorage{}
}
}
}
-
return;
}else{
class Test_Filestorage_Google extends Test_FileStorage {
-
+
private $config;
public function setUp(){
}
}
}
-
$this->instance=new OC_Filestorage_SWIFT($this->config['swift']);
}
-
+
public function tearDown(){
$this->instance->rmdir('');
}
-
+
}
}
-
$datadir = \OCP\Config::getSystemValue('datadirectory');
$currentVersion=OC_Appconfig::getValue('files_sharing', 'installed_version');
if (version_compare($currentVersion, '0.2.2', '<')) {
- if ($handle = opendir($datadir)) {\r
- while (false !== ($entry = readdir($handle))) {\r
- $sharedFolder = $datadir.'/'.$entry.'/files/Shared';\r
- if ($entry != "." && $entry != ".." && is_dir($sharedFolder)) {\r
- touch($sharedFolder);\r
- }\r
- }\r
- closedir($handle);\r
+ if ($handle = opendir($datadir)) {
+ while (false !== ($entry = readdir($handle))) {
+ $sharedFolder = $datadir.'/'.$entry.'/files/Shared';
+ if ($entry != "." && $entry != ".." && is_dir($sharedFolder)) {
+ touch($sharedFolder);
+ }
+ }
+ closedir($handle);
}
}
\ No newline at end of file
const FORMAT_OPENDIR = 3;
private $path;
-
+
public function isValidSource($itemSource, $uidOwner) {
$path = OC_FileCache::getPath($itemSource, $uidOwner);
if (OC_Filesystem::file_exists($path)) {
$files[] = basename($item['file_target']);
}
return $files;
- }
+ }
return array();
}
* Convert target path to source path and pass the function call to the correct storage provider
*/
class OC_Filestorage_Shared extends OC_Filestorage_Common {
-
+
private $sharedFolder;
private $files = array();
-
+
public function __construct($arguments) {
$this->sharedFolder = $arguments['sharedFolder'];
OC_Util::setupFS4all();
$internalPath = substr($path, strlen($mountPoint));
return $internalPath;
}
-
+
public function mkdir($path) {
if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) {
- return false;
+ return false;
} else if ($source = $this->getSourcePath($path)) {
$storage = OC_Filesystem::getStorage($source);
return $storage->mkdir($this->getInternalPath($source));
}
return false;
}
-
+
public function rmdir($path) {
if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
$storage = OC_Filesystem::getStorage($source);
}
return false;
}
-
+
public function opendir($path) {
if ($path == '' || $path == '/') {
$files = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_Folder::FORMAT_OPENDIR);
}
return false;
}
-
+
public function filectime($path) {
if ($path == '' || $path == '/') {
- $ctime = 0;
+ $ctime = 0;
if ($dh = $this->opendir($path)) {
while (($filename = readdir($dh)) !== false) {
$tempctime = $this->filectime($filename);
}
}
}
-
+
public function filemtime($path) {
if ($path == '' || $path == '/') {
- $mtime = 0;
+ $mtime = 0;
if ($dh = $this->opendir($path)) {
while (($filename = readdir($dh)) !== false) {
$tempmtime = $this->filemtime($filename);
}
}
}
-
+
public function file_get_contents($path) {
$source = $this->getSourcePath($path);
if ($source) {
return $storage->file_get_contents($this->getInternalPath($source));
}
}
-
+
public function file_put_contents($path, $data) {
if ($source = $this->getSourcePath($path)) {
// Check if permission is granted
}
return false;
}
-
+
public function unlink($path) {
// Delete the file if DELETE permission is granted
if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) {
}
return false;
}
-
+
public function rename($path1, $path2) {
// Renaming/moving is only allowed within shared folders
$pos1 = strpos($path1, '/', 1);
}
return false;
}
-
+
public function copy($path1, $path2) {
// Copy the file if CREATE permission is granted
if ($this->isCreatable(dirname($path2))) {
$versions = new OCA_Versions\Storage();
if( $versions->expireAll() ){
-
+
OCP\JSON::success();
die();
-
+
} else {
-
+
OCP\JSON::error();
die();
-
+
}
\ No newline at end of file
$count=5; //show the newest revisions
$versions = OCA_Versions\Storage::getVersions( $source, $count);
$versionsFormatted = array();
-
+
foreach ( $versions AS $version ) {
$versionsFormatted[] = OCP\Util::formatDate( $version['version'] );
}
$versionsSorted = array_reverse( $versions );
-
+
if ( !empty( $versionsSorted ) ) {
OCP\JSON::encodedPrint($versionsSorted);
}
-
+
} else {
return;
-
+
}
$users = \OCP\User::getUsers();
$datadir = \OCP\Config::getSystemValue('datadirectory').'/';
foreach ($users as $user) {
- $oldPath = $datadir.$user.'/versions';\r
+ $oldPath = $datadir.$user.'/versions';
$newPath = $datadir.$user.'/files_versions';
if(is_dir($oldPath)) {
rename($oldPath, $newPath);
}
}
-
+
}
*
* @author Frank Karlitschek
* @copyright 2012 Frank Karlitschek frank@owncloud.org
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
+ * License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
+ *
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
+ *
*/
OCP\User::checkLoggedIn( );
// roll back to old version if button clicked
if( isset( $_GET['revert'] ) ) {
-
+
if( $versions->rollback( $path, $_GET['revert'] ) ) {
-
+
$tmpl->assign( 'outcome_stat', 'success' );
-
+
$tmpl->assign( 'outcome_msg', "File {$_GET['path']} was reverted to version ".OCP\Util::formatDate( doubleval($_GET['revert']) ) );
-
+
} else {
-
+
$tmpl->assign( 'outcome_stat', 'failure' );
-
+
$tmpl->assign( 'outcome_msg', "File {$_GET['path']} could not be reverted to version ".OCP\Util::formatDate( doubleval($_GET['revert']) ) );
-
+
}
-
+
}
// show the history only if there is something to show
if( OCA_Versions\Storage::isversioned( $path ) ) {
-
+
$count = 999; //show the newest revisions
$versions = OCA_Versions\Storage::getVersions( $path, $count);
$tmpl->assign( 'versions', array_reverse( $versions ) );
-
+
}else{
-
+
$tmpl->assign( 'message', 'No old versions available' );
-
+
}
}else{
-
+
$tmpl->assign( 'message', 'No path specified' );
-
+
}
$tmpl->printPage( );
$( document ).ready(function(){
//
- $( '#expireAllBtn' ).click(
-
+ $( '#expireAllBtn' ).click(
+
function( event ) {
-
+
// Prevent page from reloading
event.preventDefault();
-
+
// Show loading gif
$('.expireAllLoading').show();
-
+
$.getJSON(
OC.filePath('files_versions','ajax','expireAll.php'),
function(result){
$('.expireAllLoading').hide();
$('#expireAllBtn').html('Expiration successful');
} else {
-
+
// Cancel loading
$('#expireAllBtn').html('Expiration failed');
-
+
// Show Dialog
OC.dialogs.alert(
- 'Something went wrong, your files may not have been expired',
- 'An error has occurred',
- function(){
- $('#expireAllBtn').html(t('files_versions', 'Expire all versions')+'<img style="display: none;" class="loading" src="'+OC.filePath('core','img','loading.gif')+'" />');
- }
- );
+ 'Something went wrong, your files may not have been expired',
+ 'An error has occurred',
+ function(){
+ $('#expireAllBtn').html(t('files_versions', 'Expire all versions')+'<img style="display: none;" class="loading" src="'+OC.filePath('core','img','loading.gif')+'" />');
+ }
+ );
}
- }
+ }
);
}
);
FileActions.register('file','History', FileActions.PERMISSION_UPDATE, function(){return OC.imagePath('core','actions/history')},function(filename){
if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback
-
+
var file = $('#dir').val()+'/'+filename;
// Check if drop down is already visible for a different file
if (($('#dropdown').length > 0)) {
function createVersionsDropdown(filename, files) {
var historyUrl = OC.linkTo('files_versions', 'history.php') + '?path='+encodeURIComponent( $( '#dir' ).val() ).replace( /%2F/g, '/' )+'/'+encodeURIComponent( filename );
-
+
var html = '<div id="dropdown" class="drop" data-file="'+files+'">';
html += '<div id="private">';
html += '<select data-placeholder="Saved versions" id="found_versions" class="chzen-select" style="width:16em;">';
//html += '<input type="button" value="Revert file" onclick="revertFile()" />';
html += '<input type="button" value="All versions..." onclick="window.location=\''+historyUrl+'\'" name="makelink" id="makelink" />';
html += '<input id="link" style="display:none; width:90%;" />';
-
+
if (filename) {
$('tr').filterAttr('data-file',filename).addClass('mouseOver');
$(html).appendTo($('tr').filterAttr('data-file',filename).find('td.filename'));
} else {
$(html).appendTo($('thead .share'));
}
-
+
$.ajax({
type: 'GET',
url: OC.filePath('files_versions', 'ajax', 'getVersions.php'),
data: { source: files },
async: false,
success: function( versions ) {
-
+
//alert("helo "+OC.linkTo('files_versions', 'ajax/getVersions.php'));
-
+
if (versions) {
$.each( versions, function(index, row ) {
addVersion( row );
})
}
});
-
+
function revertFile(file, revision) {
-
+
$.ajax({
type: 'GET',
url: OC.linkTo('files_versions', 'ajax/rollbackVersion.php'),
});
}
}
- });
-
+ });
+
}
-
+
function addVersion(revision ) {
name=formatDate(revision.version*1000);
var version=$('<option/>');
version.attr('value',revision.version);
version.text(name);
-
+
// } else {
// var checked = ((permissions > 0) ? 'checked="checked"' : 'style="display:none;"');
// var style = ((permissions == 0) ? 'style="display:none;"' : '');
// user += '<label for="'+uid_shared_with+'" '+style+'>can edit</label>';
// user += '</li>';
// }
-
+
version.appendTo('#found_versions');
}
$('#dropdown').show('blind');
-
-
+
+
}
}else{
if( isset( $_['outcome_stat'] ) ) {
-
+
echo( '<div id="feedback-messages" class="'.$_['outcome_stat'].'"><h3>'.$_['outcome_msg'] ).'</h3></div><br>';
}
echo( '<strong>Versions of '.$_['path'] ).'</strong><br>';
echo('<p><em>Revert a file to a previous version by clicking on its revert button</em></p><br />');
-
+
foreach ( $_['versions'] as $v ) {
echo ' ';
echo OCP\Util::formatDate( doubleval($v['version']) );
class OC_USER_WEBDAVAUTH extends OC_User_Backend {
protected $webdavauth_url;
-
+
public function __construct() {
$this->webdavauth_url = OC_Config::getValue( "user_webdavauth_url" );
}
-
+
public function createUser() {
// Can't create user
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to create users from web frontend using WebDAV user backend',3);
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to change password for users from web frontend using WebDAV user backend',3);
return false;
}
-
+
public function checkPassword( $uid, $password ) {
$url= 'http://'.urlencode($uid).':'.urlencode($password).'@'.$this->webdavauth_url;
$headers = get_headers($url);
if($headers==false){
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to connect to WebDAV Url: "'.$this->webdavauth_url.'" ' ,3);
- return false;
+ return false;
}
$returncode= substr($headers[0], 9, 3);
}
}
-
+
/*
* we donĀ“t know if a user exists without the password. so we have to return false all the time
*/
*/
public function getUsers(){
$returnArray = array();
-
+
return $returnArray;
}
}