summaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/smb.php
blob: 6e53c4a99310c9805ac8b5e76b886cb3a91bf4a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<?php
/**
 * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Files\Storage;

require_once __DIR__ . '/../3rdparty/smb4php/smb.php';

class SMB extends \OC\Files\Storage\StreamWrapper{
	private $password;
	private $user;
	private $host;
	private $root;
	private $share;

	public function __construct($params) {
		if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
			$this->host=$params['host'];
			$this->user=$params['user'];
			$this->password=$params['password'];
			$this->share=$params['share'];
			$this->root=isset($params['root'])?$params['root']:'/';
			if ( ! $this->root || $this->root[0]!='/') {
				$this->root='/'.$this->root;
			}
			if (substr($this->root, -1, 1)!='/') {
				$this->root.='/';
			}
			if ( ! $this->share || $this->share[0]!='/') {
				$this->share='/'.$this->share;
			}
			if (substr($this->share, -1, 1)=='/') {
				$this->share = substr($this->share, 0, -1);
			}
		} else {
			throw new \Exception('Invalid configuration');
		}
	}

	public function getId(){
		return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root;
	}

	public function constructUrl($path) {
		if (substr($path, -1)=='/') {
			$path = substr($path, 0, -1);
		}
		if (substr($path, 0, 1)=='/') {
			$path = substr($path, 1);
		}
		// remove trailing dots which some versions of samba don't seem to like
		$path = rtrim($path, '.');
		$path = urlencode($path);
		$user = urlencode($this->user);
		$pass = urlencode($this->password);
		return 'smb://'.$user.':'.$pass.'@'.$this->host.$this->share.$this->root.$path;
	}

	public function stat($path) {
		if ( ! $path and $this->root=='/') {//mtime doesn't work for shares
			$stat=stat($this->constructUrl($path));
			if (empty($stat)) {
				return false;
			}
			$mtime=$this->shareMTime();
			$stat['mtime']=$mtime;
			return $stat;
		} else {
			$stat = stat($this->constructUrl($path));

			// smb4php can return an empty array if the connection could not be established
			if (empty($stat)) {
				return false;
			}

			return $stat;
		}
	}

	/**
	 * Unlinks file or directory
	 * @param string $path
	 */
	public function unlink($path) {
		if ($this->is_dir($path)) {
			$this->rmdir($path);
		}
		else {
			$url = $this->constructUrl($path);
			unlink($url);
			clearstatcache(false, $url);
		}
		// smb4php still returns false even on success so
		// check here whether file was really deleted
		return !file_exists($path);
	}

	/**
	 * check if a file or folder has been updated since $time
	 * @param string $path
	 * @param int $time
	 * @return bool
	 */
	public function hasUpdated($path,$time) {
		if(!$path and $this->root=='/') {
			// mtime doesn't work for shares, but giving the nature of the backend,
			// doing a full update is still just fast enough
			return true;
		} else {
			$actualTime=$this->filemtime($path);
			return $actualTime>$time;
		}
	}

	/**
	 * get the best guess for the modification time of the share
	 */
	private function shareMTime() {
		$dh=$this->opendir('');
		$lastCtime=0;
		if(is_resource($dh)) {
			while (($file = readdir($dh)) !== false) {
				if ($file!='.' and $file!='..') {
					$ctime=$this->filemtime($file);
					if ($ctime>$lastCtime) {
						$lastCtime=$ctime;
					}
				}
			}
		}
		return $lastCtime;
	}

	/**
	 * check if smbclient is installed
	 */
	public static function checkDependencies() {
		if (function_exists('shell_exec')) {
			$output=shell_exec('command -v smbclient 2> /dev/null');
			if (!empty($output)) {
				return true;
			}
		}
		return array('smbclient');
	}

}