272 | HTML;
273 |
274 | }
275 |
276 | }
277 |
--------------------------------------------------------------------------------
/src/lib/SambaDAV/Directory.php:
--------------------------------------------------------------------------------
1 | .
17 | #
18 | # Project page:
19 |
20 | namespace SambaDAV;
21 |
22 | use Sabre\DAV;
23 |
24 | class Directory extends DAV\FSExt\Directory
25 | {
26 | private $entries = null;
27 | private $userhome = null;
28 |
29 | public function
30 | __construct ($auth, $config, $cache, $log, $smb, URI $uri, $parent, $smbflags, $mtime)
31 | {
32 | $this->uri = $uri;
33 | $this->auth = $auth;
34 | $this->flags = new Propflags($smbflags);
35 | $this->mtime = $mtime;
36 | $this->parent = $parent;
37 | $this->config = $config;
38 | $this->cache = $cache;
39 | $this->log = $log;
40 | $this->smb = $smb;
41 | }
42 |
43 | public function
44 | getChildren ()
45 | {
46 | $this->log->trace("%s: '%s'\n", __METHOD__, $this->uri->uriFull());
47 |
48 | $children = array();
49 |
50 | // If in root folder, show master shares list:
51 | if ($this->uri->isGlobalRoot()) {
52 | foreach ($this->global_root_entries() as $entry) {
53 | $children[] = new Directory($this->auth, $this->config, $this->cache, $this->log, $this->smb, new URI($entry[0], $entry[1]), $this, 'D', null);
54 | }
55 | return $children;
56 | }
57 | // If in root folder for given server, fetch all allowed shares for that server:
58 | if ($this->uri->isServerRoot()) {
59 | foreach ($this->server_root_entries() as $entry) {
60 | $uri = clone $this->uri;
61 | $uri->addParts($entry);
62 | $children[] = new Directory($this->auth, $this->config, $this->cache, $this->log, $this->smb, $uri, $this, 'D', null);
63 | }
64 | return $children;
65 | }
66 | // Else, open share, produce listing:
67 | if (is_null($this->entries)) {
68 | $this->get_entries();
69 | }
70 | if (is_array($this->entries)) {
71 | foreach ($this->entries as $entry) {
72 | if ($entry['name'] === '..' || $entry['name'] === '.') {
73 | continue;
74 | }
75 | $children[] = $this->getChild($entry['name']);
76 | }
77 | }
78 | return $children;
79 | }
80 |
81 | public function
82 | getChild ($name)
83 | {
84 | $this->log->trace("%s: '%s' '%s'\n", __METHOD__, $this->uri->uriFull(), $name);
85 |
86 | // Are we a folder in the root dir?
87 | if ($this->uri->isGlobalRoot()) {
88 | foreach ($this->global_root_entries() as $displayname => $entry) {
89 | if ($name === $displayname) {
90 | return new Directory($this->auth, $this->config, $this->cache, $this->log, $this->smb, new URI($entry[0], $entry[1]), $this, 'D', null);
91 | }
92 | }
93 | $this->exc_notfound($name);
94 | return false;
95 | }
96 | // We have a server, but do we have a share?
97 | if ($this->uri->isServerRoot()) {
98 | if (in_array($name, $this->server_root_entries())) {
99 | $uri = clone $this->uri;
100 | $uri->addParts($name);
101 | return new Directory($this->auth, $this->config, $this->cache, $this->log, $this->smb, $uri, $this, 'D', null);
102 | }
103 | $this->exc_notfound($name);
104 | return false;
105 | }
106 | // We have a server and a share, get entries:
107 | if (is_null($this->entries)) {
108 | $this->get_entries();
109 | }
110 | if (is_array($this->entries)) {
111 | foreach ($this->entries as $entry) {
112 | if ($entry['name'] !== $name) {
113 | continue;
114 | }
115 | $uri = clone $this->uri;
116 | $uri->addParts($entry['name']);
117 |
118 | if (strpos($entry['flags'], 'D') === false) {
119 | return new File($this->auth, $this->config, $this->log, $this->smb, $uri, $this, $entry['size'], $entry['flags'], $entry['mtime']);
120 | }
121 | return new Directory($this->auth, $this->config, $this->cache, $this->log, $this->smb, $uri, $this, $entry['flags'], $entry['mtime']);
122 | }
123 | }
124 | $uri = clone $this->uri;
125 | $uri->addParts($name);
126 | $this->exc_notfound($uri->uriFull());
127 | return false;
128 | }
129 |
130 | public function
131 | createDirectory ($name)
132 | {
133 | $this->log->trace("%s: '%s' '%s'\n", __METHOD__, $this->uri->uriFull(), $name);
134 |
135 | // Cannot create directories in the root:
136 | if ($this->uri->isGlobalRoot() || $this->uri->isServerRoot()) {
137 | $this->exc_forbidden('Cannot create shares in root');
138 | }
139 | switch ($this->smb->mkdir($this->uri, $name)) {
140 | case SMB::STATUS_OK:
141 | // Invalidate entries cache:
142 | $this->cache_destroy();
143 | return true;
144 |
145 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
146 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
147 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
148 | case SMB::STATUS_INVALID_NAME: $this->exc_forbidden('invalid pathname or filename');
149 | }
150 | }
151 |
152 | public function
153 | createFile ($name, $data = null)
154 | {
155 | $uri = clone $this->uri;
156 | $uri->addParts($name);
157 |
158 | $this->log->trace("%s: '%s'\n", __METHOD__, $uri->uriFull());
159 |
160 | if ($this->uri->isGlobalRoot()) {
161 | $this->exc_forbidden('Cannot create files in global root');
162 | }
163 | if ($this->uri->isServerRoot()) {
164 | $this->exc_forbidden('Cannot create files in server root');
165 | }
166 | switch ($this->smb->put($uri, $data, $md5)) {
167 | case SMB::STATUS_OK:
168 | // Invalidate entries cache:
169 | $this->cache_destroy();
170 | return ($md5 === null) ? null : "\"$md5\"";
171 |
172 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
173 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
174 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
175 | case SMB::STATUS_INVALID_NAME: $this->exc_forbidden('invalid pathname or filename');
176 | }
177 | }
178 |
179 | public function
180 | childExists ($name)
181 | {
182 | // Are we the global root?
183 | if ($this->uri->isGlobalRoot()) {
184 | foreach ($this->global_root_entries() as $displayname => $entry) {
185 | if ($name === $displayname) {
186 | return true;
187 | }
188 | }
189 | return false;
190 | }
191 | // Are we a server root?
192 | if ($this->uri->isServerRoot()) {
193 | return (in_array($name, $this->server_root_entries()));
194 | }
195 | if (is_null($this->entries)) {
196 | $this->get_entries();
197 | }
198 | if (is_array($this->entries)) {
199 | foreach ($this->entries as $entry) {
200 | if ($name === $entry['name']) {
201 | return true;
202 | }
203 | }
204 | }
205 | return false;
206 | }
207 |
208 | public function
209 | getName ()
210 | {
211 | return $this->uri->name();
212 | }
213 |
214 | public function
215 | setName ($name)
216 | {
217 | $this->log->trace("%s: '%s' -> '%s'\n", __METHOD__, $this->uri->uriFull(), $name);
218 |
219 | if ($this->uri->isGlobalRoot() || $this->uri->isServerRoot()) {
220 | $this->exc_forbidden('cannot rename root folders');
221 | }
222 | switch ($this->smb->rename($this->uri, $name)) {
223 | case SMB::STATUS_OK:
224 | $this->cache_destroy();
225 | $this->invalidate_parent();
226 | $this->uri->rename($name);
227 | return true;
228 |
229 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
230 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
231 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
232 | case SMB::STATUS_INVALID_NAME: $this->exc_forbidden('invalid pathname or filename');
233 | }
234 | }
235 |
236 | public function
237 | getLastModified ()
238 | {
239 | return $this->mtime;
240 | }
241 |
242 | public function
243 | getIsHidden ()
244 | {
245 | return $this->flags->get('H');
246 | }
247 |
248 | public function
249 | getIsReadonly ()
250 | {
251 | return $this->flags->get('R');
252 | }
253 |
254 | public function
255 | getWin32Props ()
256 | {
257 | return $this->flags->toWin32();
258 | }
259 |
260 | public function
261 | getQuotaInfo ()
262 | {
263 | $this->log->trace("%s: '%s'\n", __METHOD__, $this->uri->uriFull());
264 |
265 | // NB: Windows 7 uses/needs this method. Must return array.
266 | // We refuse to do the actual lookup, because:
267 | // - smbclient `du` can only give us per-share numbers, not
268 | // per-directory as this function requires;
269 | // - Windows 7 makes a LOT of these calls, and honoring them
270 | // slows things down enormously;
271 | // - Windows 7 appears to use a recursive ls to determine
272 | // disk usage if it can't get direct quota numbers;
273 | // - Windows 7 does not appear to actually *use* the quota
274 | // numbers for printing usage pie charts and things.
275 | static $quota = null;
276 |
277 | // Can we return a cached value?
278 | if ($quota !== null) {
279 | return $quota;
280 | }
281 | // If we're a subdir, make SabreDAV query the root:
282 | if ($this->uri->isGlobalRoot() || !$this->uri->isServerRoot()) {
283 | return ($quota = false);
284 | }
285 | // Get results from disk cache if available and fresh:
286 | $quota = $this->cache->get(array($this->smb, 'du'), array($this->uri), $this->auth, $this->uri, 20);
287 | if (is_array($quota)) {
288 | return $quota;
289 | }
290 | switch ($quota) {
291 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
292 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
293 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
294 | }
295 | return false;
296 | }
297 |
298 | public function
299 | delete ()
300 | {
301 | $this->log->trace("%s: '%s'\n", __METHOD__, $this->uri->uriFull());
302 |
303 | if ($this->uri->isGlobalRoot() || $this->uri->isServerRoot()) {
304 | $this->exc_forbidden('cannot delete root folders');
305 | }
306 | // Delete all children:
307 | foreach ($this->getChildren() as $child) {
308 | $child->delete();
309 | }
310 | // Delete ourselves:
311 | switch ($this->smb->rmdir($this->uri)) {
312 | case SMB::STATUS_OK:
313 | $this->cache_destroy();
314 | $this->invalidate_parent();
315 | return true;
316 |
317 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
318 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
319 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
320 | case SMB::STATUS_INVALID_NAME: $this->exc_forbidden('invalid pathname or filename');
321 | }
322 | }
323 |
324 | public function
325 | updateProperties ($mutations)
326 | {
327 | // Stub function, see \SambaDAV\File::updateProperties() for
328 | // more details.
329 | // By default, Sabre wants to save these properties in a file
330 | // in the root called .sabredav, but that location is not
331 | // writable in our setup. Silently ignore for now.
332 |
333 | // In \SambaDAV\File::updateProperties(), we use smbclient's
334 | // `setmode` command to set file flags. Unfortunately, that
335 | // command only appears to work for files, not directories. So
336 | // even though we know how to decipher the Win32 propstring
337 | // we're given, we have no way of setting the flags in the
338 | // backend.
339 |
340 | return true;
341 | }
342 |
343 | public function
344 | cache_destroy ()
345 | {
346 | $this->cache->remove(array($this->smb, 'ls'), $this->auth, $this->uri);
347 | $this->entries = null;
348 | }
349 |
350 | public function
351 | setUserhome ($uri)
352 | {
353 | $this->userhome = $uri;
354 | }
355 |
356 | private function
357 | get_entries ()
358 | {
359 | // Get listing from disk cache if available and fresh:
360 | $this->entries = $this->cache->get(array($this->smb, 'ls'), array($this->uri), $this->auth, $this->uri, 5);
361 | if (is_array($this->entries)) {
362 | return;
363 | }
364 | switch ($this->entries) {
365 | case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
366 | case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
367 | case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
368 | case SMB::STATUS_INVALID_NAME: $this->exc_forbidden('invalid pathname or filename');
369 | }
370 | }
371 |
372 | private function
373 | invalidate_parent ()
374 | {
375 | if ($this->parent !== null) {
376 | $this->parent->cache_destroy();
377 | }
378 | }
379 |
380 | private function
381 | global_root_entries ()
382 | {
383 | // structure:
384 | // $entries = array('name-of-root-folder' => array('server', 'share-on-that-server'))
385 | $entries = array();
386 |
387 | foreach ($this->config->share_root as $entry)
388 | {
389 | $server = (isset($entry[0])) ? $entry[0] : false;
390 | $share = (isset($entry[1])) ? $entry[1] : false;
391 |
392 | if ($server === false) {
393 | continue;
394 | }
395 | if ($share !== false && $share !== null && $share !== '') {
396 | $entries[$share] = array($server, $share);
397 | continue;
398 | }
399 | // Just the server name given; autodiscover all shares on this server:
400 | if (!is_array($shares = $this->cache->get(array($this->smb, 'getShares'), array(new URI($server)), $this->auth, $this->uri, 15))) {
401 | // TODO: throw an exception?
402 | // switch ($shares) {
403 | // case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
404 | // case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
405 | // case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
406 | // }
407 | continue;
408 | }
409 | foreach ($shares as $share) {
410 | $entries[$share] = array($server, $share);
411 | }
412 | }
413 | // Servers from $shares_extra get a folder with the name of the *server*:
414 | foreach ($this->config->share_extra as $entry) {
415 | $entries[$entry[0]] = array($entry[0], false);
416 | }
417 | // The user's home directory gets a folder with the name of the *user*:
418 | if ($this->auth->anonymous === false && $this->userhome !== null) {
419 | if ($this->userhome->isServerRoot()) {
420 | $entries[$this->auth->user] = array($this->userhome->server(), $this->auth->user);
421 | }
422 | else {
423 | $entries[$this->userhome->share()] = array($this->userhome->server(), $this->userhome->share());
424 | }
425 | }
426 | return $entries;
427 | }
428 |
429 | private function
430 | server_root_entries ()
431 | {
432 | $entries = array();
433 |
434 | // Shares in the global root belonging to this server
435 | // also show up in the server's own subdir:
436 | foreach ($this->config->share_root as $entry) {
437 | $server = (isset($entry[0])) ? $entry[0] : null;
438 | $share = (isset($entry[1])) ? $entry[1] : null;
439 | if ($server != $this->uri->server()) {
440 | continue;
441 | }
442 | if ($share === false || $share === null || $share === '') {
443 | continue;
444 | }
445 | $entries[$share] = true;
446 | }
447 | foreach ($this->config->share_extra as $entry) {
448 | $server = (isset($entry[0])) ? $entry[0] : null;
449 | $share = (isset($entry[1])) ? $entry[1] : null;
450 | if ($server != $this->uri->server()) {
451 | continue;
452 | }
453 | if ($share !== false && $share !== null && $share !== '') {
454 | $entries[$share] = true;
455 | continue;
456 | }
457 | // Only our server name given in $share_extra;
458 | // this means: autodiscover and use all the shares on this server:
459 | if (!is_array($shares = $this->cache->get(array($this->smb, 'getShares'), array($this->uri), $this->auth, $this->uri, 15))) {
460 | // TODO: throw an exception?
461 | // switch ($shares) {
462 | // case SMB::STATUS_NOTFOUND: $this->exc_notfound($this->uri->uriFull());
463 | // case SMB::STATUS_SMBCLIENT_ERROR: $this->exc_smbclient();
464 | // case SMB::STATUS_UNAUTHENTICATED: $this->exc_unauthenticated();
465 | // }
466 | continue;
467 | }
468 | foreach ($shares as $share) {
469 | $entries[$share] = true;
470 | }
471 | }
472 | // User's home share is on this server?
473 | if ($this->auth->anonymous === false && $this->userhome !== null) {
474 | if ($this->userhome->server() === $this->uri->server()) {
475 | if ($this->userhome->isServerRoot() === null) {
476 | $entries[$this->auth->user] = true;
477 | }
478 | else {
479 | $entries[$this->userhome->share()] = true;
480 | }
481 | }
482 | }
483 | return array_keys($entries);
484 | }
485 |
486 | private function
487 | exc_smbclient ()
488 | {
489 | $m = 'smbclient error';
490 | $this->log->error("EXCEPTION: '%s': smbclient error\n", $this->uri->uriFull());
491 | throw new DAV\Exception($m);
492 | }
493 |
494 | private function
495 | exc_forbidden ($msg)
496 | {
497 | $m = "Forbidden: $msg";
498 | $this->log->warn("EXCEPTION: '%s': %s\n", $this->uri->uriFull(), $m);
499 | throw new DAV\Exception\Forbidden($m);
500 | }
501 |
502 | private function
503 | exc_notfound ($name)
504 | {
505 | $m = "Not found: \"$name\"";
506 | $this->log->warn("EXCEPTION: $m\n");
507 | throw new DAV\Exception\NotFound($m);
508 | }
509 |
510 | private function
511 | exc_unauthenticated ()
512 | {
513 | $m = sprintf("'%s' not authenticated for '%s'", $this->auth->user, $this->uri->uriFull());
514 | $this->log->warn("EXCEPTION: $m\n");
515 | throw new DAV\Exception\NotAuthenticated($m);
516 | }
517 |
518 | private function
519 | exc_notimplemented ($msg)
520 | {
521 | $m = "Not implemented: $msg";
522 | $this->log->warn("EXCEPTION: '%s': %s\n", $this->uri->uriFull(), $m);
523 | throw new DAV\Exception\NotImplemented($m);
524 | }
525 | }
526 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **Note:** There are now many enterprise-grade
2 | solutions available, like [Nextcloud](https://nextcloud.com/). Therefor
3 | this repository is no longer maintained.
4 |
5 | 
6 |
7 | # SambaDAV
8 |
9 | SambaDAV is an SMB-to-WebDAV bridge, written in PHP and running as a web
10 | application on Linux servers. It acts as the glue between Windows Samba/CIFS
11 | filesharing and WebDAV internet file access, to provide:
12 |
13 | - Secure, worldwide access to your shares and files through any web browser.
14 | Upload and download files over nothing more than standard HTTPS without the
15 | need to setup a VPN.
16 |
17 | - Access to your remote shares directly on your computer as network drives.
18 | Open and edit your files and shares as if they were on a local network drive,
19 | from any location and with any device that supports WebDAV.
20 |
21 | SambaDAV provides the advantages of the cloud (access to your files from
22 | anywhere), while leaving control over your data and your security entirely with
23 | you. You can host your Windows network shares as your own "private cloud" over
24 | standard and secure HTTPS.
25 |
26 | Release tarballs can be downloaded [here](https://github.com/1afa/sambadav/releases).
27 |
28 | After installing and configuring SambaDAV, a WebDAV-aware service listens for
29 | requests at an entrypoint URL such as `https://www.example.com/webfolders`. If
30 | you visit this URL in a browser, you get a password box where you enter your
31 | username and password. This will open a web page with a directory and file
32 | listing. You can walk through the file tree, create directories, and download
33 | or upload files.
34 |
35 | As useful as this is, the real power of SambaDAV is in its WebDAV support. If
36 | you enter the entrypoint URL into Windows' "Map Network Drive" dialog, or Mac
37 | OS X's "connect to server" dialog, you can mount your shares as a fully
38 | functional network disk with its own drive letter. Fully functional here means
39 | that you can edit, copy, move, delete and rename files and directories just
40 | like they were on a local network share. All this over simple HTTPS and without
41 | setting up a VPN.
42 |
43 | [](https://travis-ci.org/1afa/sambadav)
44 |
45 | ## How does it work?
46 |
47 | In the background, SambaDAV executes SMB commands on the user's behalf through
48 | `smbclient`, a commandline utility distributed with
49 | [Samba](http://www.samba.org), to issue requests to SMB/CIFS (i.e. Windows)
50 | fileservers. Currently, only Samba 3.x is supported; the version of `smbclient`
51 | bundled with Samba 4.x was completely rewritten and supports a different range
52 | of options.
53 |
54 | When the user requests a file, SambaDAV will spawn an `smbclient` child process
55 | to retrieve the file and pass it through to the user as a bytestream. User
56 | authentication and all the actual Samba calls are handled by `smbclient` just
57 | as if the request was done on the command line. The resulting output (or
58 | bytestream) is parsed by SambaDAV to a WebDAV response (such as "here's the
59 | file", "file not found", or "could not authenticate") and sent back to the
60 | user. The WebDAV protocol is handled by
61 | [SabreDAV](http://sabre.io/dav), a WebDAV server library written in PHP.
62 |
63 | SambaDAV is glue code, which:
64 |
65 | - translates WebDAV requests to `smbclient` calls;
66 |
67 | - runs `smbclient` on behalf of the user;
68 |
69 | - captures and parsing the output, and:
70 |
71 | - sends the output back as a WebDAV response.
72 |
73 | This may seem like a bit of a hack, but it's actually remarkably reliable,
74 | resilient and performant for what it is. Some features:
75 |
76 | - File uploading/downloading is all fully streaming through the use of PHP
77 | streams and Unix pipes. No temporary files are created on the server. In
78 | practice you can read and write gigabyte-sized files at many tens of
79 | megabytes per second.
80 |
81 | - Supports UTF-8 filenames.
82 |
83 | - Supports read-only and hidden attribute flags.
84 |
85 | - Supports Windows XP (but you'll need a valid SSL certificate and some
86 | registry hacks, see elsewhere).
87 |
88 | - Robust decoding of the `smbclient` output (as buttoned-down and mistrusting
89 | as possible, using hints derived from the `smbclient` source code).
90 |
91 | - Caches lookups and responses in memory (using a filesystem-based cache in
92 | /dev/shm, shared memory) and properly invalidates the cache when a resource
93 | changes.
94 |
95 | - Supports multiple servers, multiple shares, and dynamic userhomes based on
96 | the username or the value of an LDAP property.
97 |
98 | - Supports anonymous (guest) logins if you enable it.
99 |
100 | - Passes the username and password to `smbclient` through an unnamed pipe (an
101 | anonymous file descriptor), which makes this sensitive data fairly hard to
102 | intercept (and invisible in the process table).
103 |
104 | - Supports group-based LDAP authentication as an cheap extra authentication
105 | check before making expensive calls to `smbclient`.
106 |
107 |
108 | ## History and provenance
109 |
110 | SambaDAV was originally written by [Bokxing IT BV](http://www.bokxing-it.nl),
111 | Delft, the Netherlands, to supplement a line of SME servers. It was released
112 | because this software was found useful and fills a need, and to give something
113 | back to the open-source community. There are other projects that offer something
114 | similar, such as [Davenport](http://davenport.sourceforge.net) and smbwebclient.php,
115 | but SambaDAV was written because those projects show their age and did not fit our
116 | needs.
117 |
118 | At the start of 2015 the project was transferred to the company developing the
119 | aforementioned line of SME servers, [1A First Alternative](http://www.1afa.com).
120 |
121 | ## License
122 |
123 | SambaDAV is licensed under the terms of the GNU Affero GPL version 3. Please
124 | refer to the
125 | [LICENSE](https://github.com/1afa/sambadav/blob/master/LICENSE) file in
126 | the project root. Please contact the authors if you have any licensing
127 | questions or requests.
128 |
129 |
130 | ## Installation
131 |
132 | SambaDAV only works on Linux servers, since among other things, it uses the
133 | Unix concept of unnamed pipes to communicate with and control `smbclient`.
134 |
135 | We assume you have installed and configured your Samba server, and can do
136 | commandline lookups with `smbclient`:
137 |
138 | ```sh
139 | # This should print a list of shares on your Samba server:
140 | smbclient -N -L //yourserver
141 | ```
142 |
143 | Download a SambaDAV release tarball
144 | [here](https://github.com/1afa/sambadav/releases). Unpack it in some
145 | directory, we'll assume `/tmp` for convenience:
146 |
147 | ```sh
148 | cd /tmp
149 | tar xvf /path/to/sambadav-version.tar.gz
150 | ```
151 |
152 | Copy the application source to a directory on on the web server. We'll assume
153 | that the application directory is `/var/www/htdocs/webfolders`:
154 |
155 | ```sh
156 | cp -ar /tmp/sambadav-version/src /var/www/htdocs/webfolders
157 | ```
158 |
159 | Install [SabreDAV](http://sabre.io/dav) using [Composer](http://getcomposer.org):
160 |
161 | ```sh
162 | cd /var/www/htdocs/webfolders
163 | composer --optimize-autoloader install
164 | ```
165 |
166 | The following directories should be made writable for the webserver:
167 |
168 | - `log`: tracelogs are written here;
169 | - `data`: the place where SabreDAV keeps lockfiles.
170 |
171 | If your webserver runs as the user `apache`:
172 |
173 | ```sh
174 | chown apache:root /var/www/htdocs/webfolders/{log,data}
175 | chmod 0750 /var/www/htdocs/webfolders/{log,data}
176 | ```
177 |
178 | At this point all the files are in the right place, all that's left is
179 | to configure the webserver and SambaDAV.
180 |
181 |
182 | ## Webserver configuration
183 |
184 | We assume that you're running your web server on the standard port 443 (because
185 | you're using SSL!) and want to serve SambaDAV from a subdirectory. In the
186 | browser, SambaDAV will be available via `https://example.com/webfolders`. For
187 | native WebDAV clients we'll do one better and allow them to connect straight to
188 | `http://example.com/`, by redirecting them in two steps to the proper location.
189 | This is more than just fancy: it's the only way the internal Windows XP WebDAV
190 | client will connect to a subfolder over SSL at all.
191 |
192 | The webserver configuration is fairly involved because we want to support as
193 | wide a range of clients as possible. Support for Windows XP's built-in WebDAV
194 | client in particular is tricky to set up. The Windows XP client always connects
195 | to the root of the domain at port 80. In order to get it to use SSL at port 443
196 | and use `/webfolders`, we must take the following steps:
197 |
198 | 1. Detect that a Windows XP client is trying to connect to port 80 at the
199 | root of the domain by sniffing the user agent string;
200 |
201 | 2. In the Apache config for the server at port 80, add a rewrite rule to send
202 | the Windows XP client to the same location but at port 443, using a 302
203 | Redirect response which the Windows XP client will honor while upgrading
204 | to SSL;
205 |
206 | 3. In the Apache config for the server at port 443, add a second set of rewrite
207 | rules that match only the Windows XP client and transparently proxy a
208 | request of the form `/`, to `/webfolders/` internally
209 | without telling the client.
210 |
211 | After these three steps, connecting with the Windows XP WebDAV client to
212 | `http://www.example.com/` will properly redirect to
213 | `https://www.example.com/webfolders/`.
214 |
215 | Because this trick is convenient for everyone who uses a native WebDAV client,
216 | we've expanded the list of eligible user agents from just the Windows XP
217 | internal one to a full range. This goes in the virtual host section for your
218 | plain HTTP server on port 80:
219 |
220 | ```apache
221 | # Workaround for the builtin WinXP WebDAV client: it can only connect to the
222 | # server root (/), over plain HTTP, port 80. Fortunately, it *does* honor 302
223 | # redirect responses, and *even* upgrades to SSL if asked! So we use browser
224 | # string matching to redirect the WinXP client to the root of our SSL server,
225 | # from where it will be redirected once more to the actual location.
226 | # This enables driveletter mapping in Windows XP.
227 | # It's also useful for other clients, so we also catch the most popular ones:
228 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft-WebDAV-MiniRedir" [OR]
229 | RewriteCond %{HTTP_USER_AGENT} "^(DAV|Dav|dav)" [OR]
230 | RewriteCond %{HTTP_USER_AGENT} "^WebDAV" [OR]
231 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft Data Access Internet Publishing Provider" [OR]
232 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft Office" [OR]
233 | RewriteCond %{HTTP_USER_AGENT} "^WebDrive" [OR]
234 | RewriteCond %{HTTP_USER_AGENT} "^iWorkHTTPKit" [OR]
235 | RewriteCond %{HTTP_USER_AGENT} "^gnome-vfs" [OR]
236 | RewriteCond %{HTTP_USER_AGENT} "^Dreamweaver-WebDAV-SCM1" [OR]
237 | RewriteCond %{HTTP_USER_AGENT} "^BitKinex/" [OR]
238 | RewriteCond %{HTTP_USER_AGENT} "^cadaver/" [OR]
239 | RewriteCond %{HTTP_USER_AGENT} "^neon/" [OR]
240 | RewriteCond %{HTTP_USER_AGENT} "^Cyberduck/" [OR]
241 | RewriteCond %{HTTP_USER_AGENT} "^gvfs/" [OR]
242 | RewriteCond %{HTTP_USER_AGENT} "^Transmit"
243 | RewriteRule ^/(.*) https://%{HTTP_HOST}:443/$1 [R]
244 |
245 | # Other clients are upgraded to SSL:
246 | RewriteRule ^/webfolders(.*) https://%{HTTP_HOST}/webfolders$1 [R]
247 | ```
248 |
249 | Since, for the sake of this manual, we are using the `/webfolders`
250 | subdirectory, we also want to transparently redirect WebDAV clients who arrive
251 | at the root of the server to `/webfolders`. Clients who reach this point always
252 | do so over SSL (since otherwise they would have been caught by the snippet
253 | above), so the following goes in the virtual host configuration for the SSL
254 | server on port 443:
255 |
256 | ```apache
257 | # Special rule for the WinXP driveletter mounter;
258 | # it will connect to the server root, and must be transparently
259 | # proxied to the actual location:
260 | # Also useful for other DAV clients:
261 | # Exception: when client requests //server/webfolders, he should not be
262 | # rewritten to /webfolders/webfolders, but end up in /webfolders.
263 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft-WebDAV-MiniRedir" [OR]
264 | RewriteCond %{HTTP_USER_AGENT} "^(DAV|Dav|dav)" [OR]
265 | RewriteCond %{HTTP_USER_AGENT} "^WebDAV" [OR]
266 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft Data Access Internet Publishing Provider" [OR]
267 | RewriteCond %{HTTP_USER_AGENT} "^Microsoft Office" [OR]
268 | RewriteCond %{HTTP_USER_AGENT} "^WebDrive" [OR]
269 | RewriteCond %{HTTP_USER_AGENT} "^iWorkHTTPKit" [OR]
270 | RewriteCond %{HTTP_USER_AGENT} "^gnome-vfs" [OR]
271 | RewriteCond %{HTTP_USER_AGENT} "^Dreamweaver-WebDAV-SCM1" [OR]
272 | RewriteCond %{HTTP_USER_AGENT} "^BitKinex/" [OR]
273 | RewriteCond %{HTTP_USER_AGENT} "^cadaver/" [OR]
274 | RewriteCond %{HTTP_USER_AGENT} "^neon/" [OR]
275 | RewriteCond %{HTTP_USER_AGENT} "^Cyberduck/" [OR]
276 | RewriteCond %{HTTP_USER_AGENT} "^gvfs/" [OR]
277 | RewriteCond %{HTTP_USER_AGENT} "^Transmit"
278 | RewriteCond %{REQUEST_URI} !^/webfolders$
279 | RewriteCond %{REQUEST_URI} !^/webfolders/
280 | RewriteRule ^/(.*) /webfolders/$1 [PT]
281 |
282 | RewriteRule ^/webfolders$ /webfolders/ [R]
283 | Alias /webfolders/ /var/www/htdocs/webfolders/
284 | ```
285 |
286 | Clients who arrive at the server root over port 80 will now be untransparently
287 | redirected to SSL over port 443, and transparently redirected from `/` to
288 | `/webfolders/`.
289 |
290 | Next comes the directory configuration. In the virtual host section of your
291 | port 443 SSL server, put something along the following lines:
292 |
293 | ```apache
294 |
295 |
296 | # As our "cloud solution", this should be available from anywhere:
297 | Order allow,deny
298 | Allow from all
299 |
300 | AddDefaultCharset utf-8
301 | AddType application/x-httpd-php php php5
302 | DirectoryIndex server.php
303 |
304 | # Reroute all requests to subdirectories, or things that are not
305 | # physical files in the root directory, through server.php, which
306 | # happens to be a physical file in the root directory and thus exempt.
307 | # This also hides physical app directories like /data and /lib
308 | # from view.
309 | RewriteEngine On
310 | RewriteBase /webfolders
311 | RewriteCond %{REQUEST_URI} ^/webfolders/.*/.*$ [OR]
312 | RewriteCond %{REQUEST_FILENAME} !-f
313 | RewriteRule ^.*$ /webfolders/server.php
314 |
315 |
316 | ```
317 |
318 | The rewrite rules tell the server to send all requests to `server.php` that
319 | contain two or more slashes (so are guaranteed to be virtual), and those not
320 | referencing real files on disk, to `server.php` for processing. Since
321 | `server.php` is itself a real file on disk, this breaks the loop and avoids
322 | recursion. Resources such as `style.css` and `dir.png` also happen to be plain
323 | files in the SambaDAV root, and are available normally.
324 |
325 |
326 | ## SambaDAV configuration
327 |
328 | At startup, SambaDAV reads all PHP files in the `/config` directory. Each file
329 | should return an array with config keys, like so:
330 |
331 | ```php
332 | 'config_value',
336 | );
337 | ```
338 |
339 | The order and number of files doesn't matter as long as the right keys are set,
340 | but for convenience we supply four example config files.
341 |
342 | The main configuration file is `/config/config.inc.php`. Please refer to the
343 | comments in the file itself for more information. Some notes:
344 |
345 | - `enable_webfolders` is the "master switch" for the whole SambaDAV suite. If
346 | this variable is not available *and* does not have the explicit value of
347 | `true`, then `server.php` does an early exit with a '404 Not found' error.
348 | The idea behind this is to create a single on/off switch for SambaDAV,
349 | through which administrators can centrally enable or disable the service.
350 |
351 | - `server_basedir` is used by `server.php` to check whether the request was
352 | transparently rewritten from the root of the server. If the given URI does
353 | not start with `server_basedir`, `server.php` appends it during the setup of
354 | the SabreDAV server.
355 |
356 | - `smbclient_extra_opts` is an optional string containing extra arguments to
357 | pass to `smbclient`. For example, you can specify a nonstandard port by
358 | adding `--port 6789`. The option string is pasted verbatim and unescaped at
359 | the end of the `smbclient` invocation.
360 |
361 | - `anonymous_only` allows _only_ anonymous logins, and consequently bypasses
362 | the whole basic authentication logic, because credentials are no longer
363 | necessary. This setting is for people who allow guest access to their shares.
364 |
365 | - `anonymous_allow` means that empty usernames and passwords are not rejected
366 | as they would normally be, but converted into an anonymous (guest) request.
367 |
368 | `anonymous_allow` causes seemingly strange behaviour when visiting SambaDAV
369 | in the browser. You might expect to get a password box, but instead you find
370 | that you're always logged in automatically as the anonymous user. That
371 | happens because the password box normally only appears after an initial
372 | unauthenticated request is countered by the server's 'authentication
373 | required' response. This instructs the browser to retry with a username and
374 | password. However, if anonymous logins are permitted, the server cannot tell
375 | the difference between someone attempting a true anonymous login and someone
376 | who should be sent an 'authentication required' response. So in the browser
377 | you always become the anonymous (guest) user.
378 |
379 | With a "real" WebDAV client, you can pass a username and password in the very
380 | first request and get authenticated access that way.
381 |
382 | - `cache_use` enables the disk cache. If you set this to `false`, nothing will be
383 | cached and performance will be rather slow (everything's an expensive call to
384 | `smbclient`). Note that file contents are never cached, only metadata such as
385 | directory listings.
386 |
387 | - `cache_dir` is the directory to use for caching. The default is
388 | `/dev/shm/webfolders`, which is a directory in `/dev/shm`, a filesystem in
389 | shared memory. The cache code will create this cache directory at runtime if
390 | it doesn't exist (and set the permissons correctly), so you don't have to
391 | create the directory first. See [this section](#caching) for more.
392 |
393 | - `share_userhomes` is a bit of a misnomer, it's not a share but the name of
394 | the server on which the userhomes can be found. If this variable is not
395 | defined or is `false`, no userhome lookup is done. However, if it's set to
396 | the name of a server, then the share `//server/username` is added, where
397 | `username` is the name of the logged-in user. This userhome will appear in
398 | the SambaDAV root as a folder with the name of the logged-in user.
399 |
400 | - `share_userhome_ldap` can be set to the name of a LDAP property containing
401 | the URL for the user's home share. The value of this property must be of the
402 | form `\\server` (which is interpreted as `\\server\username` for the
403 | currently logged-in user), or `\\server\share`. For instance, if all your
404 | LDAP users have a property called `sambaHomePath`, then its value will be
405 | used for the home share. This setting overrides `share_userhomes`, and only
406 | works with LDAP authentication.
407 |
408 | The username that a user logs in with can be dissected as follows:
409 |
410 | workgroup\username@domain
411 |
412 | %w = workgroup
413 | %u = username
414 | %d = domain
415 |
416 | The `%w`, `%u` and `%d` placeholders can be used in pattern strings. The
417 | username is always available by definition, unless anonymous logins are
418 | allowed. The other two placeholders can be undefined if the user didn't enter
419 | them. If you specify a pattern that can't be filled from the user's input, the
420 | application will abort the request. Patterns can be set to `null` or left
421 | unspecified to use the default values.
422 |
423 | - `userhome_pattern` contains a pattern to use for the userhomes. Example:
424 | `'//SERVER/%u'`. Defaults to `null` (no userhome derived from a pattern).
425 |
426 | - `ldap_username_pattern` contains the pattern to use for the LDAP bind
427 | operation. Defaults to the (stripped) username for backwards compatibility.
428 |
429 | - `samba_username_pattern` and `samba_domain_pattern` contain patterns to use
430 | for logging in to `smbclient`. They default to the username and `null`,
431 | respectively.
432 |
433 | - `log_level`: set the log verbosity. Defaults to 'warn' when omitted. Can be
434 | set to the values 'none', 'error', 'warn', 'info', 'debug' or 'trace' in
435 | order of verboseness from least to most.
436 |
437 | The other two config files are:
438 |
439 | - `share_root.inc.php`: defines server/share pairs that show up in the server
440 | root under the name of the share;
441 |
442 | - `share_extra.inc.php`: defines server/share pairs that show up in the server
443 | root as a folder with the name of the server(s), containing folders named
444 | after the share(s) on that server;
445 |
446 | See the files themselves for specific examples and syntax.
447 |
448 | An example of what `share_root.inc.php` can look like:
449 |
450 | ```php
451 | array(
454 | array('server1'),
455 | array('server2','share1'),
456 | array('server2','share2'),
457 | ),
458 | );
459 | ```
460 |
461 | `share_root` is an array of arrays. Each child array consists of one or two
462 | strings. The first string is the name of a server, the second string is
463 | optional and is the name of a share on that server. If you don't specify a
464 | share name, SambaDAV will use a `smbclient -L` call to automatically retrieve a
465 | list of available shares on that server (which may or may not be accessible to
466 | the user).
467 |
468 | `share_root` is so called because the shares that you specify here are placed
469 | directly in the root as folders with the name of the *share*. In the example
470 | above, the root folder would have multiple subfolders: a folder for each share
471 | found on `server1`, and the folders `share1` and `share2`.
472 |
473 | `share_extra` is like `share_root`, but shares and servers that you define in
474 | that array are always placed in the SambaDAV root in a folder with the name of
475 | the *server*, containing subfolders named after the shares.
476 |
477 | ```php
478 | array(
481 | array('server5'),
482 | array('server6','share6').
483 | ),
484 | );
485 | ```
486 |
487 | In the example above, this would create two folders in the root named `server5`
488 | and `server6`, with `server5` containing folders for all the autodiscovered
489 | shares on that server, and `server6` containing a single subfolder called `share6`.
490 |
491 | Further customization of the shares listing can be done by configuring Samba to
492 | produce the required list of shares. SambaDAV is kept simple on purpose.
493 |
494 |
495 | # User authentication
496 |
497 | SambaDAV supports three methods of user authentication:
498 |
499 | 1. Anonymous access only;
500 |
501 | 2. Access through HTTP Basic authentication;
502 |
503 | 3. Access through HTTP Basic authentication, with an extra check against an
504 | LDAP server to see if the user is known and is allowed to access SambaDAV.
505 |
506 | It is not possible to use Digest authentication, because SambaDAV needs the
507 | user's plaintext username and password to pass on to `smbclient`. Using Basic
508 | authentication is only secure over a HTTPS connection, so always make sure your
509 | connection is properly encrypted!
510 |
511 | SambaDAV does not have a user database of its own; it relies completely on
512 | `smbclient` to authenticate and authorize the user. SambaDAV passes through
513 | anything the user enters to `smbclient` for actual inspection. Smbclient is free
514 | to accept or reject the login attempt according to its internal processes, and
515 | SambaDAV will faithfully pass on the response.
516 |
517 | The extra check against the LDAP server was written specially for the original
518 | deployment environment, and might be too specific for general use. Since
519 | version 0.4.0, SambaDAV supports two kinds of binds: the AD kind and the
520 | regular kind, here called "fastbind". If the ldap host and basedn are not
521 | provided in the config file, the code will try to get them from
522 | `/etc/ldap.conf`.
523 |
524 | In the fastbind scenario, the LDAP code will check whether the username and
525 | password are valid by attempting to bind as the given user. If that succeeds,
526 | and the config variable `ldap_groups` is not `false`, it checks whether the
527 | user is a member of the given Posix group(s). If either condition fails, the
528 | user is rejected.
529 |
530 | In the AD bind scenario, the code will first bind with an auth DN, fetch the DN
531 | for the user, and rebind as that user. It also optionally checks group
532 | memberships.
533 |
534 | There are three reasons for having LDAP support. Firstly, to put a lightweight
535 | authentication service in front of the relatively heavyweight `smbclient`
536 | method of authentication (spawning a process, interpreting the results and so
537 | on). Secondly, to provide some form of access control. In this setup, only the
538 | users who are members of a certain group can use SambaDAV. Thirdly, there is
539 | the option to fetch the location of a user's home directory from an LDAP
540 | property.
541 |
542 |
543 | ## Caching
544 |
545 | Though the cache can be turned off in the config, you may find that the
546 | performance becomes unacceptably slow, especially under Mac OS X. SambaDAV can
547 | cache directory listings, file properties and other metadata on disk for
548 | improved performance. The default cache location, changeable in the config, is
549 | a directory in shared memory, under `/dev/shm`. SambaDAV will create this
550 | directory with proper ownerships and permissions if it doesn't exist.
551 |
552 | File *contents* are never cached. Only metadata such as directory listings are
553 | cached. Metadata is first serialized, then zipped, then encrypted with a key
554 | derived from the user's password.
555 |
556 | The cache is automatically cleaned at certain intervals. A semaphore file is
557 | used to avoid pulling the rug out from under active lookups. It should always
558 | be safe to delete all the cache files (but hopefully unnecessary, since the
559 | cache is self-cleaning).
560 |
561 |
562 | ## Logging
563 |
564 | SambaDAV has a simple built-in logging mechanism that traces out the flow
565 | through the program. The granularity is currently not great: trace logging can
566 | be turned either 'off' or 'on'. The setting is in `/include/function.log.php`,
567 | the `$trace_log` variable. Feel free to add `log_trace` statements wherever you
568 | need them. Logging may become more pervasive in future releases.
569 |
570 |
571 | ## Client support
572 |
573 | See also the SabreDAV documentation for details. Client support is mostly
574 | something between the client and SabreDAV, not something that SambaDAV has
575 | much influence on. However, there are some tips for getting WebDAV clients
576 | running:
577 |
578 | - All clients should connect over SSL as a matter of principle. Don't use an
579 | unencrypted connection, or you will expose passwords and file contents to the
580 | whole world.
581 |
582 | - Windows XP needs a valid certificate. If the Network Drive mapper is not
583 | working, try surfing to the webfolders URL with Internet Explorer and see if
584 | you get a certificate error. Internet Explorer uses the same networking code
585 | as the builtin Webfolders client, and any errors you get in Internet Explorer
586 | will tell you what's going wrong in the Webfolders client.
587 |
588 | - Windows XP does not support SSL connection syntax, or connecting to anything
589 | other than the root of a domain, but it does properly redirect to an SSL
590 | connection if it receives a redirect response from the server. So for proper
591 | Windows XP support, you must setup a plain HTTP server that redirects all
592 | requests to an SSL server with a valid SSL certificate. See the
593 | [Config](#webserver-configuration) section.
594 |
595 |
596 | ### Slow in Windows 7?
597 |
598 | The default configuration of the built-in Windows 7 WebDAV client sometimes
599 | makes network drives seem really slow to respond. A network share will take
600 | ages to connect and opening folders takes many seconds. Luckily, getting a
601 | snappy browsing experience is an easy fix:
602 |
603 | 1. Open Internet Explorer.
604 | 2. Open the `Tools` menu from the top menu bar.
605 | 3. Click `Internet Options`. A window opens.
606 | 4. In the window, open the `Connections` tab.
607 | 5. Click the button `LAN settings` near the bottom. A second window opens.
608 | 6. Uncheck the box marked `Automatically detect settings`.
609 | 7. Click `Ok` on both the windows to close them.
610 |
611 | Try again and you should be able to connect and browse at normal speeds.
612 |
613 | More information can be found in the [SabreDAV wiki](http://sabre.io/dav/clients).
614 |
615 |
616 | ## Security considerations
617 |
618 | Always run this service over SSL! Your users are sending plaintext passwords,
619 | which is only secure if the transport is encrypted.
620 |
621 | Files inside the WebDAV tree (such as PHP files) are not interpreted or
622 | executed by SambaDAV; they are streamed straight through `smbclient` to the
623 | user in passthrough mode.
624 |
625 | All operations on the server are run through `smbclient`, so users can do no
626 | more than they already could by running `smbclient` on the server in a shell.
627 | All permission checking is left to the SMB server.
628 |
629 | The username and password are supplied to `smbclient` in plaintext through an
630 | anonymous file descriptor (Unix pipe). This is reasonably secure (the passwords
631 | don't show up in the process table and aren't written to disk), but in theory,
632 | the data could be intercepted by other processes running as the same user. For
633 | that reason, you should run this service under a dedicated user account.
634 |
635 | `smbclient` comes with an ill-conceived shell-command "feature": users can
636 | execute shell commands on the local server by sending `smbclient` a command
637 | that starts with an exclamation mark; see the manpage. This is hardly useful
638 | because the shell command is executed locally instead of remotely. The problem
639 | is made worse by the fact that the exclamation mark is actually allowed in
640 | Windows filenames, so it can't really be filtered out. However, characters from
641 | 0 to 31 are not allowed, and that range includes newlines. SambaDAV does filter
642 | out (rather, forbid) characters in that range, so it's not easy to arrange for
643 | an exclamation mark to appear at the start of a line.
644 |
645 | We make no guarantees about the security or fitness for purpose of this
646 | software. See the
647 | [LICENSE](https://github.com/1afa/sambadav/blob/master/LICENSE) for
648 | specifics.
649 |
650 |
651 | ## Troubleshooting
652 |
653 | - Is your `smbclient` install working correctly? Do you get the expected output
654 | when you execute:
655 |
656 | ```sh
657 | # Lookup shares list as guest:
658 | smbclient -N -L //myserver
659 |
660 | # Lookup shares as specific user:
661 | smbclient -U myuser -L //myserver
662 |
663 | # Connect to a share as a specific user, get a file listing:
664 | smbclient -U myuser //myserver/myshare -c 'ls'
665 | ```
666 |
667 | If these examples fail, try again with `--debuglevel=3` and carefully inspect
668 | the output for errors.
669 |
670 | - If things are not working, try connecting to the server with a browser first.
671 | If your browser can't connect, or if you encounter certificate errors, fix
672 | those problems first. Only try WebDAV clients after getting SambaDAV to work
673 | in the browser.
674 |
675 | - If nothing appears to happen (blank page), check the PHP error logs for error
676 | messages. SabreDAV requires a number of PHP extensions; you might need to
677 | enable some.
678 |
679 | - Is `$enable_webfolders` set to the precise value of `true` in
680 | `/config/share_userhomes.inc.php`? That variable is the master switch; if
681 | it's set to anything but `true`, `server.php` bails out early with a 404 Not
682 | Found error.
683 |
684 | - If you're getting errors, try checking the server logs. Pay attention to the
685 | resources requested and the HTTP reponse codes dished out by SambaDAV. Is
686 | the client requesting the proper URL?
687 |
688 | - Remember that SambaDAV is ultimately just a frontend to `smbclient`. If a
689 | user is granted no rights by `smbclient`, there's nothing SambaDAV can do.
690 | Turn on tracelogging to see the commands issued to `smbclient` and reproduce
691 | them on the commandline. Any unexpected errors?
692 |
693 | - SambaDAV makes precise assumptions about the format of the `smbclient`
694 | output. Your `smbclient` might be producing different output from what
695 | SambaDAV expects.
696 |
697 |
698 | ## Reporting bugs
699 |
700 | Bugs should be reported at the GitHub project page, in the issues section. This
701 | requires a GitHub account. Alternatively, you can send an e-mail to the
702 | authors; the e-mail addresses are found in the commit headers.
703 |
704 | Please be specific about any problems you encounter. Turn on logging and try to
705 | capture the commands and responses sent by SambaDAV and `smbclient`. (This
706 | might require the insertion of some strategically placed `error_log()`
707 | statements.) Include a mention of what you think the output should be.
708 |
709 | ## Upgrading
710 |
711 | ### From 0.5 to 0.6
712 |
713 | If you want to migrate an older config, you need to add the new config options:
714 | - `'ldap_port' => 389,`
715 | - `'browserplugin_enable_delete' => false,`
716 |
717 | ### From 0.4 to 0.5
718 |
719 | If you want to migrate an older config, you probably need to add the new
720 | `ldap_username_pattern` and `samba_username_pattern` config options. The
721 | backwards-compatible value for these is `%u` (use the stripped username).
722 |
723 | ### From 0.3 to 0.4
724 |
725 | The config system changed between 0.3 and 0.4. In 0.3, configuration was done
726 | with a mix of global variables and defines. This changed in 0.4 to a system of
727 | array keys which are merged into the main config from all PHP files found in
728 | `/config`. The config variables and settings themselves have not changed, and
729 | can be carried over quite easily from an 0.3 installation.
730 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU AFFERO GENERAL PUBLIC LICENSE
2 | Version 3, 19 November 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU Affero General Public License is a free, copyleft license for
11 | software and other kinds of works, specifically designed to ensure
12 | cooperation with the community in the case of network server software.
13 |
14 | The licenses for most software and other practical works are designed
15 | to take away your freedom to share and change the works. By contrast,
16 | our General Public Licenses are intended to guarantee your freedom to
17 | share and change all versions of a program--to make sure it remains free
18 | software for all its users.
19 |
20 | When we speak of free software, we are referring to freedom, not
21 | price. Our General Public Licenses are designed to make sure that you
22 | have the freedom to distribute copies of free software (and charge for
23 | them if you wish), that you receive source code or can get it if you
24 | want it, that you can change the software or use pieces of it in new
25 | free programs, and that you know you can do these things.
26 |
27 | Developers that use our General Public Licenses protect your rights
28 | with two steps: (1) assert copyright on the software, and (2) offer
29 | you this License which gives you legal permission to copy, distribute
30 | and/or modify the software.
31 |
32 | A secondary benefit of defending all users' freedom is that
33 | improvements made in alternate versions of the program, if they
34 | receive widespread use, become available for other developers to
35 | incorporate. Many developers of free software are heartened and
36 | encouraged by the resulting cooperation. However, in the case of
37 | software used on network servers, this result may fail to come about.
38 | The GNU General Public License permits making a modified version and
39 | letting the public access it on a server without ever releasing its
40 | source code to the public.
41 |
42 | The GNU Affero General Public License is designed specifically to
43 | ensure that, in such cases, the modified source code becomes available
44 | to the community. It requires the operator of a network server to
45 | provide the source code of the modified version running there to the
46 | users of that server. Therefore, public use of a modified version, on
47 | a publicly accessible server, gives the public access to the source
48 | code of the modified version.
49 |
50 | An older license, called the Affero General Public License and
51 | published by Affero, was designed to accomplish similar goals. This is
52 | a different license, not a version of the Affero GPL, but Affero has
53 | released a new version of the Affero GPL which permits relicensing under
54 | this license.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | TERMS AND CONDITIONS
60 |
61 | 0. Definitions.
62 |
63 | "This License" refers to version 3 of the GNU Affero General Public License.
64 |
65 | "Copyright" also means copyright-like laws that apply to other kinds of
66 | works, such as semiconductor masks.
67 |
68 | "The Program" refers to any copyrightable work licensed under this
69 | License. Each licensee is addressed as "you". "Licensees" and
70 | "recipients" may be individuals or organizations.
71 |
72 | To "modify" a work means to copy from or adapt all or part of the work
73 | in a fashion requiring copyright permission, other than the making of an
74 | exact copy. The resulting work is called a "modified version" of the
75 | earlier work or a work "based on" the earlier work.
76 |
77 | A "covered work" means either the unmodified Program or a work based
78 | on the Program.
79 |
80 | To "propagate" a work means to do anything with it that, without
81 | permission, would make you directly or secondarily liable for
82 | infringement under applicable copyright law, except executing it on a
83 | computer or modifying a private copy. Propagation includes copying,
84 | distribution (with or without modification), making available to the
85 | public, and in some countries other activities as well.
86 |
87 | To "convey" a work means any kind of propagation that enables other
88 | parties to make or receive copies. Mere interaction with a user through
89 | a computer network, with no transfer of a copy, is not conveying.
90 |
91 | An interactive user interface displays "Appropriate Legal Notices"
92 | to the extent that it includes a convenient and prominently visible
93 | feature that (1) displays an appropriate copyright notice, and (2)
94 | tells the user that there is no warranty for the work (except to the
95 | extent that warranties are provided), that licensees may convey the
96 | work under this License, and how to view a copy of this License. If
97 | the interface presents a list of user commands or options, such as a
98 | menu, a prominent item in the list meets this criterion.
99 |
100 | 1. Source Code.
101 |
102 | The "source code" for a work means the preferred form of the work
103 | for making modifications to it. "Object code" means any non-source
104 | form of a work.
105 |
106 | A "Standard Interface" means an interface that either is an official
107 | standard defined by a recognized standards body, or, in the case of
108 | interfaces specified for a particular programming language, one that
109 | is widely used among developers working in that language.
110 |
111 | The "System Libraries" of an executable work include anything, other
112 | than the work as a whole, that (a) is included in the normal form of
113 | packaging a Major Component, but which is not part of that Major
114 | Component, and (b) serves only to enable use of the work with that
115 | Major Component, or to implement a Standard Interface for which an
116 | implementation is available to the public in source code form. A
117 | "Major Component", in this context, means a major essential component
118 | (kernel, window system, and so on) of the specific operating system
119 | (if any) on which the executable work runs, or a compiler used to
120 | produce the work, or an object code interpreter used to run it.
121 |
122 | The "Corresponding Source" for a work in object code form means all
123 | the source code needed to generate, install, and (for an executable
124 | work) run the object code and to modify the work, including scripts to
125 | control those activities. However, it does not include the work's
126 | System Libraries, or general-purpose tools or generally available free
127 | programs which are used unmodified in performing those activities but
128 | which are not part of the work. For example, Corresponding Source
129 | includes interface definition files associated with source files for
130 | the work, and the source code for shared libraries and dynamically
131 | linked subprograms that the work is specifically designed to require,
132 | such as by intimate data communication or control flow between those
133 | subprograms and other parts of the work.
134 |
135 | The Corresponding Source need not include anything that users
136 | can regenerate automatically from other parts of the Corresponding
137 | Source.
138 |
139 | The Corresponding Source for a work in source code form is that
140 | same work.
141 |
142 | 2. Basic Permissions.
143 |
144 | All rights granted under this License are granted for the term of
145 | copyright on the Program, and are irrevocable provided the stated
146 | conditions are met. This License explicitly affirms your unlimited
147 | permission to run the unmodified Program. The output from running a
148 | covered work is covered by this License only if the output, given its
149 | content, constitutes a covered work. This License acknowledges your
150 | rights of fair use or other equivalent, as provided by copyright law.
151 |
152 | You may make, run and propagate covered works that you do not
153 | convey, without conditions so long as your license otherwise remains
154 | in force. You may convey covered works to others for the sole purpose
155 | of having them make modifications exclusively for you, or provide you
156 | with facilities for running those works, provided that you comply with
157 | the terms of this License in conveying all material for which you do
158 | not control copyright. Those thus making or running the covered works
159 | for you must do so exclusively on your behalf, under your direction
160 | and control, on terms that prohibit them from making any copies of
161 | your copyrighted material outside their relationship with you.
162 |
163 | Conveying under any other circumstances is permitted solely under
164 | the conditions stated below. Sublicensing is not allowed; section 10
165 | makes it unnecessary.
166 |
167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
168 |
169 | No covered work shall be deemed part of an effective technological
170 | measure under any applicable law fulfilling obligations under article
171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
172 | similar laws prohibiting or restricting circumvention of such
173 | measures.
174 |
175 | When you convey a covered work, you waive any legal power to forbid
176 | circumvention of technological measures to the extent such circumvention
177 | is effected by exercising rights under this License with respect to
178 | the covered work, and you disclaim any intention to limit operation or
179 | modification of the work as a means of enforcing, against the work's
180 | users, your or third parties' legal rights to forbid circumvention of
181 | technological measures.
182 |
183 | 4. Conveying Verbatim Copies.
184 |
185 | You may convey verbatim copies of the Program's source code as you
186 | receive it, in any medium, provided that you conspicuously and
187 | appropriately publish on each copy an appropriate copyright notice;
188 | keep intact all notices stating that this License and any
189 | non-permissive terms added in accord with section 7 apply to the code;
190 | keep intact all notices of the absence of any warranty; and give all
191 | recipients a copy of this License along with the Program.
192 |
193 | You may charge any price or no price for each copy that you convey,
194 | and you may offer support or warranty protection for a fee.
195 |
196 | 5. Conveying Modified Source Versions.
197 |
198 | You may convey a work based on the Program, or the modifications to
199 | produce it from the Program, in the form of source code under the
200 | terms of section 4, provided that you also meet all of these conditions:
201 |
202 | a) The work must carry prominent notices stating that you modified
203 | it, and giving a relevant date.
204 |
205 | b) The work must carry prominent notices stating that it is
206 | released under this License and any conditions added under section
207 | 7. This requirement modifies the requirement in section 4 to
208 | "keep intact all notices".
209 |
210 | c) You must license the entire work, as a whole, under this
211 | License to anyone who comes into possession of a copy. This
212 | License will therefore apply, along with any applicable section 7
213 | additional terms, to the whole of the work, and all its parts,
214 | regardless of how they are packaged. This License gives no
215 | permission to license the work in any other way, but it does not
216 | invalidate such permission if you have separately received it.
217 |
218 | d) If the work has interactive user interfaces, each must display
219 | Appropriate Legal Notices; however, if the Program has interactive
220 | interfaces that do not display Appropriate Legal Notices, your
221 | work need not make them do so.
222 |
223 | A compilation of a covered work with other separate and independent
224 | works, which are not by their nature extensions of the covered work,
225 | and which are not combined with it such as to form a larger program,
226 | in or on a volume of a storage or distribution medium, is called an
227 | "aggregate" if the compilation and its resulting copyright are not
228 | used to limit the access or legal rights of the compilation's users
229 | beyond what the individual works permit. Inclusion of a covered work
230 | in an aggregate does not cause this License to apply to the other
231 | parts of the aggregate.
232 |
233 | 6. Conveying Non-Source Forms.
234 |
235 | You may convey a covered work in object code form under the terms
236 | of sections 4 and 5, provided that you also convey the
237 | machine-readable Corresponding Source under the terms of this License,
238 | in one of these ways:
239 |
240 | a) Convey the object code in, or embodied in, a physical product
241 | (including a physical distribution medium), accompanied by the
242 | Corresponding Source fixed on a durable physical medium
243 | customarily used for software interchange.
244 |
245 | b) Convey the object code in, or embodied in, a physical product
246 | (including a physical distribution medium), accompanied by a
247 | written offer, valid for at least three years and valid for as
248 | long as you offer spare parts or customer support for that product
249 | model, to give anyone who possesses the object code either (1) a
250 | copy of the Corresponding Source for all the software in the
251 | product that is covered by this License, on a durable physical
252 | medium customarily used for software interchange, for a price no
253 | more than your reasonable cost of physically performing this
254 | conveying of source, or (2) access to copy the
255 | Corresponding Source from a network server at no charge.
256 |
257 | c) Convey individual copies of the object code with a copy of the
258 | written offer to provide the Corresponding Source. This
259 | alternative is allowed only occasionally and noncommercially, and
260 | only if you received the object code with such an offer, in accord
261 | with subsection 6b.
262 |
263 | d) Convey the object code by offering access from a designated
264 | place (gratis or for a charge), and offer equivalent access to the
265 | Corresponding Source in the same way through the same place at no
266 | further charge. You need not require recipients to copy the
267 | Corresponding Source along with the object code. If the place to
268 | copy the object code is a network server, the Corresponding Source
269 | may be on a different server (operated by you or a third party)
270 | that supports equivalent copying facilities, provided you maintain
271 | clear directions next to the object code saying where to find the
272 | Corresponding Source. Regardless of what server hosts the
273 | Corresponding Source, you remain obligated to ensure that it is
274 | available for as long as needed to satisfy these requirements.
275 |
276 | e) Convey the object code using peer-to-peer transmission, provided
277 | you inform other peers where the object code and Corresponding
278 | Source of the work are being offered to the general public at no
279 | charge under subsection 6d.
280 |
281 | A separable portion of the object code, whose source code is excluded
282 | from the Corresponding Source as a System Library, need not be
283 | included in conveying the object code work.
284 |
285 | A "User Product" is either (1) a "consumer product", which means any
286 | tangible personal property which is normally used for personal, family,
287 | or household purposes, or (2) anything designed or sold for incorporation
288 | into a dwelling. In determining whether a product is a consumer product,
289 | doubtful cases shall be resolved in favor of coverage. For a particular
290 | product received by a particular user, "normally used" refers to a
291 | typical or common use of that class of product, regardless of the status
292 | of the particular user or of the way in which the particular user
293 | actually uses, or expects or is expected to use, the product. A product
294 | is a consumer product regardless of whether the product has substantial
295 | commercial, industrial or non-consumer uses, unless such uses represent
296 | the only significant mode of use of the product.
297 |
298 | "Installation Information" for a User Product means any methods,
299 | procedures, authorization keys, or other information required to install
300 | and execute modified versions of a covered work in that User Product from
301 | a modified version of its Corresponding Source. The information must
302 | suffice to ensure that the continued functioning of the modified object
303 | code is in no case prevented or interfered with solely because
304 | modification has been made.
305 |
306 | If you convey an object code work under this section in, or with, or
307 | specifically for use in, a User Product, and the conveying occurs as
308 | part of a transaction in which the right of possession and use of the
309 | User Product is transferred to the recipient in perpetuity or for a
310 | fixed term (regardless of how the transaction is characterized), the
311 | Corresponding Source conveyed under this section must be accompanied
312 | by the Installation Information. But this requirement does not apply
313 | if neither you nor any third party retains the ability to install
314 | modified object code on the User Product (for example, the work has
315 | been installed in ROM).
316 |
317 | The requirement to provide Installation Information does not include a
318 | requirement to continue to provide support service, warranty, or updates
319 | for a work that has been modified or installed by the recipient, or for
320 | the User Product in which it has been modified or installed. Access to a
321 | network may be denied when the modification itself materially and
322 | adversely affects the operation of the network or violates the rules and
323 | protocols for communication across the network.
324 |
325 | Corresponding Source conveyed, and Installation Information provided,
326 | in accord with this section must be in a format that is publicly
327 | documented (and with an implementation available to the public in
328 | source code form), and must require no special password or key for
329 | unpacking, reading or copying.
330 |
331 | 7. Additional Terms.
332 |
333 | "Additional permissions" are terms that supplement the terms of this
334 | License by making exceptions from one or more of its conditions.
335 | Additional permissions that are applicable to the entire Program shall
336 | be treated as though they were included in this License, to the extent
337 | that they are valid under applicable law. If additional permissions
338 | apply only to part of the Program, that part may be used separately
339 | under those permissions, but the entire Program remains governed by
340 | this License without regard to the additional permissions.
341 |
342 | When you convey a copy of a covered work, you may at your option
343 | remove any additional permissions from that copy, or from any part of
344 | it. (Additional permissions may be written to require their own
345 | removal in certain cases when you modify the work.) You may place
346 | additional permissions on material, added by you to a covered work,
347 | for which you have or can give appropriate copyright permission.
348 |
349 | Notwithstanding any other provision of this License, for material you
350 | add to a covered work, you may (if authorized by the copyright holders of
351 | that material) supplement the terms of this License with terms:
352 |
353 | a) Disclaiming warranty or limiting liability differently from the
354 | terms of sections 15 and 16 of this License; or
355 |
356 | b) Requiring preservation of specified reasonable legal notices or
357 | author attributions in that material or in the Appropriate Legal
358 | Notices displayed by works containing it; or
359 |
360 | c) Prohibiting misrepresentation of the origin of that material, or
361 | requiring that modified versions of such material be marked in
362 | reasonable ways as different from the original version; or
363 |
364 | d) Limiting the use for publicity purposes of names of licensors or
365 | authors of the material; or
366 |
367 | e) Declining to grant rights under trademark law for use of some
368 | trade names, trademarks, or service marks; or
369 |
370 | f) Requiring indemnification of licensors and authors of that
371 | material by anyone who conveys the material (or modified versions of
372 | it) with contractual assumptions of liability to the recipient, for
373 | any liability that these contractual assumptions directly impose on
374 | those licensors and authors.
375 |
376 | All other non-permissive additional terms are considered "further
377 | restrictions" within the meaning of section 10. If the Program as you
378 | received it, or any part of it, contains a notice stating that it is
379 | governed by this License along with a term that is a further
380 | restriction, you may remove that term. If a license document contains
381 | a further restriction but permits relicensing or conveying under this
382 | License, you may add to a covered work material governed by the terms
383 | of that license document, provided that the further restriction does
384 | not survive such relicensing or conveying.
385 |
386 | If you add terms to a covered work in accord with this section, you
387 | must place, in the relevant source files, a statement of the
388 | additional terms that apply to those files, or a notice indicating
389 | where to find the applicable terms.
390 |
391 | Additional terms, permissive or non-permissive, may be stated in the
392 | form of a separately written license, or stated as exceptions;
393 | the above requirements apply either way.
394 |
395 | 8. Termination.
396 |
397 | You may not propagate or modify a covered work except as expressly
398 | provided under this License. Any attempt otherwise to propagate or
399 | modify it is void, and will automatically terminate your rights under
400 | this License (including any patent licenses granted under the third
401 | paragraph of section 11).
402 |
403 | However, if you cease all violation of this License, then your
404 | license from a particular copyright holder is reinstated (a)
405 | provisionally, unless and until the copyright holder explicitly and
406 | finally terminates your license, and (b) permanently, if the copyright
407 | holder fails to notify you of the violation by some reasonable means
408 | prior to 60 days after the cessation.
409 |
410 | Moreover, your license from a particular copyright holder is
411 | reinstated permanently if the copyright holder notifies you of the
412 | violation by some reasonable means, this is the first time you have
413 | received notice of violation of this License (for any work) from that
414 | copyright holder, and you cure the violation prior to 30 days after
415 | your receipt of the notice.
416 |
417 | Termination of your rights under this section does not terminate the
418 | licenses of parties who have received copies or rights from you under
419 | this License. If your rights have been terminated and not permanently
420 | reinstated, you do not qualify to receive new licenses for the same
421 | material under section 10.
422 |
423 | 9. Acceptance Not Required for Having Copies.
424 |
425 | You are not required to accept this License in order to receive or
426 | run a copy of the Program. Ancillary propagation of a covered work
427 | occurring solely as a consequence of using peer-to-peer transmission
428 | to receive a copy likewise does not require acceptance. However,
429 | nothing other than this License grants you permission to propagate or
430 | modify any covered work. These actions infringe copyright if you do
431 | not accept this License. Therefore, by modifying or propagating a
432 | covered work, you indicate your acceptance of this License to do so.
433 |
434 | 10. Automatic Licensing of Downstream Recipients.
435 |
436 | Each time you convey a covered work, the recipient automatically
437 | receives a license from the original licensors, to run, modify and
438 | propagate that work, subject to this License. You are not responsible
439 | for enforcing compliance by third parties with this License.
440 |
441 | An "entity transaction" is a transaction transferring control of an
442 | organization, or substantially all assets of one, or subdividing an
443 | organization, or merging organizations. If propagation of a covered
444 | work results from an entity transaction, each party to that
445 | transaction who receives a copy of the work also receives whatever
446 | licenses to the work the party's predecessor in interest had or could
447 | give under the previous paragraph, plus a right to possession of the
448 | Corresponding Source of the work from the predecessor in interest, if
449 | the predecessor has it or can get it with reasonable efforts.
450 |
451 | You may not impose any further restrictions on the exercise of the
452 | rights granted or affirmed under this License. For example, you may
453 | not impose a license fee, royalty, or other charge for exercise of
454 | rights granted under this License, and you may not initiate litigation
455 | (including a cross-claim or counterclaim in a lawsuit) alleging that
456 | any patent claim is infringed by making, using, selling, offering for
457 | sale, or importing the Program or any portion of it.
458 |
459 | 11. Patents.
460 |
461 | A "contributor" is a copyright holder who authorizes use under this
462 | License of the Program or a work on which the Program is based. The
463 | work thus licensed is called the contributor's "contributor version".
464 |
465 | A contributor's "essential patent claims" are all patent claims
466 | owned or controlled by the contributor, whether already acquired or
467 | hereafter acquired, that would be infringed by some manner, permitted
468 | by this License, of making, using, or selling its contributor version,
469 | but do not include claims that would be infringed only as a
470 | consequence of further modification of the contributor version. For
471 | purposes of this definition, "control" includes the right to grant
472 | patent sublicenses in a manner consistent with the requirements of
473 | this License.
474 |
475 | Each contributor grants you a non-exclusive, worldwide, royalty-free
476 | patent license under the contributor's essential patent claims, to
477 | make, use, sell, offer for sale, import and otherwise run, modify and
478 | propagate the contents of its contributor version.
479 |
480 | In the following three paragraphs, a "patent license" is any express
481 | agreement or commitment, however denominated, not to enforce a patent
482 | (such as an express permission to practice a patent or covenant not to
483 | sue for patent infringement). To "grant" such a patent license to a
484 | party means to make such an agreement or commitment not to enforce a
485 | patent against the party.
486 |
487 | If you convey a covered work, knowingly relying on a patent license,
488 | and the Corresponding Source of the work is not available for anyone
489 | to copy, free of charge and under the terms of this License, through a
490 | publicly available network server or other readily accessible means,
491 | then you must either (1) cause the Corresponding Source to be so
492 | available, or (2) arrange to deprive yourself of the benefit of the
493 | patent license for this particular work, or (3) arrange, in a manner
494 | consistent with the requirements of this License, to extend the patent
495 | license to downstream recipients. "Knowingly relying" means you have
496 | actual knowledge that, but for the patent license, your conveying the
497 | covered work in a country, or your recipient's use of the covered work
498 | in a country, would infringe one or more identifiable patents in that
499 | country that you have reason to believe are valid.
500 |
501 | If, pursuant to or in connection with a single transaction or
502 | arrangement, you convey, or propagate by procuring conveyance of, a
503 | covered work, and grant a patent license to some of the parties
504 | receiving the covered work authorizing them to use, propagate, modify
505 | or convey a specific copy of the covered work, then the patent license
506 | you grant is automatically extended to all recipients of the covered
507 | work and works based on it.
508 |
509 | A patent license is "discriminatory" if it does not include within
510 | the scope of its coverage, prohibits the exercise of, or is
511 | conditioned on the non-exercise of one or more of the rights that are
512 | specifically granted under this License. You may not convey a covered
513 | work if you are a party to an arrangement with a third party that is
514 | in the business of distributing software, under which you make payment
515 | to the third party based on the extent of your activity of conveying
516 | the work, and under which the third party grants, to any of the
517 | parties who would receive the covered work from you, a discriminatory
518 | patent license (a) in connection with copies of the covered work
519 | conveyed by you (or copies made from those copies), or (b) primarily
520 | for and in connection with specific products or compilations that
521 | contain the covered work, unless you entered into that arrangement,
522 | or that patent license was granted, prior to 28 March 2007.
523 |
524 | Nothing in this License shall be construed as excluding or limiting
525 | any implied license or other defenses to infringement that may
526 | otherwise be available to you under applicable patent law.
527 |
528 | 12. No Surrender of Others' Freedom.
529 |
530 | If conditions are imposed on you (whether by court order, agreement or
531 | otherwise) that contradict the conditions of this License, they do not
532 | excuse you from the conditions of this License. If you cannot convey a
533 | covered work so as to satisfy simultaneously your obligations under this
534 | License and any other pertinent obligations, then as a consequence you may
535 | not convey it at all. For example, if you agree to terms that obligate you
536 | to collect a royalty for further conveying from those to whom you convey
537 | the Program, the only way you could satisfy both those terms and this
538 | License would be to refrain entirely from conveying the Program.
539 |
540 | 13. Remote Network Interaction; Use with the GNU General Public License.
541 |
542 | Notwithstanding any other provision of this License, if you modify the
543 | Program, your modified version must prominently offer all users
544 | interacting with it remotely through a computer network (if your version
545 | supports such interaction) an opportunity to receive the Corresponding
546 | Source of your version by providing access to the Corresponding Source
547 | from a network server at no charge, through some standard or customary
548 | means of facilitating copying of software. This Corresponding Source
549 | shall include the Corresponding Source for any work covered by version 3
550 | of the GNU General Public License that is incorporated pursuant to the
551 | following paragraph.
552 |
553 | Notwithstanding any other provision of this License, you have
554 | permission to link or combine any covered work with a work licensed
555 | under version 3 of the GNU General Public License into a single
556 | combined work, and to convey the resulting work. The terms of this
557 | License will continue to apply to the part which is the covered work,
558 | but the work with which it is combined will remain governed by version
559 | 3 of the GNU General Public License.
560 |
561 | 14. Revised Versions of this License.
562 |
563 | The Free Software Foundation may publish revised and/or new versions of
564 | the GNU Affero General Public License from time to time. Such new versions
565 | will be similar in spirit to the present version, but may differ in detail to
566 | address new problems or concerns.
567 |
568 | Each version is given a distinguishing version number. If the
569 | Program specifies that a certain numbered version of the GNU Affero General
570 | Public License "or any later version" applies to it, you have the
571 | option of following the terms and conditions either of that numbered
572 | version or of any later version published by the Free Software
573 | Foundation. If the Program does not specify a version number of the
574 | GNU Affero General Public License, you may choose any version ever published
575 | by the Free Software Foundation.
576 |
577 | If the Program specifies that a proxy can decide which future
578 | versions of the GNU Affero General Public License can be used, that proxy's
579 | public statement of acceptance of a version permanently authorizes you
580 | to choose that version for the Program.
581 |
582 | Later license versions may give you additional or different
583 | permissions. However, no additional obligations are imposed on any
584 | author or copyright holder as a result of your choosing to follow a
585 | later version.
586 |
587 | 15. Disclaimer of Warranty.
588 |
589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
597 |
598 | 16. Limitation of Liability.
599 |
600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
608 | SUCH DAMAGES.
609 |
610 | 17. Interpretation of Sections 15 and 16.
611 |
612 | If the disclaimer of warranty and limitation of liability provided
613 | above cannot be given local legal effect according to their terms,
614 | reviewing courts shall apply local law that most closely approximates
615 | an absolute waiver of all civil liability in connection with the
616 | Program, unless a warranty or assumption of liability accompanies a
617 | copy of the Program in return for a fee.
618 |
619 | END OF TERMS AND CONDITIONS
620 |
621 | How to Apply These Terms to Your New Programs
622 |
623 | If you develop a new program, and you want it to be of the greatest
624 | possible use to the public, the best way to achieve this is to make it
625 | free software which everyone can redistribute and change under these terms.
626 |
627 | To do so, attach the following notices to the program. It is safest
628 | to attach them to the start of each source file to most effectively
629 | state the exclusion of warranty; and each file should have at least
630 | the "copyright" line and a pointer to where the full notice is found.
631 |
632 |
633 | Copyright (C)
634 |
635 | This program is free software: you can redistribute it and/or modify
636 | it under the terms of the GNU Affero General Public License as published by
637 | the Free Software Foundation, either version 3 of the License, or
638 | (at your option) any later version.
639 |
640 | This program is distributed in the hope that it will be useful,
641 | but WITHOUT ANY WARRANTY; without even the implied warranty of
642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
643 | GNU Affero General Public License for more details.
644 |
645 | You should have received a copy of the GNU Affero General Public License
646 | along with this program. If not, see .
647 |
648 | Also add information on how to contact you by electronic and paper mail.
649 |
650 | If your software can interact with users remotely through a computer
651 | network, you should also make sure that it provides a way for users to
652 | get its source. For example, if your program is a web application, its
653 | interface could display a "Source" link that leads users to an archive
654 | of the code. There are many ways you could offer source, and different
655 | solutions will be better for different programs; see section 13 for the
656 | specific requirements.
657 |
658 | You should also get your employer (if you work as a programmer) or school,
659 | if any, to sign a "copyright disclaimer" for the program, if necessary.
660 | For more information on this, and how to apply and follow the GNU AGPL, see
661 | .
662 |
--------------------------------------------------------------------------------